创建自定义窗口调整大小功能

时间:2020-11-05 16:38:20

标签: c++ winapi

我正在尝试创建一种无边框,无标题且可调整大小的样式,而无需使用WS_THICKFRAMEWS_BORDERWS_SIZEBOX样式。

我不想使用这些样式,因为它们会产生边框,但更重要的是,当我使用SetWindowCompositionAttribute函数在窗口后面启用丙烯酸模糊效果时,由于某种原因,模糊效果超出了窗口image

我签出了this repo,目前正在使用他们的匹配测试逻辑。

所以从本质上讲,我认为我需要实现自己的调整大小能力,但是我不知道从哪里真正开始。

2 个答案:

答案 0 :(得分:2)

精确复制所有标准窗口大小调整行为有很多细微差别,但是您需要做的主要事情是实现自己的WM_NCHITTEST处理程序,该处理程序基本上会告诉Windows给定点位于窗口的哪个部分。

下面是一个示例,该示例允许通过自定义标题栏区域进行拖动,并通过拖动窗口的左,右和底部来调整大小。

#include <windows.h>
#include <tuple>
#include "windowsx.h"

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

    MSG msg = { 0 };
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = L"customwindowresizing";
    if (!RegisterClass(&wc))
        return 1;

    if (!CreateWindow(wc.lpszClassName,
        L"",
        WS_POPUP | WS_VISIBLE,
        0, 0, 640, 480, 0, 0, hInstance, NULL))
        return 2;

    while (GetMessage(&msg, NULL, 0, 0) > 0)
        DispatchMessage(&msg);

    return 0;
}

LRESULT HandleNonclientHitTest(HWND wnd, LPARAM lparam, int title_bar_hgt, int resizing_border_wd)
{
    RECT wnd_rect;
    GetWindowRect(wnd, &wnd_rect);

    int wd = wnd_rect.right - wnd_rect.left;
    int hgt = wnd_rect.bottom - wnd_rect.top;

    RECT title_bar = { 0,0, wd, title_bar_hgt };
    RECT left = { 0, title_bar_hgt , resizing_border_wd , hgt - title_bar_hgt - resizing_border_wd };
    RECT right = {wd - resizing_border_wd , title_bar_hgt , wd, hgt - title_bar_hgt - resizing_border_wd };
    RECT bottom = { 0, hgt - resizing_border_wd, wd, hgt };

    std::tuple<RECT, LRESULT> rects[] = {
        {title_bar, HTCAPTION},
        {left, HTLEFT},
        {right, HTRIGHT},
        {bottom, HTBOTTOM}
    };

    POINT pt = { GET_X_LPARAM(lparam) - wnd_rect.left, GET_Y_LPARAM(lparam) - wnd_rect.top };
    for (const auto& [r, code] : rects) {
        if (PtInRect(&r, pt))
            return code;
    }
    return HTCLIENT;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    switch (message)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    case WM_NCHITTEST:
        return HandleNonclientHitTest(hWnd, lParam, 25, 10);
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;

}

答案 1 :(得分:1)

所以本质上,我相信我需要实现自己的调整大小能力

实际上,您不是。如果只想通过窗口的右下角进行调整大小,则只需抓住WM_NCHITTEST并在鼠标位于您认为是调整大小手柄的窗口区域时返回HTGROWBOX即可。

还可以使用其他更复杂的WM_NCHITTEST返回值(包括使用户可以在屏幕上拖动窗口),但是您明白了。