首页 > 解决方案 > 如何让 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;
}

标签: c#wpf

解决方案


下面是一个处理创建和销毁外部窗口的 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;
    }
}

推荐阅读