Menu

Proposal for CWinEventHookImpl

2021-03-11
2021-05-16
  • Bill Stevens

    Bill Stevens - 2021-03-11

    I came up with an ATL-style class (with some map macros) and thought I'd submit it here. It's for setting WinEvent hooks. My rough draft looks like this, but maybe you can improve it:

    template<typename T>
    class CWinEventHookImpl
    {
    public:
        CWinEventHookImpl() : m_hhook(NULL)
        {
        }
    
        virtual void ProcessWinEvent(DWORD dwEvent, HWND hwnd, LONG idObject,
                        LONG idChild, DWORD idEventThread, DWORD dwEventTime) = 0;
    
        HWINEVENTHOOK SetWinEventHook(DWORD dwEventMin, DWORD dwEventMax,
                        HMODULE hmodWinEventProc = _AtlBaseModule.GetModuleInstance(),
                        DWORD idProcess = GetCurrentProcessId(), DWORD idThread = GetCurrentThreadId(),
                        DWORD dwFlags = WINEVENT_INCONTEXT)
        {
            ATLASSERT(m_hhook == NULL);
            m_hhook = ::SetWinEventHook(dwEventMin, dwEventMax, hmodWinEventProc,
                            WinEventProc, idProcess, idThread, dwFlags);
    
            if (m_hhook)
                s_mapHooksToObjPtrs.SetAt(m_hhook, static_cast<T*>(this));
    
            return m_hhook;
        }
    
        BOOL UnhookWinEvent()
        {
            if (::UnhookWinEvent(m_hhook))
            {
                s_mapHooksToObjPtrs.RemoveKey(m_hhook);
                m_hhook = NULL;
                return TRUE;
            }
    
            return FALSE;
        }
    
    private:
        static void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD dwEvent, HWND hwnd,
                                LONG idObject, LONG idChild, DWORD idEventThread, DWORD dwEventTime)
        {
            T* pT;
            if (s_mapHooksToObjPtrs.Lookup(hWinEventHook, pT))
                pT->ProcessWinEvent(dwEvent, hwnd, idObject, idChild, idEventThread, dwEventTime);
        }
    
        static CAtlMap<HWINEVENTHOOK, T*> s_mapHooksToObjPtrs;
        HWINEVENTHOOK m_hhook;
    };
    
    template<typename T>
    CAtlMap<HWINEVENTHOOK, T*> CWinEventHookImpl<T>::s_mapHooksToObjPtrs;
    
    #define BEGIN_WINEVENT_MAP(theClass) \
    public: \
        void ProcessWinEvent(DWORD dwEvent, HWND hwnd, LONG idObject, \
            LONG idChild, DWORD idEventThread, DWORD dwEventTime) \
        { \
            switch(dwEvent) \
            { 
    
    #define WINEVENT_HANDLER(dwEvent, func) \
            case dwEvent: \
                return func(hwnd, idObject, idChild);
    
    #define END_WINEVENT_MAP() \
            } \
        }
    

    Thanks for any feedback.

     

    Last edit: Bill Stevens 2021-03-11
  • Paul Selormey

    Paul Selormey - 2021-04-24

    Hello Bill,
    Looking good but what is the real use of the s_mapHooksToObjPtrs object?

     
  • Bill Stevens

    Bill Stevens - 2021-04-25

    Well perhaps this can be accomplished without that object. But I think you need a way of accessing specific class instances within the static WinEventProc. The only thing WinEventProc gives you is hWinEventHook. So I just figured I'd create a map of hook handles to object pointers. But there's probably a better way. This ATL and Winapi stuff ties my brain in knots.

     
  • Paul Selormey

    Paul Selormey - 2021-05-16

    Hello Bill,
    It seems the ATL thunking class CStdCallThunk (not CWndProcThunk) can be used in this case too. Have you already looked into this?
    You may then have say, CWinEventHookRoot with the thunking and CWinEventHookImpl providing the non-static procedure, no virtual method.

     
  • Bill Stevens

    Bill Stevens - 2021-05-16

    I haven't really gotten into thunking yet. I'm pretty new to WinAPI and ATL. So I'd defer to you and other people on that.

    On another note, maybe it would be more useful to create a CUIAutomationEventHandlerImpl instead. UIAutomation is probably better than SetWinEventHook overall, and it wouldn't involve the static callback issues. But it would present challenges of its own in creating the map macros.

     

    Last edit: Bill Stevens 2021-05-16

Log in to post a comment.