问题描述
我们正在开发WPF布局管理器有哪些可以由用户移动/调整大小的/ etc视口。视口通过,这是我们在布局管理器控制下,供应商通常填充数据(照片/电影/等)。我的工作是检查其是否也可以在视口中举办任何外部Windows应用程序(例如记事本,钙,Adobe Reader,请等)。我遇到了一些问题。
We are developing a layout manager in WPF that has viewports which can be moved/resized/etc by a user. Viewports are normally filled with data (pictures/movies/etc) via providers that are under our control in the layout manager. My job is to examine if its also possible to host any external Windows app (i.e. notepad, calc, adobe reader, etc) in a viewport. I encounter a number of problems.
大多数资源指向使用HwndHost类。我从微软自己本演练尝试:http://msdn.microsoft.com/en-us/library/ms752055.aspx
Most resources point to using the HwndHost class. I am experimenting with this walkthrough from Microsoft itself: http://msdn.microsoft.com/en-us/library/ms752055.aspx
我已经适应了这个让列表框被替换为窗口从外部应用程序处理。任何人都可以帮我带着这些问题:
I've adapted this so the list box is replaced with the windows handle from the external application. Can anybody help me out with these questions:
- 的演练增加,其中
的ListBox
被放在一个额外的静态子窗口。我不认为我需要外部的应用程序。如果我ommit它,我必须使外部应用程序的一个子窗口(使用GET / SetWindowLong函数从user32.dll中设置GWL_STYLE
为WS_CHILD
)。但是,如果我这样做,应用程序自败的菜单栏(因为WS_CHILD
风格),它不再接收输入。 - 如果我不使用子窗口,使外部应用程序的事情合理工作一个孩子,但有时外部应用程序不画确定。
- 另外,我需要的子窗口大小调整为视口。这可能吗?
- 当exernal应用程序产生一个子窗口(即Notepad->帮助 - >关于),这个窗口不被
HwndHost
(因此可以外移托管视口)。有没有什么办法可以prevent是什么? - 因为我需要的外部应用程序和布局管理器之间没有进一步的互动,我会就在假设我不需要捕捉和转发邮件? (演练增加了一个HwndSourceHook到子窗口赶在列表框中选择更改)。
- 当您运行(未修改)的例子VS2010和关闭窗口,VS2010并没有看到该程序结束。如果你打破一切,你在装配最终没有来源。臭的东西是怎么回事,但我不能找到它。
- 演练本身似乎是非常草率的$ C $的CD,但我还没有找到任何关于这一问题更好的文档。其他的例子吗?
- 另一种方法是不使用
HwndHost
,但WindowsFormHost
所讨论的here.它的工作原理(和简单得多!),但我没有在应用程序的大小控制?此外,WinFormHost是不是真的意味着这个?
- The walkthrough adds an extra static sub window in which the
ListBox
is placed. I don't think I need that for external apps. If I ommit it, I have to make the external app a child window (using Get/SetWindowLong from user32.dll to setGWL_STYLE
asWS_CHILD
). But if I do that, the menu bar of the app dissapears (because of theWS_CHILD
style) and it no longer receives input. - If I do use the sub window, and make the external app a child of that things work reasonably, but sometimes the external app does not paint ok.
- Also, I need the child window to resize to the viewport. Is this possible?
- When the exernal app spawns a child window (i.e. Notepad->Help->About), this window is not hosted by the
HwndHost
(and thus can be moved outside the viewport). Is there any way I can prevent that? - Since I need no further interaction between the external application and the layout manager, am I right in assuming I do not need to catch and forward messages? (the walkthrough adds a HwndSourceHook to the sub window to catch selection changes in the listbox).
- When you run the (unmodified) example VS2010 and close the window, VS2010 does not see that the program ended. If you break-all, you end up in assembly without source. Something smelly is going on, but I cannot find it.
- The walkthrough itself seems to be very sloppy coded, but I have not found any better documentation on this subject. Any other examples?
- Another approach is not to use
HwndHost
butWindowsFormHost
as discussed here. It works (and is much simpler!) but I do not have control over the size of the application? Also, WinFormHost is not really meant for this?
感谢在正确的方向的指针。
Thanks for any pointers in the right direction.
推荐答案
呃......如果这个问题已经提出类似20年前,一会回答,当然,看OLE'!,这里是什么是链接对象链接和嵌入
Well... if the question had been posed like 20 years ago, one would have answer, "Sure, look at 'OLE'!", here is a link to what is "Object Linking and Embedding":
http://en.wikipedia.org/wiki/Object_Linking_and_Embedding
如果你读这篇文章,你会看到接口的数量界定的规格,而不是因为它的作者觉得很有趣,而是因为它在技术上是难以实现的在一般情况下的
If you read this article, you will see the number of interfaces this spec defined, not because its author thought it was fun, but because it's technically difficult to achieve in the general cases
它实际上仍然被一些应用程序支持(主要是微软的人,因为微软几乎OLE的唯一赞助商......)
It's actually still supported by some apps (mostly Microsoft ones, as Microsoft was almost the only sponsor of OLE...)
您可以使用一种叫做DSOFramer(见链接在这里SO嵌入这些应用程序:MS KB311765和DsoFramer从微软的网站丢失),一个组件,让您的主机OLE服务器(即:外部应用运行的另一个进程)
目视内部的应用程序。这是一些大的黑客微软几年前让出,也就是不再支持到如此地步的二进制文件是很难找到!
You can embed these apps using something called DSOFramer (see links here on SO: MS KB311765 and DsoFramer are missing from MS site), a component that allows you to host OLE server (ie: external apps running as another process)visually inside an application. It's some kind of a big hack Microsoft let out a few years ago, that is not supported anymore to the point that the binaries are quite difficult to find!
据(5月)仍可以用于简单的OLE服务器,但我觉得我读的地方,它甚至不新的Microsoft应用程序,如Word 2010中工作。
所以,你可以使用DSOFramer应用程序支持它。你可以尝试一下。
It (may) still works for simple OLE servers, but I think I read somewhere it does not even work for new Microsoft applications such as Word 2010.So, you can use DSOFramer for application that support it. You can try it.
有关其他应用程序,那么,在今天,在现代世界,我们生活在,你不主持的应用的,跑了外部进程,您主持的组件的,并他们一般应该运行的制程的。
这就是为什么你将有很大的困难,做你想做的事的一般的东西。有一个问题,你将面对(而不是最少的最近版本的Windows)为安全:如何能的您的过程中,我不放心可以合法地处理的我的的窗口和菜单创建通过我的过程:-)?
For others applications, well, today, in the modern world we live in, you don't host applications, ran in external process, you host components, and they are in general supposed to run inprocess.That's why you will have great difficulties to do what you want to do in general. One problem you will face (and not the least with recent versions of Windows) is security: how can your process I don't trust can legitimately handle my windows and menus created by my process :-) ?
不过,你可以通过应用程序做了不少应用程序,使用各种Windows的黑客。
的setparent是基本上所有黑客的母亲: - )
Still, you can do quite a lot application by application, using various Windows hack.SetParent is basically the mother of all hacks :-)
下面是一块code的扩展你点样品,加入自动调整大小,并取消标题框。
它演示了如何隐含拆下控制箱,系统菜单,作为一个例子:
Here is a piece of code that extends the sample you point, adding automatic resize, and the removal of the caption box.It demonstrates how to implicitely remove the control box, the system menu, as an example:
public partial class Window1 : Window
{
private System.Windows.Forms.Panel _panel;
private Process _process;
public Window1()
{
InitializeComponent();
_panel = new System.Windows.Forms.Panel();
windowsFormsHost1.Child = _panel;
}
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
private void button1_Click(object sender, RoutedEventArgs e)
{
button1.Visibility = Visibility.Hidden;
ProcessStartInfo psi = new ProcessStartInfo("notepad.exe");
_process = Process.Start(psi);
_process.WaitForInputIdle();
SetParent(_process.MainWindowHandle, _panel.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
}
这基本上是所有的Windows传统的黑客。你也可以删除你不喜欢的项目菜单,如下解释:(如何删除从窗体的控制菜单框菜单项)。
This is basically all Windows "traditional" hacks. You could also remove item menus you don't like, as explained here: http://support.microsoft.com/kb/110393/en-us (How to Remove Menu Items from a Form's Control-Menu Box).
您也可以替换的notepad.exe的WINWORD.EXE,它的看起来的工作。但也有这种限制(键盘,鼠标,聚焦等)。
You can also replace "notepad.exe" by "winword.exe" and it seems to work. But there are limitations to this (keyboard, mouse, focus, etc.).
祝你好运!
这篇关于主办WPF窗口外部应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!