Библиотека dll CBT Hook, чтобы предотвратить изменение размера окна

#c #winapi

Вопрос:

Я пытаюсь написать dll, чтобы предотвратить изменение размера окна, но я не могу понять, как правильно указать lParam в этом случае.

Из документов:

HCBT_MOVESIZE: Указывает длинный указатель на прямоугольную структуру, содержащую координаты окна. Изменяя значения в структуре, процедура привязки CBTProc может задать конечные координаты окна.

Текущий код:

 #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;
}
 

Ответ №1:

В случае HCBT_MOVESIZE , lParam содержит адрес памяти a 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;
}
 

Комментарии:

1. Как правильно переключаться между «событиями», и в случае, если ширина/высота окна будут отличаться от заданного значения, измените его размер обратно? Что у меня в банкомате: pastebin.com/mhuj8EE9 Размер окна не изменяется до нужной ширины/высоты, просто сбрасывается до ее первоначального размера.

2. В нем нет «событий» HCBT_MOVESIZE , это не говорит вам, ПОЧЕМУ окно перемещается/изменяется размер. EVENT_SYSTEM_MOVESIZESTART используется только с SetWinEventHook() , а не с SetWindowsHookEx() . В HCBT_MOVESIZE , все, что вы можете, это посмотреть на содержимое RECT , чтобы проверить, находится ли оно в нужном вам диапазоне, а если нет, то вы можете либо изменить содержимое RECT (вместо использования SetWindowPos() ) и return 0 принять изменения, либо return 1 вообще заблокировать перемещение/размер.

Ответ №2:

LPARAM-это значение размером с указатель. Он может содержать любое значение, которое помещается в указатель. Значение значения обычно зависит от контекста.

При обработке HCBT_MOVESIZE обратного вызова он обозначает

длинный указатель на ПРЯМУЮ структуру

Чтобы использовать его, клиентский код должен преобразовать значение в значение соответствующего типа. В C это делается с помощью приведения, например

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

// ...
}