我有一个看起来像这样的例程,用伪代码:
while PeekMessage(Message, 0, 0, 0, PM_REMOVE)
HandleMessageAppropriately(Message)
基本上,它会通过并将所有消息拉出队列并调度它们。我不能改变这个例程。
我有一个这样的例程,如果它在某些条件下被调用,并且队列中有一条消息表示用户在错误的时刻点击了ESC
,它可能导致程序崩溃。 (得热爱种族条件。)
我无法更改上面的例程,但我可以更改调用它的代码。有没有什么方法可以在运行之前立即做一些事情,说“通过消息队列并删除用户点击ESC,的所有键盘输入消息,而不影响队列中的其余项目或更改他们的订单“?
答案 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。