0
votes

I'm trying to hook into Windows' sizing events. I wrote the following hook:

__declspec(dllexport)
LRESULT CALLBACK HookProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
    MSG *msg = (MSG *)lParam;

    wchar_t text[1014];
    GetWindowText(msg->hwnd, text, 1024);

    if (wcscmp(text, L"Untitled - Notepad") == 0)
    {
        if (nCode == HCBT_MOVESIZE)
        {
            FILE *file;
            fopen_s(&file, "C:\\Users\\Me\\hooklog.txt", "a+");
            fprintf(file, "Move or size.\n");
            fclose(file);
        }
        else
        {
            FILE *file;
            fopen_s(&file, "C:\\Users\\Me\\hooklog.txt", "a+");
            fprintf(file, "Something else.\n");
            fclose(file);
        }
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

And I'm tring to install it using:

HHOOK hhk = SetWindowsHookEx(WH_CBT, hookProc, hModule, 0);
DWORD err = GetLastError();

The same technique works for other types of hooks, but fot WH_CBT is not working. All the variables (hookProc, hModule ad hhk after the call, and err is 0) involved have reasonable values and there are no signs of error. In the log file nothing shows up.

Working version

I had noticed that nCode usage depends on the type of hook, but I completely forgot to check the other parameters; as Hans noticed lParam doesn't point to a MSG for WH_CBT with nCode == HCBT_MOVESIZE; instead, lParam points to the new RECT and the HWND can be retrieved from wParam.

__declspec(dllexport)
LRESULT CALLBACK HookProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_MOVESIZE)
    {
        wchar_t text[1014];
        GetWindowText((HWND)wParam, text, 1024);

        if (wcscmp(text, L"Untitled - Notepad") == 0)
        {
            RECT *rect = (RECT *)lParam;

            FILE *file;
            fopen_s(&file, "C:\\Users\\Me\\hooklog.txt", "a+");
            fprintf(file, "Move or size (%d, %d, %d, %d) for target window.\n", rect->left, rect->right, rect->top, rect->bottom);
            fclose(file);
        }
        else
        {
            FILE *file;
            fopen_s(&file, "C:\\Users\\Me\\hooklog.txt", "a+");
            fprintf(file, "Move or size for some other window.\n");
            fclose(file);
        }
    }
    else
    {
        FILE *file;
        fopen_s(&file, "C:\\Users\\Me\\hooklog.txt", "a+");
        fprintf(file, "Something else.\n");
        fclose(file);
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
1
Installing a global hook to monitor just one window is overkill. Use an accessibility hook filtered to the thread that owns the window you care about.Raymond Chen
This will be very useful, I was wondering whether there was a way to be more selective, thanks! Just to make sure I understood, are you talking about SetWinEventHook and WinEvents ? I had seen those in the docs, but wasn't sure if they were good for my case or not.damix911
@damix911 yes, "accessibility hook filtered to the thread" implies SetWinEventHookmanuell

1 Answers

3
votes

Your assumption that the passed lParam is a pointer to a MSG is just wrong. Check the MSDN article for the callback, scroll to the bottom. You'll see that when nCode == HCBT_MOVESIZE then lParam is a pointer to RECT.

wParam gives you the handle to the window.

Code defensively, never ignore winapi function return values.