我正在使用SetWinEventHook挂钩来检测对“编辑控件”的选择。在事件挂钩回调函数中,是否可以指定自定义数据?在我的情况下,自定义数据将是VKeyboard实例。

请参阅代码以更好地描述我要实现的目标。

class VKeyboard
{
public:
    static void CALLBACK winEventProc(HWINEVENTHOOK hWinEventHook, DWORD  event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
    {
        // Somehow access VKeyboard instance?
        VKeyboard* keyboard = ??;

        IAccessible* pAcc = NULL;
        VARIANT varChild;
        HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);

        if ((hr == S_OK) && (pAcc != NULL))
        {
            VARIANT varRole;
            hr = pAcc->get_accRole(varChild, &varRole);

            // if user selects a edit control: show window
            if ((hr == S_OK) && (varRole.vt == VT_I4) && (varRole.lVal == ROLE_SYSTEM_TEXT))
                ShowWindow(keyboard->mainHwnd, SW_SHOW);
            else ShowWindow(keyboard->mainHwnd, SW_HIDE);

            pAcc->Release();
        }
    }

    VKeyboard()
    {
        SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, NULL, (WINEVENTPROC)&winEventProc, 0, 0, WINEVENT_SKIPOWNPROCESS);


        SetWindowLongPtr (mainHwnd, GWLP_USERDATA, (LONG_PTR)this);
    }

    HWND mainHwnd;
}

最佳答案

由于您的挂钩回调是通过Out of Context hook实现的,因此即使在挂钩其他进程的事件时,也总是在调用SetWinEventHook()的线程的上下文中调用它。这样,您可以使用Thread Local Storage或什至仅使用全局变量来存储VKeyboard对象指针。前提是您只需要一个VKeyboard实例。

class VKeyboard
{
private:
    HWINEVENTHOOK hHook;
    static VKeyboard *pKeyboard;

    static void CALLBACK winEventProc(HWINEVENTHOOK hWinEventHook, DWORD  event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
    {
        IAccessible* pAcc = NULL;
        VARIANT varChild;
        HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);

        if ((hr == S_OK) && (pAcc != NULL))
        {
            VARIANT varRole;
            hr = pAcc->get_accRole(varChild, &varRole);

            // if user selects a edit control: show window
            if ((hr == S_OK) && (varRole.vt == VT_I4) && (varRole.lVal == ROLE_SYSTEM_TEXT))
                ShowWindow(pKeyboard->mainHwnd, SW_SHOW);
            else ShowWindow(pKeyboard->mainHwnd, SW_HIDE);

            pAcc->Release();
        }
    }

    VKeyboard()
    {
        hHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, NULL, &winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

        mainHwnd = ...;
        SetWindowLongPtr (mainHwnd, GWLP_USERDATA, (LONG_PTR)this);
        pKeyboard = this;
    }

    ~VKeyboard()
    {
        UnhookWinEvent(hHook);
        pKeyboard = NULL;
    }

    HWND mainHwnd;
};

07-24 13:59