能否指定非正方形/矩形的自定义窗口非客户区(NC zone)?
多区域异形非客户区(NC Zone)实现方案
你需要组合WM_NCCALCSIZE、自定义区域计算、命中测试三个核心环节实现需求,具体操作如下:
具体实现步骤
- 第一步:处理
WM_NCCALCSIZE消息当
wParam为TRUE时,先获取NCCALCSIZE_PARAMS结构体中的新窗口矩形,先按默认规则调用DefWindowProc处理后,调整返回的客户区矩形,把你需要划入客户区的右上角空间预留出来。如果需要完全自定义NC区计算,也可以直接修改rgrc[0]字段自定义客户区的基础矩形范围。 - 第二步:构造自定义NC区的区域对象
自行创建
HRGN类型的区域对象,把你需要保留为NC区的所有独立区域(比如示例中的右侧下半段边缘、上下左边缘、标题栏区域等)分别用CreateRectRgn创建矩形区域,再通过CombineRgn接口把所有子区域合并成一个完整的NC区域。如果你的NC区有非矩形的形状,也可以用CreatePolygonRgn等接口创建对应形状的区域再合并。
针对你示例中的需求,只要在合并右侧边缘区域时,排除掉右上角需要划入客户区的矩形范围即可。 - 第三步:生效自定义区域
调用
SetWindowRgn接口把你合并完成的HRGN设置为当前窗口的区域,调用后系统会自动管理该区域的资源,不需要手动释放。 - 第四步:补充处理
WM_NCHITTEST消息这步是极易遗漏的必做项:即使你修改了窗口区域,系统默认的命中测试逻辑还是会按默认规则判定区域类型,你需要自己实现命中测试:判断鼠标坐标是否落在你自定义的NC区范围内,对应返回
HTCAPTION(可拖动标题栏)、HTTOP/HTLEFT/HTRIGHT(边缘拉伸)等NC区命中值,落在客户区范围则返回HTCLIENT即可。
注意事项
- 窗口大小发生变化(收到
WM_SIZE、WM_WINDOWPOSCHANGED消息)时,需要重新计算并设置NC区域,否则区域不会随窗口缩放自动适配。 - 如果程序开启了DPI感知,计算区域坐标时要按当前窗口的DPI缩放系数换算,避免高DPI场景下区域出现偏移。
- 如果不需要系统绘制默认的NC区样式,可以自行处理
WM_NCPAINT消息,自绘所有NC区的内容和你定义的区域匹配即可。
内容的提问来源于stack exchange,提问作者Younth
相关产品推荐
相关产品推荐

