vb.net - 如何制作表单后面窗口的屏幕截图?

标签 vb.net winforms winapi bitmap window

我的应用程序在 Google Chrome 窗口前运行。 Chrome 窗口的右侧四分之一始终可见,因为我可能需要与其交互。 Chrome 窗口的左侧被完全覆盖,因为这是我的控件所在的位置。

问题是,Chrome 窗口左侧有一些内容可能会不时发生变化,我需要知道这种情况何时发生。在我的表单上创建透明区域看起来真的很困惑,所以我需要做的是每隔几秒拍摄一张表单后面的 Chrome 窗口的图形,这样我就可以检查是否有任何差异。

我发现了许多使用 bitblt 等的代码示例,但到目前为止我得到的只是纯黑色。没有任何东西返回任何图像。那么如何拍摄 Chrome 窗口的图形呢?

如果有人可以提供一个从 hwnd 返回位图的函数,那就太棒了!

最佳答案

好吧,尝试一下PrintWindow

此函数发出 WM_PRINTWM_PRINTCLIENT 消息(取决于指定的标志),因此接收和处理该消息的窗口将其自身打印到 hDC 传入函数调用。
► 窗口可以被另一个窗口完全遮挡,没关系,这不是屏幕截图。不过,窗口必须处理该消息。


此处显示的静态(Shared)RenderWindow 方法返回由 PrintWindow 生成的 Bitmap 对象。功能。

您应该尝试将 True 作为 clientAreaOnly 参数传递,以将 PW_CLIENTONLY 设置为 nFlags 选项,因为许多 WPF 应用程序设计为隐藏默认窗口框架,而 WinForms Windows 通常不会,因此在这种情况下尝试传递 False

可选的 tryGetFullContent 参数设置 PW_RENDERFULLCONTENT 标志,该标志在 Windows 8.1+ 中可用。该标志没有记录。
更新:在这种情况下,这就是完成工作的原因。

要获得您关心的窗口的句柄,您有很多选择。

Process.GetProcessesByName("processName").FirstOrDefault(...)Process.GetProcessById(id)(如果您知道进程 ID)。

或者FindWindowEx ,或EnumWindows ,或EnumDesktopWindows ,取决于上下文。
参见这里:How to obtain task bar Notification Area width简单使用 FindWindowEx 函数。

假设您有一个 WinForms 应用程序,您可以调用如下方法,以在 PictureBox 中显示渲染窗口的位图:

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

Win32 RenderWindow 方法的声明和实现:

► 在这里,我使用 DwmGetWindowAttribute ,指定 DWMWA_EXTENDED_FRAME_BOUNDS 作为属性,以检索窗口矩形。
您还可以使用GetWindowRect ,但这个函数不是 DpiAware(而且有点旧:),在特定条件下它可能会返回错误的大小。

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

native 方法:

<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

关于vb.net - 如何制作表单后面窗口的屏幕截图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65315020/

相关文章:

c# - 如何在窗体中点击 "X",不会关闭而是隐藏

c# - 为什么我的窗口没有从我的线程更新?

使用 COM 端口/使用 USB 串行 COM 端口与 xbee 模块通信的 C# 程序

c# - 需要帮助打印列表中的多页

c++ - 无法在 Windows CE 中以编程方式卸载字体

c# - 如何将此 VB.net/C# 代码移植到 Objective-C/iOS?

vb.net - 如何查找项目中的警告总数?

c++ - 如何使用 CWindowImpl 类创建新窗口

vb.net - 当单元格内容被截断时,将三个点(省略号)(...)更改为 VB.Net DataGridView 中的自定义字符

c++ - 无法在 Windows 10 下关闭 OSK.exe