CBT Hook dll,拦截 window 调整大小

CBT Hook dll, to intercept window from being resized

我正在尝试编写一个 dll 来拦截 window 调整大小,但我无法理解在这种情况下如何正确指定 lParam。

来自docs

HCBT_MOVESIZE: Specifies a long pointer to a RECT structure containing the coordinates of the window. By changing the values in the structure, a CBTProc hook procedure can set the final coordinates of the window.

当前代码:

#include "pch.h"
#include <Windows.h>

extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
    _In_ int    nCode,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
    
    switch(nCode)
    {
    case HCBT_MOVESIZE: // A window is about to be moved or sized.

        /*
            For operations corresponding to the following CBT hook codes, the return value must be 0 to allow the operation, or 1 to prevent it.
            HCBT_ACTIVATE
            HCBT_CREATEWND
            HCBT_DESTROYWND
            HCBT_MINMAX
            HCBT_MOVESIZE
            HCBT_SETFOCUS
            HCBT_SYSCOMMAND
        */

        /*
        switch(LOWORD(lParam)) //
        {
        case EVENT_SYSTEM_MOVESIZESTART:
            return 1; // Prevent
        }
        */
    }
    return 0;
}

LPARAM 是指针大小的值。它可以保存适合指针的任何值。值的含义通常取决于上下文。

处理 HCBT_MOVESIZE callback 时,它指定

a long pointer to a RECT structure

要使用它,客户端代码需要将值转换为相应类型的值。在 C++ 中,这是使用强制转换完成的,例如

switch(nCode)
{
case HCBT_MOVESIZE: {
    auto pRect{ reinterpret_cast<RECT*>(lParam) };
    // Use `pRect` to read from or write to the rectangle
}
    break;

// ...
}

HCBT_MOVESIZE 的情况下,lParam 包含 RECT 的内存地址,因此只需将 lParam 类型转换为 RECT* 指针,例如:

extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
    _In_ int    nCode,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
    
    switch(nCode)
    {
        case HCBT_MOVESIZE: // A window is about to be moved or sized.
        {
            HWND hwnd = reinterpret_cast<HWND>(wParam);
            RECT *rc = reinterpret_cast<RECT*>(lParam);

            // use hwnd and *rc as needed...

            if (should not resize)
                return 1;

            break;
        }

        ...
    }

    return 0;
}