Delphi技术问题:已设SetProcessDPIAware时缩放主窗口及XE6取色器截图
Delphi DPI感知后主窗口缩放与全屏截图优化
一、SetProcessDPIAware后如何缩放主应用窗口
刚调用SetProcessDPIAware开启进程DPI感知后,系统就不会再自动帮你缩放窗口和控件了——毕竟你告诉系统“我自己能处理高DPI”嘛。结合XE6的VCL特性,咱可以这么搞:
- 手动计算缩放比例调整控件:先拿当前DPI值,用
GetDeviceCaps(Canvas.Handle, LOGPIXELSX)获取横向DPI(纵向一般和横向一致),然后算出缩放比例Scale := CurrentDPI / 96(96是系统默认DPI)。接着在窗体的OnCreate事件里,遍历所有控件,把它们的Left、Top、Width、Height都乘以这个Scale,字体大小也按比例调。注意别重复缩放,可以加个标记位判断是否已经处理过。 - 试试VCL自带的ScaleForDPI:XE6虽然不像高版本Delphi那样有完善的高DPI支持,但也提供了
TForm.ScaleForDPI方法。你可以在窗体创建时,获取当前DPI,然后调用ScaleForDPI(DesignDPI, CurrentDPI)(DesignDPI就是你设计窗体时的DPI,一般是96)。不过这个方法对自定义控件或者第三方控件兼容性可能一般,得自己测测。 - 修正最大化/最小化的窗口尺寸:开了DPI感知后,窗体最大化可能会不对,这时候可以用
GetSystemMetricsForDPI(需要手动声明这个API,因为XE6的Windows单元可能没包含)来获取适配DPI后的屏幕尺寸,然后手动调整窗体的BoundsRect。
二、全屏截图代码优化(不再支持XP/Vista)
看了你贴的旧代码,确实有不少可以优化的地方,而且既然放弃了XP/Vista,咱可以用更简洁高效的实现,还能避免资源泄漏:
原始代码片段
var hDesktopWindow: THandle; DesktopCanvas: TCanvas; DeskRect, SourceRect: TRect; begin DesktopCanvas := TCanvas.Create; try hDesktopWindow := GetDesktopWindow; DesktopCanvas.Handle := GetDC(hDesktopWindow); try // 1. On XP/Vista De...的内容
优化后的完整实现
procedure CaptureFullScreen(ABitmap: TBitmap); var hDesktop: HWND; hDesktopDC: HDC; DesktopRect: TRect; begin // 先确保传入的位图对象不为空 Assert(ABitmap <> nil, 'CaptureFullScreen: Bitmap parameter cannot be nil'); // 获取桌面窗口句柄 hDesktop := GetDesktopWindow; // 获取桌面的实际像素尺寸(自动适配DPI) GetWindowRect(hDesktop, DesktopRect); // 获取桌面设备上下文 hDesktopDC := GetDC(hDesktop); try // 设置位图尺寸和桌面一致 ABitmap.SetSize(DesktopRect.Width, DesktopRect.Height); // 把桌面图像复制到位图上 BitBlt(ABitmap.Canvas.Handle, 0, 0, DesktopRect.Width, DesktopRect.Height, hDesktopDC, DesktopRect.Left, DesktopRect.Top, SRCCOPY); finally // 必须释放DC,否则会造成资源泄漏 ReleaseDC(hDesktop, hDesktopDC); end; end; // 使用示例 procedure TMainForm.btnCaptureClick(Sender: TObject); var FullScreenBmp: TBitmap; begin FullScreenBmp := TBitmap.Create; try CaptureFullScreen(FullScreenBmp); // 这里可以做你需要的操作,比如保存到文件 FullScreenBmp.SaveToFile('FullScreenCapture.png'); ShowMessage('截图已保存!'); finally FullScreenBmp.Free; end; end;
优化点说明
- 去掉了冗余的
TCanvas创建,直接复用传入的位图Canvas,减少内存开销 - 用
ReleaseDC正确释放获取的DC,解决了原始代码里的资源泄漏隐患 - 增加断言检查,提前发现参数错误,让代码更健壮
- 分离了截图逻辑和资源管理,代码更清晰,也方便复用
- 用
GetWindowRect获取真实的桌面尺寸,适配DPI感知后的屏幕像素
内容的提问来源于stack exchange,提问作者Vlastimil Burián
相关产品推荐
相关产品推荐

