質問

I want to Hook a specific control (a combobox) and receive all keys typed in that control. The Combobox is part of an Outlook Ribbon an has no events like keypress or something (just onChange which behaves really weird).

Here is the Code:

    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private LowLevelKeyboardProc _proc;
    private IntPtr _hookID = IntPtr.Zero;

    private void SetHook(IntPtr handle)
    {
        uint PID; //not needed
        _proc = HookCallback;
        uint threadid = GetWindowThreadProcessId(handle, out PID);
        _hookID = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, IntPtr.Zero, threadid );

    }

    private delegate IntPtr LowLevelKeyboardProc(
            int nCode, IntPtr wParam, IntPtr lParam);

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            System.Diagnostics.Debug.WriteLine("Key: " + (Keys)vkCode);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

The handle i have and the ThreadID i get are correct (verified via Spy++) but no key is captured. Works fine with "0" as the last parameter of the SetWindowsHookEx function but then its a global hook ofcourse.

役に立ちましたか?

解決

I add this for anyone who has the same problem. Keyboardhooks are global, one cannot hook to a specific control. What you need to do is capture the messages of the given handle. To do so, you have to subclass your window/handle.

    [DllImport("user32")]
    private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
    [DllImport("user32")]
    private static extern int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam);

    // A delegate that matches Win32 WNDPROC:
    private delegate int Win32WndProc(IntPtr hWnd, int Msg, int wParam, int lParam);

    // from winuser.h:
    private const int GWL_WNDPROC = -4;
    private const int WM_KEYDOWN = 0x0100;

    // program variables
    private IntPtr oldWndProc = IntPtr.Zero;
    private Win32WndProc newWndProc = null;

    private void SubclassHWnd(IntPtr hWnd)
    {
        // hWnd is the window you want to subclass..., create a new 
        // delegate for the new wndproc
        newWndProc = new Win32WndProc(MyWndProc);
        // subclass
        oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, newWndProc);
    }

    private const int ENTER_KEY = 1835009;

    // this is the new wndproc, just show a messagebox on left button down:
    private int MyWndProc(IntPtr hWnd, int Msg, int wParam, int lParam)
    {

        switch (Msg)
        {
            case WM_KEYDOWN:
                int vkCode = lParam;
                if (vkCode == ENTER_KEY)
                    doSomething();
                return 0;

            default:
                break;
        }

        return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam);
    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top