我注意到WinForms有很多方法可以处理命令或密钥(Process*()
)和(预)过滤系统的消息,但我们不清楚它们各自的用途。
官方文档有点模糊,我没有找到任何明确和完整的回复。
我谈到以下方法:
PreFilterMessage(ref Message m)
ProcessCmdKey(ref Message msg, Keys keyData)
WndProc(ref Message m)
ProcessDialogKey(Keys keyData)
PreProcessMessage(ref Message msg)
ProcessKeyMessage(ref Message m)
ProcessKeyPreview(ref Message m)
一些用于拦截键(如ProcessCmdKey
或ProcessDialogKey
),一些用于拦截消息(彼此)。但为什么有很多方法呢?他们的目的和用例是什么?
我认为每种方法的执行顺序都不同。
这是我所知道的(或者我认为知道):
PreFilterMessage
:首先拦截消息。您可以在此停止为以下所有方法分发消息!ProcessCmdKey
:拦截所有键,甚至组合键,特殊键和命令键。很好地检测整个表单上的关键快捷键(如Ctrl + D)。您可以在这里停止分发密钥。WndProc
:第二个在过滤后拦截消息?我只用它来检测用户是否点击右上方的“X”,但我想这可能是另一种方法!ProcessDialogKey
:仅截取一个密钥,可能在ProcessCmdKey
之后和所有密钥的控件事件之前。PreProcessMessage
:WndProc
之前和PreFilterMessage
之后?我不知道为什么要使用它。ProcessKeyMessage
:拦截关键信息。它似乎很少使用。ProcessKeyPreview
:在预览事件之前截取密钥?很少使用。深入,我认为这是正确的执行顺序:
为什么这么多步骤?
任何信息或具体用例都将受到赞赏!
答案 0 :(得分:10)
本机Windows GUI应用程序通常具有一个消息循环,基础winapi调用是GetMessage()。但是许多窗口获取消息,底层的winapi调用是DispatchMessage()。在您的.NET应用程序中,您只能调用Application.Run(),但有许多WndProc()方法,每个控件一个。其中大多数都隐藏在.NET Framework代码中,只有在覆盖它时才会公开。
通常需要挂钩到消息循环,在将消息分派给控件并到达WndProc()之前拦截消息。最明显的原因是键盘快捷键,无论哪个控件都有焦点,您都希望对它们采取行动。如果必须在每个控件上使用KeyDown来检测快捷方式,那当然会非常痛苦。不太明显的原因,例如,ActiveX控件因必须与其主机进行协商而着名。
Winforms提供很多的扩展点来拦截消息。实际上太多了,但有些不可避免的副作用是不想预测哪些情况下它们可能有用。按顺序:
尝试保持理智,始终覆盖ProcessCmdKey()以实现快捷键。覆盖IsInputKey()以让控件查看导航键。并且只覆盖WndProc()来自定义现有控件。