如何在我的表单后面制作 Window 的屏幕截图?
How can I make a screen shot of a Window behind my Form?
我的应用程序在 Google Chrome Window 前面运行。 chrome window 的右侧四分之一始终可见,因为我可能需要与之交互。 chrome window 的左侧完全被覆盖,因为这是我的控件所在的位置。
麻烦的是,Chrome Window 左侧有几项可能会不时更改,我需要知道何时会发生这种情况。在我的表格上制作透明区域看起来真的很乱,所以我需要做的是每隔几秒钟在我的表格后面拍摄 chrome window 的图形,这样我就可以检查是否有任何差异。
我发现了许多使用 bitblt
等的代码示例,但到目前为止,我得到的都是纯黑色。没有任何图像返回。那么如何才能拍出ChromeWindow的图呢?
如果有人可以提供 returns 来自 hwnd
的位图的功能,那就太棒了!
好吧,试试PrintWindow
。
此函数发出 WM_PRINT
或 WM_PRINTCLIENT
消息(取决于指定的标志),因此接收和处理消息的 Window 将自身打印到 hDC
传入函数调用。
► Window 可以完全被另一个遮住,没关系,不是截图。不过 Window 必须处理消息。
此处显示的是静态(Shared
)RenderWindow
方法,return是PrintWindow函数生成的Bitmap对象.
您应该尝试将 True
作为 clientAreaOnly
参数传递,以将 PW_CLIENTONLY
设置为 nFlags
选项,因为许多 WPF 应用程序旨在隐藏默认值Window 框架,而 WinForms Windows 通常不会,所以在这种情况下尝试通过 False
。
可选的 tryGetFullContent
参数设置 PW_RENDERFULLCONTENT
标志,可从 Windows 8.1+ 获得。此标志未记录。
更新:在这种情况下,这是完成工作的原因。
要得到你关心的Window的句柄,你有很多选择。
Process.GetProcessesByName("processName").FirstOrDefault(...)
或 Process.GetProcessById(id)
,如果您知道进程 ID。
或FindWindowEx, or EnumWindows, or EnumDesktopWindows,视情况而定。
请参阅此处: 了解 FindWindowEx
函数的简单用法。
假设您有一个 WinForms 应用程序,您可以像这样调用方法,以在 PictureBox 中显示呈现的 Window 的位图:
Dim proc = Process.GetProcessesByName("WINWORD").FirstOrDefault(Function(p) p.MainWindowHandle <> IntPtr.Zero)
If proc IsNot Nothing Then
PictureBox1.Image = RenderWindow(proc.MainWindowHandle, True)
End If
RenderWindow 方法的 Win32 声明和实现:
► 在这里,我使用 DwmGetWindowAttribute,指定 DWMWA_EXTENDED_FRAME_BOUNDS
作为属性,以检索 Window 矩形。
您也可以使用 GetWindowRect,但此功能不是 DpiAware(并且有点旧 :),在特定条件下可能 return 大小错误。
Public Shared Function RenderWindow(hWnd As IntPtr, clientAreaOnly As Boolean, Optional tryGetFullContent As Boolean = False) As Bitmap
Dim printOption = If(clientAreaOnly, PrintWindowOptions.PW_CLIENTONLY, PrintWindowOptions.PW_DEFAULT)
printOption = If(tryGetFullContent, PrintWindowOptions.PW_RENDERFULLCONTENT, printOption)
Dim dwmRect = New Rectangle()
Dim hResult = DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, dwmRect, Marshal.SizeOf(Of Rectangle)())
If hResult < 0 Then
Marshal.ThrowExceptionForHR(hResult)
Return Nothing
End If
Dim bmp = New Bitmap(dwmRect.Width, dwmRect.Height)
Using g = Graphics.FromImage(bmp)
Dim hDC = g.GetHdc()
Try
Dim success = PrintWindow(hWnd, hDC, printOption)
' success result not fully handled here
If Not success Then
Dim win32Error = Marshal.GetLastWin32Error()
Return Nothing
End If
Return bmp
Finally
g.ReleaseHdc(hDC)
End Try
End Using
End Function
本机方法:
<DllImport("user32.dll", SetLastError:=True)>
Friend Shared Function PrintWindow(hwnd As IntPtr, hDC As IntPtr, nFlags As UInteger) As Boolean
End Function
<DllImport("dwmapi.dll", SetLastError:=True)>
Friend Shared Function DwmGetWindowAttribute(hwnd As IntPtr, dwAttribute As DWMWINDOWATTRIBUTE, ByRef pvAttribute As Rectangle, cbAttribute As Integer) As Integer
End Function
Public Enum DWMWINDOWATTRIBUTE As UInteger
DWMWA_NCRENDERING_ENABLED = 1 ' [get] Is non-client rendering enabled/disabled
DWMWA_NCRENDERING_POLICY ' [set] DWMNCRENDERINGPOLICY - Non-client rendering policy
DWMWA_TRANSITIONS_FORCEDISABLED ' [set] Potentially enable/forcibly disable transitions
DWMWA_ALLOW_NCPAINT ' [set] Allow contents rendered In the non-client area To be visible On the DWM-drawn frame.
DWMWA_CAPTION_BUTTON_BOUNDS ' [get] Bounds Of the caption button area In window-relative space.
DWMWA_NONCLIENT_RTL_LAYOUT ' [set] Is non-client content RTL mirrored
DWMWA_FORCE_ICONIC_REPRESENTATION ' [set] Force this window To display iconic thumbnails.
DWMWA_FLIP3D_POLICY ' [set] Designates how Flip3D will treat the window.
DWMWA_EXTENDED_FRAME_BOUNDS ' [get] Gets the extended frame bounds rectangle In screen space
DWMWA_HAS_ICONIC_BITMAP ' [set] Indicates an available bitmap When there Is no better thumbnail representation.
DWMWA_DISALLOW_PEEK ' [set] Don't invoke Peek on the window.
DWMWA_EXCLUDED_FROM_PEEK ' [set] LivePreview exclusion information
DWMWA_CLOAK ' [set] Cloak Or uncloak the window
DWMWA_CLOAKED ' [get] Gets the cloaked state Of the window
DWMWA_FREEZE_REPRESENTATION ' [set] BOOL, Force this window To freeze the thumbnail without live update
DWMWA_LAST
End Enum
Public Enum PrintWindowOptions As UInteger
PW_DEFAULT = 0
PW_CLIENTONLY = 1
PW_RENDERFULLCONTENT = 2
End Enum
我的应用程序在 Google Chrome Window 前面运行。 chrome window 的右侧四分之一始终可见,因为我可能需要与之交互。 chrome window 的左侧完全被覆盖,因为这是我的控件所在的位置。
麻烦的是,Chrome Window 左侧有几项可能会不时更改,我需要知道何时会发生这种情况。在我的表格上制作透明区域看起来真的很乱,所以我需要做的是每隔几秒钟在我的表格后面拍摄 chrome window 的图形,这样我就可以检查是否有任何差异。
我发现了许多使用 bitblt
等的代码示例,但到目前为止,我得到的都是纯黑色。没有任何图像返回。那么如何才能拍出ChromeWindow的图呢?
如果有人可以提供 returns 来自 hwnd
的位图的功能,那就太棒了!
好吧,试试PrintWindow
。
此函数发出 WM_PRINT
或 WM_PRINTCLIENT
消息(取决于指定的标志),因此接收和处理消息的 Window 将自身打印到 hDC
传入函数调用。
► Window 可以完全被另一个遮住,没关系,不是截图。不过 Window 必须处理消息。
此处显示的是静态(Shared
)RenderWindow
方法,return是PrintWindow函数生成的Bitmap对象.
您应该尝试将 True
作为 clientAreaOnly
参数传递,以将 PW_CLIENTONLY
设置为 nFlags
选项,因为许多 WPF 应用程序旨在隐藏默认值Window 框架,而 WinForms Windows 通常不会,所以在这种情况下尝试通过 False
。
可选的 tryGetFullContent
参数设置 PW_RENDERFULLCONTENT
标志,可从 Windows 8.1+ 获得。此标志未记录。
更新:在这种情况下,这是完成工作的原因。
要得到你关心的Window的句柄,你有很多选择。
Process.GetProcessesByName("processName").FirstOrDefault(...)
或 Process.GetProcessById(id)
,如果您知道进程 ID。
或FindWindowEx, or EnumWindows, or EnumDesktopWindows,视情况而定。
请参阅此处:FindWindowEx
函数的简单用法。
假设您有一个 WinForms 应用程序,您可以像这样调用方法,以在 PictureBox 中显示呈现的 Window 的位图:
Dim proc = Process.GetProcessesByName("WINWORD").FirstOrDefault(Function(p) p.MainWindowHandle <> IntPtr.Zero)
If proc IsNot Nothing Then
PictureBox1.Image = RenderWindow(proc.MainWindowHandle, True)
End If
RenderWindow 方法的 Win32 声明和实现:
► 在这里,我使用 DwmGetWindowAttribute,指定 DWMWA_EXTENDED_FRAME_BOUNDS
作为属性,以检索 Window 矩形。
您也可以使用 GetWindowRect,但此功能不是 DpiAware(并且有点旧 :),在特定条件下可能 return 大小错误。
Public Shared Function RenderWindow(hWnd As IntPtr, clientAreaOnly As Boolean, Optional tryGetFullContent As Boolean = False) As Bitmap
Dim printOption = If(clientAreaOnly, PrintWindowOptions.PW_CLIENTONLY, PrintWindowOptions.PW_DEFAULT)
printOption = If(tryGetFullContent, PrintWindowOptions.PW_RENDERFULLCONTENT, printOption)
Dim dwmRect = New Rectangle()
Dim hResult = DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, dwmRect, Marshal.SizeOf(Of Rectangle)())
If hResult < 0 Then
Marshal.ThrowExceptionForHR(hResult)
Return Nothing
End If
Dim bmp = New Bitmap(dwmRect.Width, dwmRect.Height)
Using g = Graphics.FromImage(bmp)
Dim hDC = g.GetHdc()
Try
Dim success = PrintWindow(hWnd, hDC, printOption)
' success result not fully handled here
If Not success Then
Dim win32Error = Marshal.GetLastWin32Error()
Return Nothing
End If
Return bmp
Finally
g.ReleaseHdc(hDC)
End Try
End Using
End Function
本机方法:
<DllImport("user32.dll", SetLastError:=True)>
Friend Shared Function PrintWindow(hwnd As IntPtr, hDC As IntPtr, nFlags As UInteger) As Boolean
End Function
<DllImport("dwmapi.dll", SetLastError:=True)>
Friend Shared Function DwmGetWindowAttribute(hwnd As IntPtr, dwAttribute As DWMWINDOWATTRIBUTE, ByRef pvAttribute As Rectangle, cbAttribute As Integer) As Integer
End Function
Public Enum DWMWINDOWATTRIBUTE As UInteger
DWMWA_NCRENDERING_ENABLED = 1 ' [get] Is non-client rendering enabled/disabled
DWMWA_NCRENDERING_POLICY ' [set] DWMNCRENDERINGPOLICY - Non-client rendering policy
DWMWA_TRANSITIONS_FORCEDISABLED ' [set] Potentially enable/forcibly disable transitions
DWMWA_ALLOW_NCPAINT ' [set] Allow contents rendered In the non-client area To be visible On the DWM-drawn frame.
DWMWA_CAPTION_BUTTON_BOUNDS ' [get] Bounds Of the caption button area In window-relative space.
DWMWA_NONCLIENT_RTL_LAYOUT ' [set] Is non-client content RTL mirrored
DWMWA_FORCE_ICONIC_REPRESENTATION ' [set] Force this window To display iconic thumbnails.
DWMWA_FLIP3D_POLICY ' [set] Designates how Flip3D will treat the window.
DWMWA_EXTENDED_FRAME_BOUNDS ' [get] Gets the extended frame bounds rectangle In screen space
DWMWA_HAS_ICONIC_BITMAP ' [set] Indicates an available bitmap When there Is no better thumbnail representation.
DWMWA_DISALLOW_PEEK ' [set] Don't invoke Peek on the window.
DWMWA_EXCLUDED_FROM_PEEK ' [set] LivePreview exclusion information
DWMWA_CLOAK ' [set] Cloak Or uncloak the window
DWMWA_CLOAKED ' [get] Gets the cloaked state Of the window
DWMWA_FREEZE_REPRESENTATION ' [set] BOOL, Force this window To freeze the thumbnail without live update
DWMWA_LAST
End Enum
Public Enum PrintWindowOptions As UInteger
PW_DEFAULT = 0
PW_CLIENTONLY = 1
PW_RENDERFULLCONTENT = 2
End Enum