Control.ModifierKeys返回NONE

时间:2013-01-10 10:24:54

标签: c# winforms

我正在使用我从这个博客获得的课程: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        Console.WriteLine((Keys)vkCode);
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

这个函数获取单个键的密钥代码,我想改变它,所以我可以捕获ctrl + C所以我改变了上面的函数如下:

    private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if ((Keys)(vkCode) == Keys.C && (Control.ModifierKeys == Keys.Control))
    {
        int vkCode = Marshal.ReadInt32(lParam);
        Console.WriteLine((Keys)vkCode);
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

问题是Control.ModifierKeys总是返回NONE,我搜索任何结果太多了,我想要注意我在课程中使用此代码在解决方案的单独模块中。我在这做什么,请提供解决方案。

2 个答案:

答案 0 :(得分:1)

是的,这通常会出错,尤其是当您的程序本身没有GUI或使用隐藏窗口时。 Windows维护每个进程的键盘状态,在程序收到键盘消息时更新。这是必要的,因为键击存储在消息队列中并且稍后由程序检索,有时甚至更晚。键盘钩子的问题在于它是另一个获取消息的进程,而不是你的。你仍然有陈旧的键盘状态。

为了使其真正可靠,您需要知道其他进程的键盘状态。但这不是你可以得到的东西,GetKeyboardState()函数只允许检索你自己的状态。这通常使得将键击转换为键入键非常困难。 WH_KEYBOARD钩子是一个更好的解决方案,但你不能在C#中编写这样的钩子。

解决方法是自己跟踪Control键的状态。或者通过pinvoking GetAsyncKeyState()来检查Control键的实际无缓冲状态。

答案 1 :(得分:0)

这对你不起作用!

Control.ModifierKeys的实现只调用Windows API函数GetKeyState()三次,依次调用参数0x10,0x11和0x12,并适当地调整结果。

但是状态与正在处理来自消息队列的消息有关。

我认为您需要使用PInvoke来调用Windows API函数GetAsyncKeyState()