• C# 根据窗口句柄获取窗口截图


    本章介绍如何通过句柄,截取指定窗口内容,以及截取失败的场景

    一、根据窗口句柄获取窗口截图

    先创建一个测试窗口程序A,显示如下:

    同时我们把此窗口的句柄显示到一个文本输入框内。

    1     TestBox.Text = new WindowInteropHelper(this).Handle.ToString();

    如上图所示,1774674是此窗口的句柄值。

    然后,我们新建一个窗口程序B,对窗口A进行截图并展示

    1     var windowIntPtr = new IntPtr(1774674);
    2     var bitmapImage = GetWindowShotCut(windowIntPtr);
    3     TestImage.Source = bitmapImage;

    截图方法及详细操作如下:

    1     private BitmapImage GetWindowShotCut(IntPtr intPtr)
    2     {
    3         var image = WindowCaptureHelper.GetShotCutImage(intPtr);
    4         var bitmapImage = BitmapConveters.ConvertToBitmapImage(image);
    5         return bitmapImage;
    6     }

    WindowCaptureHelper:

     1     public class WindowCaptureHelper
     2     {
     3         [DllImport("user32.dll")]
     4         private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rectangle rect);
     5         [DllImport("gdi32.dll")]
     6         private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
     7         [DllImport("gdi32.dll")]
     8         private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
     9         [DllImport("gdi32.dll")]
    10         private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
    11         [DllImport("gdi32.dll")]
    12         private static extern int DeleteDC(IntPtr hdc);
    13         [DllImport("user32.dll")]
    14         private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, int nFlags);
    15         [DllImport("user32.dll")]
    16         private static extern IntPtr GetWindowDC(IntPtr hwnd);
    17 
    18         public static Bitmap GetShotCutImage(IntPtr hWnd)
    19         {
    20             var hscrdc = GetWindowDC(hWnd);
    21             var windowRect = new Rectangle();
    22             GetWindowRect(hWnd, ref windowRect);
    23             int width = Math.Abs(windowRect.Width- windowRect.X);
    24             int height = Math.Abs(windowRect.Height- windowRect.Y);
    25             var hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
    26             var hmemdc = CreateCompatibleDC(hscrdc);
    27             SelectObject(hmemdc, hbitmap);
    28             PrintWindow(hWnd, hmemdc, 0);
    29             var bmp = Image.FromHbitmap(hbitmap);
    30             DeleteDC(hscrdc);
    31             DeleteDC(hmemdc);
    32             return bmp;
    33         }
    34     }
    View Code

    BitmapConveters:

     1     public class BitmapConveters
     2     {
     3         [DllImport("gdi32")]
     4         static extern int DeleteObject(IntPtr o);
     5         public static BitmapSource ConvertToBitMapSource(Bitmap bitmap)
     6         {
     7             IntPtr intPtrl = bitmap.GetHbitmap();
     8             BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(intPtrl,
     9                 IntPtr.Zero,
    10                 Int32Rect.Empty,
    11                 BitmapSizeOptions.FromEmptyOptions());
    12             DeleteObject(intPtrl);
    13             return bitmapSource;
    14         }
    15         public static BitmapImage ConvertToBitmapImage(Bitmap bitmap)
    16         {
    17             using (MemoryStream stream = new MemoryStream())
    18             {
    19                 bitmap.Save(stream, ImageFormat.Bmp);
    20                 stream.Position = 0;
    21                 BitmapImage result = new BitmapImage();
    22                 result.BeginInit();
    23                 result.CacheOption = BitmapCacheOption.OnLoad;
    24                 result.StreamSource = stream;
    25                 result.EndInit();
    26                 result.Freeze();
    27                 return result;
    28             }
    29         }
    30     }
    View Code

    截图后显示如下:

     二、窗口截图失败

    窗口A在特定场景下,我们截到的窗口内容是黑色的:

    截图获取失败了,窗口A做了什么处理?

     定位发现是属性AllowsTransparency="True"的锅,搜索了下,网上也有同样的反馈:

    有个Issue在跟进:Screen capture semi-transparent windows? · Issue #334 · microsoft/WindowsCompositionSamples (github.com)

    官方大佬说,这是他们的一个BUG。在win10 2004更新版本中,已处理。

    不过,我现在是win11,依然还有问题。。。我是在win10上直接更新到win11,可能原来那个win10企业LTSC版本有点老,win11更新只更新了UI?或者win11是基于原来旧分支开发的?等回复中...Taking a screenshot of windows with AllowsTransparency="True" · Issue #358 · microsoft/WindowsCompositionSamples (github.com)

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    前后端分离下的自动化部署
    bouncy castle的配置
    列出本机JCE提供者,支持消息摘要算法,支持公钥私钥算法
    javaScript动态参数
    PKCS10生成证书csr
    未来编程语言---猜测
    html编辑网站
    java反编译工具JD-GUI
    java.lang.OutOfMemoryError: PermGen space
    修改idea的运行内存
  • 原文地址:https://www.cnblogs.com/kybs0/p/15768990.html
Copyright © 2020-2023  润新知