使用DWM_WINDOW_CORNER_PREFERENCE后,Delphi工具窗口高度异常问题
Win11下调用SetRoundedCorners后工具提示窗口高度翻倍的问题解决
问题背景
我在Delphi中开发了一个无标题、无边框的小型工具提示窗口,FormCreate中的初始设置如下:
SetWindowLong(Application.Handle, GWL_EXSTYLE, GetWindowLong(Application.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW); BorderIcons := BorderIcons - [biMaximize];
原本通过CreateRoundRectRgn实现圆角,但边缘不够平滑;改用Win11原生的SetRoundedCorners辅助函数后,窗口高度变为原来的两倍且呈方形,需要排查问题成因并修复。
问题成因
- 窗口样式与DWM渲染冲突:Win11的DWM圆角API依赖标准窗口的非客户区渲染逻辑,而
无边框(bsNone)+WS_EX_TOOLWINDOW的组合会导致DWM错误计算窗口尺寸——系统默认会为标准窗口预留非客户区空间,无边框窗口无此区域,调用圆角API时会误将客户区高度叠加非客户区高度,造成窗口高度翻倍。 - 调用时机过早:在
FormCreate中调用SetRoundedCorners时,窗口尚未完成初始化,尺寸、样式等属性未完全确定,DWM无法正确识别窗口边界,引发渲染异常。 - 自定义区域干扰:残留的
CreateRoundRectRgn+SetWindowRgn代码会覆盖DWM的圆角处理逻辑,同时自定义区域会干扰DWM对窗口尺寸的判断。
解决方案
步骤1:清理冲突代码
移除原有的自定义圆角区域代码:
// 删除以下两行代码 RRShape := CreateRoundRectRgn(1, 1, Width - 1, height - 1, 100, 100); SetWindowRgn(Handle,RRShape,True);
步骤2:调整窗口样式与DWM渲染设置
在FormCreate中补充正确的窗口样式,并启用DWM非客户区渲染:
procedure TForm1.FormCreate(Sender: TObject); var NCRenderingPolicy: DWORD; begin // 给当前工具窗口设置扩展样式(而非Application主窗口) SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW); // 移除最大化按钮 BorderIcons := BorderIcons - [biMaximize]; // 设置无边框样式 BorderStyle := bsNone; // 启用DWM非客户区渲染,确保圆角功能生效 NCRenderingPolicy := DWMNCRP_ENABLED; DwmSetWindowAttribute(Handle, DWMWA_NCRENDERING_POLICY, @NCRenderingPolicy, SizeOf(NCRenderingPolicy)); end;
步骤3:延迟调用SetRoundedCorners
将圆角设置代码移到FormShow事件中,确保窗口完全初始化后再应用圆角:
procedure TForm1.FormShow(Sender: TObject); begin SetRoundedCorners(Self.Handle, RoundedCornerSmall); end;
额外注意事项
- 确保Delphi版本支持
Dwmapi单元(RAD Studio 10.3及以上版本通常自带),若版本较低需手动引入Dwmapi.dll的函数声明。 - Win11的原生圆角效果仅对顶层窗口生效,且需确保系统设置中未关闭圆角功能(设置>个性化>窗口>圆角)。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

