Windows截图.NET API因缩放问题异常:RDP下截图被截断
问题
使用以下代码可将当前窗口截图保存为Bitmap对象:
Function ScreenShotWindow() As Bitmap Dim bmpScreenshot As Bitmap = New Bitmap(Me.Width, Me.Height) Using g = Graphics.FromImage(bmpScreenshot) g.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, Me.Size) Return bmpScreenshot End Using End Function
(上述示例为简化重写版本,可能存在一两个语法错误)
该方法在本地控制台运行时正常,但通过RDP执行时,生成的位图比窗口小,底部和右侧内容缺失,截图被截断。推测需考虑缩放因素调整实现方式,相关参数均为像素值,但实际表现不符。已搜索缩放相关文档未找到有效信息,求助正确实现方案及参考文档方向。
正确实现方案
1. 适配RDP会话的DPI缩放逻辑
RDP会话中系统的DPI缩放会导致Me.Width/Height、Me.Location这类控件属性返回逻辑像素,而非屏幕实际物理像素,这是截图截断的核心原因。需要通过Win32 API获取窗口对应DPI,将逻辑单位转换为物理像素:
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll")> Private Shared Function GetDpiForWindow(hWnd As IntPtr) As Integer End Function <DllImport("gdi32.dll")> Private Shared Function MulDiv(nNumber As Integer, nNumerator As Integer, nDenominator As Integer) As Integer End Function Function ScreenShotWindow() As Bitmap Dim dpi As Integer = GetDpiForWindow(Me.Handle) ' 以96DPI为基准,将逻辑尺寸转换为物理像素 Dim physicalWidth As Integer = MulDiv(Me.Width, dpi, 96) Dim physicalHeight As Integer = MulDiv(Me.Height, dpi, 96) Dim physicalX As Integer = MulDiv(Me.Location.X, dpi, 96) Dim physicalY As Integer = MulDiv(Me.Location.Y, dpi, 96) Dim bmpScreenshot As New Bitmap(physicalWidth, physicalHeight) Using g = Graphics.FromImage(bmpScreenshot) g.DpiX = dpi g.DpiY = dpi g.CopyFromScreen(physicalX, physicalY, 0, 0, New Size(physicalWidth, physicalHeight)) Return bmpScreenshot End Using End Function End Class
2. 备选方案:用PrintWindow API直接捕获窗口内容
如果DPI转换仍有问题,可改用PrintWindow API,它直接从窗口绘制缓存中获取内容,不受RDP缩放影响:
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll")> Private Shared Function PrintWindow(hWnd As IntPtr, hdcBlt As IntPtr, nFlags As UInteger) As Boolean End Function Function ScreenShotWindow() As Bitmap Dim bmpScreenshot As New Bitmap(Me.Width, Me.Height) Using g = Graphics.FromImage(bmpScreenshot) Dim hdc As IntPtr = g.GetHdc() PrintWindow(Me.Handle, hdc, 0) g.ReleaseHdc(hdc) End Using Return bmpScreenshot End Function End Class
参考文档方向
- 微软官方Windows DPI缩放文档,重点理解逻辑像素与物理像素的转换规则
GetDpiForWindow、PrintWindow的Win32 API官方说明,掌握参数用法与适用场景- .NET WinForms高DPI适配官方指南,了解控件属性在不同DPI下的取值逻辑
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

