.NET的SuppressKeypress如何/为什么工作?

[这个问题是关于WinAPI编程的核心]


.NET术语:

当Keydown事件在WinForms中触发时,您可以设置KeyEventArgs.SuppressKeypress = true ,然后后续的按键/字符不会发送到控件。

我发现下面的答案详细说明了控制如何使用SuppressKeyPress事件来阻止KeyUp事件

但是现在我不明白,这怎么能正常工作呢? 如果程序在其队列中build立了几个keydown消息,并且前几个让步,但最后一个使用上面的方法取消,则RemovePendingMessages函数不会从队列中删除所有字符,而不仅仅是最后一个?


在Windows API术语中:

考虑一个典型的消息循环来调用TranslateMessage来从键盘input中获取WM_CHAR消息。 在WM_KEYDOWN检查键是否被识别为一个命令,在这种情况下,它不应该产生一个字符。 怎么可能去除可能发送到消息队列的WM_CHAR消息,以有效地抑制按键? .NET中现有的解决scheme似乎使用循环的PeekMessage(.., WM_CHAR, WM_CHAR, PM_REMOVE)从队列中删除所有字符,但如果多个keydown消息在队列中不会删除太多的字符?

你的直觉是正确的,事实上,你所描述的事情是不正确的。 一些代码玩,看到这个错误:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } int keycnt = 0; protected override void OnKeyDown(KeyEventArgs e) { keycnt++; if (keycnt == 3) e.SuppressKeyPress = true; base.OnKeyDown(e); } protected override void OnKeyPress(KeyPressEventArgs e) { Debug.Print("Press {0}", e.KeyChar); base.OnKeyPress(e); } protected override void WndProc(ref Message m) { if (m.Msg >= 0x100 && m.Msg <= 0x109) Debug.WriteLine(m); base.WndProc(ref m); } [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern IntPtr PostMessage(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp); protected override void OnMouseClick(MouseEventArgs e) { for (int ix = 0; ix < 5; ++ix) { PostMessage(this.Handle, 0x100, (IntPtr)Keys.A, IntPtr.Zero); } } } 

点击表格触发测试。 请注意,OnKeyDown只能抑制第三次击键。 但是只有前两个通过,其余的都被吞下去了。

我从来没有见过有人抱怨过这个。