创建自定义窗口大小调整功能
Posted
技术标签:
【中文标题】创建自定义窗口大小调整功能【英文标题】:Create custom window resize functionality 【发布时间】:2020-11-05 16:38:20 【问题描述】:我正在尝试在不使用 WS_THICKFRAME
、WS_BORDER
和 WS_SIZEBOX
样式的情况下创建无边框、无标题和可调整大小。
我不想使用这些样式,因为它们会创建边框,但更重要的是,当我使用 SetWindowCompositionAttribute
函数在窗口后面启用丙烯酸模糊时,由于某种原因,模糊超出了窗口 @987654321 @。
我查看了this repo,目前正在使用他们的命中测试逻辑。
所以基本上我认为我需要实现自己的调整大小的能力,但我不知道从哪里真正开始。
【问题讨论】:
在使用SetWindowCompositionAttribute
(undocumented) 函数之前,希望你先阅读When programs grovel into undocumented structures…。无边框窗口可以参考the similar case。
谢谢,我会读的!我将重构以使用明显相似的记录在案的DwmSetWindowAttribute
函数。最初,由于我的风格标志,我在收听WM_NCHITTEST
时没有得到预期的行为。我现在已经解决了这个问题!
@StriveSun-MSFT 如果可以的话,我会给这个评论两票。
【参考方案1】:
准确复制所有标准窗口大小调整行为有很多细微差别,但您需要做的主要事情是实现自己的 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;
【讨论】:
【参考方案2】:所以基本上我认为我需要实现自己的调整大小的能力
实际上,你没有。如果您只想通过窗口的右下角调整大小,只需在鼠标位于您认为是调整大小句柄的窗口区域时捕捉WM_NCHITTEST
并返回HTGROWBOX
。
WM_NCHITTEST
的其他更复杂的返回值是可能的(包括使用户可以在屏幕上拖动窗口),但你明白了。
【讨论】:
不幸的是,如果我在窗口样式中包含WS_THICKFRAME
并且包含该标志会导致丙烯酸模糊模糊窗口,这似乎才有效
这让我很吃惊。我会仔细检查你的代码。如果操作正确,当您将鼠标悬停在调整大小手柄上时,您应该会看到光标变为调整大小箭头。此外,如果窗口设置了WS_CHILD
,它可能不起作用。
你是对的,我的窗口样式冲突阻止了调整大小的行为以上是关于创建自定义窗口大小调整功能的主要内容,如果未能解决你的问题,请参考以下文章
调整显示自定义字体大小的 MessageBox 窗口的大小?