过滤Windows消息队列

时间:2011-05-12 21:49:01

标签: windows winapi

我有一个看起来像这样的例程,用伪代码:

while PeekMessage(Message, 0, 0, 0, PM_REMOVE)
  HandleMessageAppropriately(Message)

基本上,它会通过并将所有消息拉出队列并调度它们。我不能改变这个例程。

我有一个这样的例程,如果它在某些条件下被调用,并且队列中有一条消息表示用户在错误的时刻点击了ESC,它可能导致程序崩溃。 (得热爱种族条件。)

我无法更改上面的例程,但我可以更改调用它的代码。有没有什么方法可以在运行之前立即做一些事情,说“通过消息队列并删除用户点击ESC,的所有键盘输入消息,而不影响队列中的其余项目或更改他们的订单“?

3 个答案:

答案 0 :(得分:3)

您可以使用PeekMessage中的范围参数仅限制WM_CHAR消息,如果字符不是ESC,则PM_NOREMOVE可以保留消息队列的完整性;如果需要删除该消息,请使用PM_REMOVE标志重复该过程。不幸的是,没有办法超越队列中的第一个WM_CHAR。

答案 1 :(得分:3)

这与臭名昭着的DoEvents调用完全相同,这让很多VB6程序员遇到了麻烦。因为ESC按键肯定会关闭一个窗口,让代码在没有用户界面的循环中运行。结果总是很差。

你不要乱用它,在进入这个循环之前调用EnableWindow(hWnd,FALSE)来禁用不应该关闭的窗口上的输入。现在你不再关心消息队列中的内容了。对话框完全相同。

不要在模态循环上书写。使其成为模态,也让用户明白。

答案 2 :(得分:0)

您可能最好挂钩对PeekMessages的调用,并将其替换为您所需的版本。

你可以使用madshi的钩子例程,但这并不难 - 我在Stack Overflow上发布了一个简单的钩子例程。

如果代码在您编译的可执行模块中运行,那么您可以编译替换PeekMessage的自定义版本的Windows.pas。当然我猜你的代码是Delphi。