在WPF窗口中使用窗口消息接收键盘事件(HwndSource.AddHook)

时间:2015-10-13 11:17:02

标签: c# wpf wndproc keyboard-hook window-messages

我有一个带有TextBox的窗口。光标位于TextBox内。如果我按一个键,我会在WndProc中收到一条消息(对于KeyUp和KeyDown)。但是如果我在KeyUp和KeyDown事件中设置e.Handled = true,那么我没有收到任何关键信息:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var textBox = new TextBox();
        textBox.KeyDown += TextBox_KeyDown;
        textBox.KeyUp += TextBox_KeyUp;
        Content = textBox;
        (PresentationSource.FromVisual(this) as HwndSource).AddHook(WndProc);
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        e.Handled = true;
    }

    private void TextBox_KeyUp(object sender, KeyEventArgs e)
    {
        e.Handled = true;
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        Debug.WriteLine(msg + " " + wParam);
        return IntPtr.Zero;
    }
}

是否可以在WndProc中接收PreviewKeyDown / PreviewKeyUp事件?

2 个答案:

答案 0 :(得分:4)

有很多方法可以拦截关键信息。你甚至不需要任何库。使用纯Win32 API是可以的,但如果您想要简单,请尝试处理ThreadPreprocessMessage的{​​{1}}事件:

ComponentDispatcher

该事件能够在实际发送到您的窗口之前接收任何关键消息。因此,如果您想处理原始消息(而不是处理ComponentDispatcher.ThreadPreprocessMessage += (ref MSG m, ref bool handled) => { //check if WM_KEYDOWN, print some message to test it if (m.message == 0x100) { System.Diagnostics.Debug.Print("Key down!"); } }; ,...),那么这就是您想要的。

PreviewKeyDown方法允许为窗口添加一些钩子proc,但它在WPF中确实受到限制(而winforms中AddHook的{​​{1}}等效保护方法可以拦截更多的消息)

答案 1 :(得分:0)

尝试使用ManagedWinApi。您可以使用NuGet安装它。

PM> Install-Package ManagedWinapi

有关键盘和其他msg拦截的大量示例:http://mwinapi.sourceforge.net/

另一种选择是https://easyhook.github.io/

两个图书馆都有详细记录。