I have a WPF window which has to behave as an overlay of a window in a third-party running application. My WPF window must be mostly transparent with some visible controls, always be positioned right on top of the other window in the z-order, move with it, etc. In short: I want it to behave like a child window.
我有一个WPF窗口,它必须在第三方运行的应用程序中表现为窗口的叠加。我的WPF窗口必须大部分是透明的,带有一些可见的控件,总是位于z顺序的另一个窗口的顶部,随之移动等等。简而言之:我希望它的行为就像一个子窗口。
I have reviewed the techniques offered here (WPF HwndSource technique) and here (WPF SetParent technique). The HwndSource technique doesn't work at all. The SetParent technique works on Windows 7, but only with the basic theme. With Windows 7 Aero themes, it doesn't work: my child window is invisible.
我已经回顾了这里提供的技术(WPF HwndSource技术)和这里(WPF SetParent技术)。 HwndSource技术根本不起作用。 SetParent技术适用于Windows 7,但仅适用于基本主题。使用Windows 7 Aero主题时,它不起作用:我的子窗口是不可见的。
I am looking for a solution that will work on all Windows 7 themes.
我正在寻找一个适用于所有Windows 7主题的解决方案。
My test application creates a test window and calls SetParent to make it a child window of a (hard-coded HWND to) a Notepad window.
我的测试应用程序创建一个测试窗口并调用SetParent使其成为记事本窗口(硬编码的HWND)的子窗口。
Under the basic theme, it looks like so:
在基本主题下,它看起来像这样:
Under the Windows 7 theme, I don't see it:
在Windows 7主题下,我看不到它:
Child window XAML:
子窗口XAML:
<Window x:Class="WpfApplication22.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300" Background="#63000000" ShowInTaskbar="False" WindowStyle="None" Initialized="Window_Initialized" Loaded="Window_Loaded" AllowsTransparency="True">
<Grid>
<Ellipse Height="87" HorizontalAlignment="Left" Margin="12,12,0,0" Name="ellipse1" Stroke="Black" VerticalAlignment="Top" Width="167" Fill="#FFBE3A3A" />
</Grid>
</Window>
The child window form load handler code:
子窗口表单加载处理程序代码:
var parentHwnd = new IntPtr(0x01DE0DFC); // Running Notepad
var guestHandle = new WindowInteropHelper(this).Handle;
var style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_CHILD | WS_POPUP;
SetWindowLong(guestHandle, GWL_STYLE, (int)(style));
SetParent(guestHandle, parentHwnd);
(I've tried un-setting the WS_POPUP style. It has no effect.)
(我尝试取消设置WS_POPUP样式。它没有效果。)
1 个解决方案
#1
3
Instead of using SetParent, set WindowInteropHelper.Owner of your WPF "child" window to the window you want to display above.
不要使用SetParent,而是将WPF“子”窗口的WindowInteropHelper.Owner设置为要在上面显示的窗口。
Note that in .NET 3.5, if you do this in any of the "child" window's event handlers, even as early as OnSourceInitialized, the window owner doesn't really get set. Apparently it's too late to set an owner at that point.
请注意,在.NET 3.5中,如果您在任何“子”窗口的事件处理程序中执行此操作,即使早在OnSourceInitialized,窗口所有者也不会真正设置。显然,在那时设置所有者为时已晚。
Instead, set the Owner in the code that creates the window, before you call Show(). .NET 4 seems to allow setting the Owner from within SourceInitialized.
而是在调用Show()之前,在创建窗口的代码中设置所有者。 .NET 4似乎允许在SourceInitialized中设置所有者。
- Jack
- 插口
#1
3
Instead of using SetParent, set WindowInteropHelper.Owner of your WPF "child" window to the window you want to display above.
不要使用SetParent,而是将WPF“子”窗口的WindowInteropHelper.Owner设置为要在上面显示的窗口。
Note that in .NET 3.5, if you do this in any of the "child" window's event handlers, even as early as OnSourceInitialized, the window owner doesn't really get set. Apparently it's too late to set an owner at that point.
请注意,在.NET 3.5中,如果您在任何“子”窗口的事件处理程序中执行此操作,即使早在OnSourceInitialized,窗口所有者也不会真正设置。显然,在那时设置所有者为时已晚。
Instead, set the Owner in the code that creates the window, before you call Show(). .NET 4 seems to allow setting the Owner from within SourceInitialized.
而是在调用Show()之前,在创建窗口的代码中设置所有者。 .NET 4似乎允许在SourceInitialized中设置所有者。
- Jack
- 插口