Application.AddMessageFilter - 如何准确读取推送的键?

时间:2011-12-13 15:10:35

标签: c# winforms

我正在尝试Application.AddMessageFilter,使用最初由Somebody Else编写的一些代码,所以我不一定了解这里发生的所有事情。

这是代码的样子。在Main()

Application.AddMessageFilter(new KeyDownMessageFilter());

KeyDownMessageFilter

internal class KeyDownMessageFilter : IMessageFilter {
    private const int WM_KEYDOWN = 0x0100;

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            var k = (Keys)m.WParam;
            var c = (char)k;
            // and some other stuff
        }
        return false;
    }
}

我可以看到,通过将m.WParam转换为System.Windows.Forms.Keys类型的变量,然后将其转换为char,我可以看出键盘上的哪个键被推送了。到目前为止,非常好。

但是 - 我无法弄清楚如何区分 Shift ed键和没有 Shift 的键推 - 例如推产生字符'5'。更奇怪的是,看看k的价值,它看起来像是“LButton | MButton | ShiftKey | Space”(无论我是推 5 还是)。

关于此主题的MSDN文档相当薄。任何人都可以解释如何确切地说出推送的字符,以及奖励标记,解释这个Message对象应该是什么,以及为什么它使用诸如LParam和{{WParam之类的非描述属性1}}携带有用的信息?

2 个答案:

答案 0 :(得分:4)

  

e.g。推动"%"产生角色' 5'

按照设计,WM_KEYDOWN消息在wparam中传递虚拟密钥代码。生成'%'的密钥的虚拟密钥代码和' 5'是相同的,它是键盘上的相同键。在Windows处理WM_KEYDOWN消息并将其转换为WM_CHAR消息之前,它不会变成实际的输入键。这将检查Shift,Ctrl和Alt键的状态并相应地更改生成的字符。生成的实际字符取决于活动的键盘布局。

  

查看k的值,它显示为" LButton | MButton | ShiftKey |空间"

这是Keys类型的[Flags]属性的副作用。默认的Enum.ToString()方法检查该属性,并在该属性存在时将组合枚举值。 Keys.D5的整数值是0x35,0x01 + 0x04 + 0x10 + 0x20的组合。分别是Keys.LButton,MButton,ShiftKey和Space。显然,这在你的情况下是无用的,在监视表达式中转换为(int)。

嗯,这解释了发生了什么。您实际想要避免的一件事是尝试将虚拟密钥转换为自己的输入密钥。看看ToUnicodeEx() Windows api函数,您必须使用它来正确执行它。您可以使用Control.ModifierKeys属性来检测普通Keys.D5与使用Shift键按下的键之间的区别。

顺便说一句:你还应该捕获WM_SYSKEYDOWN,这是Alt键关闭时生成的消息。消息0x104。

答案 1 :(得分:0)

陷阱WM_CHAR,它已经被转换了,你应该收到%。