我怎样才能添加一个WPF覆盖在一个外部的Win32应用程序的窗口?

我试图附加一个WPF窗口作为一个外部应用程序,如记事本的子窗口提供覆盖。 在研究了所有可以在SO和MSDN上find的答案之后,当我的WPF应用程序运行时,我已经在记事本的angular落创build了一个可靠的叠加层。 然而,

  • 只要记事本获得焦点,叠加消失,
  • 以及在记事本上显示的叠加层,叠加层也单独显示为一个窗口
  • 记事本上的叠加层不会收到任何MouseMove事件(但单独的窗口不会)。

这是演示这个问题的最简单的例子:

Overlay.xaml

<Window x:Class="WindowControlTest.Overlay" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300" Opacity="1" Background="Azure" MouseMove="Window_MouseMove" GotFocus="Window_GotFocus" Loaded="Window_Loaded" Title="Overlay" WindowStyle="None" > </Window> 

Overlay.xaml.cs

 using System; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Windows.Interop; namespace WindowControlTest { public partial class Overlay : Window { IntPtr m_ParentHwnd; HwndSource m_HwndSource; public Overlay(IntPtr parentHwnd) { InitializeComponent(); m_ParentHwnd = parentHwnd; } private void Window_MouseMove(object sender, MouseEventArgs e) { Console.WriteLine("Overlay.Window_MouseMove: " + e.GetPosition(this)); } private void Window_GotFocus(object sender, RoutedEventArgs e) { Console.WriteLine("Overlay.Window_GotFocus"); } private void Window_Loaded(object sender, RoutedEventArgs e) { HwndSourceParameters parameters = new HwndSourceParameters(); parameters.WindowStyle = (int) (WindowStyles.WS_VISIBLE | WindowStyles.WS_CHILD); parameters.SetPosition(0, 0); parameters.UsesPerPixelOpacity = true; parameters.SetSize((int)Width, (int)Height); parameters.ParentWindow = m_ParentHwnd; m_HwndSource = new HwndSource(parameters); m_HwndSource.CompositionTarget.BackgroundColor = Colors.Aqua; m_HwndSource.RootVisual = (Visual)Content; } } } 

MainWindow.xaml

 <Window x:Class="WindowControlTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Loaded="OnLoaded" > <StackPanel> <Label x:Name="stateLabel">Label</Label> </StackPanel> </Window> 

MainWindow.xaml.cs – 查找并处理记事本并创buildOverlay

 using System; using System.Text; using System.Windows; namespace WindowControlTest { public partial class MainWindow : Window { private IntPtr m_TargetHwnd; private Overlay m_Overlay; public MainWindow() { InitializeComponent(); } private void OnLoaded(object sender, RoutedEventArgs e) { processWindows(); if (m_TargetHwnd != IntPtr.Zero) { m_Overlay = new Overlay(m_TargetHwnd); m_Overlay.Show(); } } private void processWindows() { Win32.EnumWindows(delegate(IntPtr wnd, IntPtr param) { String text = GetWindowText(wnd); Console.WriteLine("Window: " + text); if (text.Contains("Notepad")) { m_TargetHwnd = wnd; } return true; }, IntPtr.Zero); } public static string GetWindowText(IntPtr hWnd) { int size = Win32.GetWindowTextLength(hWnd); if (size++ > 0) { var builder = new StringBuilder(size); Win32.GetWindowText(hWnd, builder, builder.Capacity); return builder.ToString(); } return String.Empty; } } } 

(注意:一些SO问题解决了一个类似但不同的问题,例如, 如何将Win32窗口设置为WPF窗口的所有者?假设我在控制Win32窗口的源代码,就像我可以在MSDN上find的例子 。)

Solutions Collecting From Web of "我怎样才能添加一个WPF覆盖在一个外部的Win32应用程序的窗口?"

我认为你走错了路,而不是让你的覆盖记事本窗口的孩子,你应该尝试通过HwndHost记事本的主窗口的孩子,然后保持覆盖主机上方。

这里是我的博客文章,介绍了我为WPF装饰器在由HwndHost托管的任何hwnd上分层编写的库 。 一个简单的网页浏览器演示如下所示:

快照http://img.zgserver.com/c%23/kej3bd.png