windowswinapihooksetwindowshookex

SetWindowsHookEx to determine when a window is deactivated


I have a global WH_CBT 32bit hook that I am using to determine when a window is about to be activated using HCBT_ACTIVATE.

How can I determine when the window is about to be deactivated? There is the CBTACTIVATESTRUCT which has hWndActive, but that is sometimes 0x0and it wont work when switching to a 64bit window.

There is no HCBT_DEACTIVATE.


Solution

  • As@Remy Lebeau mentioned, you can use WM_ACTIVATE message. This message is sent both when the window is activated or deactivated. Set a WH_CALLWNDPROC hook to capture the deactivated message, it will get the messages before the system sends them to the destination window procedure. For more detail:

    Use a function in a DLL for a non-local hook:

    #include <Windows.h>
    #include <stdio.h>
    
    LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
        HWND hwnd;
        //...
    
        DWORD threadID = GetWindowThreadProcessId(hwnd, NULL);
        HINSTANCE hinstDLL = LoadLibrary(TEXT("..\\Debug\\ProcHookDLL.dll"));
        void (*AttachHookProc)(DWORD);
        AttachHookProc = (void (*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook");
        AttachHookProc(threadID);
    
        MSG msg = {};
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
        //...
    };
    

    Here is the code for the DLL:

    #include <Windows.h>
    #include <stdio.h>
    
    HMODULE thisModule;
    HHOOK hook;
    LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam);
    
    #ifdef __cplusplus      // If used by C++ code, 
        extern "C" {        // we need to export the C interface
    #endif
        __declspec(dllexport) void AttachHook(DWORD threadID) {
            hook = SetWindowsHookEx(WH_CALLWNDPROC, LaunchListener, thisModule, threadID);
        }
    #ifdef __cplusplus
    }
    #endif
        LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam) {
            // process event here
            if (nCode >= 0) {
                CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
                if (cwp->message == WM_ACTIVATE) {
                    if (LOWORD(cwp->wParam) == WA_INACTIVE)
                    {
                        //the window being deactivated
                    }
                    else
                    {
                        //the window being activated
                    }
                }
            }
            return CallNextHookEx(NULL, nCode, wParam, lParam);
        }