c# - 如何让 WndProc 消息在 WPF 中工作?
问题描述
我正在尝试使用 WPF 制作任务栏应用程序,并且我需要能够对正在创建和销毁的窗口做出反应。在 winforms 中,这样做的一种方法是覆盖 WndProc 过程以便能够接收和处理 Windows 消息,我试图在 WPF 中做同样的事情。
在四处搜索并摆弄代码一周后,我就是无法让它工作。
我只在应用程序首次启动时收到一些消息,并且只有在打开新的资源管理器窗口时我可能会收到一些消息,尽管消息本身绝不是“创建窗口”消息。除此之外,无论我打开、切换或关闭多少个窗口,都不会调用 WndProc 函数。
我尝试遵循Getting Wndproc events to work with WPF中的答案?,来自如何在 WPF 中处理 WndProc 消息?,搜索结果中的其他几个网站以及此博客文章中描述的“MVVM-Compliant way”,该方法也在stackoverflow上的答案之一中引用。
无论如何,这应该有效,但它只是没有。我在两台运行 Windows 10 的不同计算机上进行了尝试,并且行为相同。WndPorc 只是没有被调用。
这是我尝试使用的一些代码以及压缩 VS 项目的链接:
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
// Or
// private void Window_Loaded(object sender, RoutedEventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
// Or
// HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
// source.AddHook(new HwndSourceHook(WndProc));
// Or
// HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(Application.Current.MainWindow).Handle);
// source.AddHook(new HwndSourceHook(WndProc));
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
System.Diagnostics.Debug.Write(string.Format("{0}; {1}; {2}; {3}; {4}",
hwnd.ToString(), msg, wParam, lParam, handled));
switch (wParam.ToInt32())
{
// For window created
case 1:
System.Diagnostics.Debug.Write(" window created");
break;
}
System.Diagnostics.Debug.WriteLine("");
return IntPtr.Zero;
}
解决方案
下面是一个处理创建和销毁外部窗口的 WPF 窗口示例:
public partial class MainWindow : Window
{
[DllImport("user32.dll", EntryPoint = "RegisterWindowMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int RegisterWindowMessage(string lpString);
[DllImport("user32.dll")]
public static extern bool RegisterShellHookWindow(IntPtr handle);
private static int _msg;
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
IntPtr handle = new WindowInteropHelper(this).Handle;
_msg = RegisterWindowMessage("SHELLHOOK");
RegisterShellHookWindow(handle);
HwndSource source = HwndSource.FromHwnd(handle);
source.AddHook(new HwndSourceHook(WndProc));
}
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == _msg)
{
switch (wParam.ToInt32())
{
case 1:
//window created
break;
case 2:
//window destroyed
break;
}
}
return IntPtr.Zero;
}
}
推荐阅读
- ruby-on-rails - 选择框不显示所选值
- python - 如何运行 gRPC 客户端来测试 tensorflow 模型?
- c# - C# 存储过程函数需要未提供的参数“@id”
- php - 数组未显示来自内爆结果的匹配项
- hadoop - 在 HIVE 表中生成唯一的 bigint 代理键
- oracle-apex - oracle apex 中的柱形图
- for-loop - 如何为回归循环编写本地宏
- javascript - Javascript 正则表达式替换捕获
- java - Eclipse / IntelliJ IDEA 上的 Maven 设置
- python - Python3 http.sever 无效语法