Обнаружение Ctrl + V с RegisterHotKey, но не перехватывает это - PullRequest
9 голосов
/ 27 июля 2011

Мне нужно определить, когда пользователь нажимает Ctrl + V (независимо от фокуса окна - мое приложение, вероятно, будет свернуто), но я не должен останавливать фактическую операцию вставки.

Я пробовал несколько вещей: (Я успешно связываю нажатия клавиш с помощью RegisterHotKey)

У меня есть:

protected override void WndProc(ref Message m)
{
  if (m.Msg == 0x312)
    hotKey();
  base.WndProc(ref m);
}

, и я попробовал следующее:

void hotKey()
{
  SendKeys.SendWait("^v"); //just puts 'v' instead of clipboard contents
}

и

void hotKey()
{
  SendKeys.SendWait(ClipBoard.GetText());
  /* This works, but since Ctrl is still down, it triggers
   * all the shortcut keys for the app, e.g. if the keyboard
   * contains 's' then instead of putting 's' in the app, it
   * calls Ctrl+S which makes the app think the user wants
   * to save.
   */
}

В настоящее время единственное рабочее решение, которое у меня есть, - это привязать к чему-то другому, например, Ctrl + B , а затем вызватьSendKeys.SendWait("^v"); однако это не идеально.

Идеальным решением было бы, если бы мое окно не перехватывало нажатие клавиши в первую очередь, просто реагировало.

1 Ответ

13 голосов
/ 27 июля 2011

Вы можете сделать это, используя хуки, используя SetWindowsHookEx ().

HHOOK WINAPI SetWindowsHookEx(
  __in  int idHook,
  __in  HOOKPROC lpfn,
  __in  HINSTANCE hMod,
  __in  DWORD dwThreadId
);

По сути, вы можете настроить низкоуровневый хук клавиатуры:

_hookHandle = SetWindowsHookEx(
    WH_KEYBOARD_LL,
    KbHookProc,                   // Your keyboard handler
    (IntPtr)0,
    0);                           // Set up system-wide hook.

для захвата общесистемных событий клавиатуры.Но это также позволяет передавать эти события клавиатуры другим приложениям.Для вашего конкретного случая вы можете определить KbHookProc как:

private static int KbHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0) // This means we can intercept the event.
    {
        var hookStruct = (KbLLHookStruct)Marshal.PtrToStructure(
                lParam,
                typeof(KbLLHookStruct));

        // Quick check if Ctrl key is down. 
        // See GetKeyState() doco for more info about the flags.
        bool ctrlDown = 
                GetKeyState(VK_LCONTROL) != 0 ||
                GetKeyState(VK_RCONTROL) != 0;

        if (ctrlDown && hookStruct.vkCode == 0x56) // Ctrl+V
        {
            // Replace this with your custom action.
            Clipboard.SetText("Hi");
        }
    }

    // Pass to other keyboard handlers. Makes the Ctrl+V pass through.
    return CallNextHookEx(_hookHandle, nCode, wParam, lParam);
} 

Я написал быстрое и грязное приложение WinForms, чтобы проиллюстрировать это.Полный список кодов см. http://pastebin.com/uCSvqwb4.

...