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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM