在 WPF 中接收带有 Window 消息的键盘事件-Window (HwndSource.AddHook)
Receive Keyboard Events with Window Messages in a WPF-Window (HwndSource.AddHook)
我有一个带有文本框的 Window。光标位于文本框内。如果我按下一个键,那么我会在 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 事件?
尝试使用 ManagedWinApi。您可以使用 NuGet 安装它。
PM> Install-Package ManagedWinapi
有关键盘和其他消息拦截的大量示例:http://mwinapi.sourceforge.net/
另一种选择是https://easyhook.github.io/
这两个库都有很好的文档记录。
拦截关键消息的方法有很多种。你甚至不需要任何图书馆。使用纯 Win32 API 是可以的,但如果您想要简单,请尝试处理 ComponentDispatcher
的 ThreadPreprocessMessage
事件:
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!");
}
};
事件能够在实际发送到您的 window 之前接收任何关键消息。所以在这种情况下,如果您想处理原始消息(而不是处理 PreviewKeyDown
, ...),这就是您想要的。
AddHook
方法允许为 window 添加一些 hook proc 但它在 WPF 中确实受到限制(而在 winforms 中等效 WndProc
受保护的 Form
方法可以拦截更多消息)。
我有一个带有文本框的 Window。光标位于文本框内。如果我按下一个键,那么我会在 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 事件?
尝试使用 ManagedWinApi。您可以使用 NuGet 安装它。
PM> Install-Package ManagedWinapi
有关键盘和其他消息拦截的大量示例:http://mwinapi.sourceforge.net/
另一种选择是https://easyhook.github.io/
这两个库都有很好的文档记录。
拦截关键消息的方法有很多种。你甚至不需要任何图书馆。使用纯 Win32 API 是可以的,但如果您想要简单,请尝试处理 ComponentDispatcher
的 ThreadPreprocessMessage
事件:
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!");
}
};
事件能够在实际发送到您的 window 之前接收任何关键消息。所以在这种情况下,如果您想处理原始消息(而不是处理 PreviewKeyDown
, ...),这就是您想要的。
AddHook
方法允许为 window 添加一些 hook proc 但它在 WPF 中确实受到限制(而在 winforms 中等效 WndProc
受保护的 Form
方法可以拦截更多消息)。