C# 根据窗口句柄获取窗口截图
本文经原作者授权以原创方式二次分享,欢迎转载、分享。
C# 根据窗口句柄获取窗口截图
作者:唐宋元明清的博客
原文链接: https://www.cnblogs.com/kybs0/p/15768990.html
本章介绍如何通过句柄,截取指定窗口内容,以及截取失败的场景。
一、根据窗口句柄获取窗口截图
先创建一个测试窗口
程序A
,显示如下:
同时我们把此窗口的句柄显示到一个文本输入框内。
TestBox.Text = new WindowInteropHelper(this).Handle.ToString();
如上图所示,
1774674
是此窗口的句柄值。然后,我们新建一个窗口
程序B
,对窗口A
进行截图并展示。
var windowIntPtr = new IntPtr(1774674);
var bitmapImage = GetWindowShotCut(windowIntPtr);
TestImage.Source = bitmapImage;
截图方法及详细操作如下:
private BitmapImage GetWindowShotCut(IntPtr intPtr)
{
var image = WindowCaptureHelper.GetShotCutImage(intPtr);
var bitmapImage = BitmapConveters.ConvertToBitmapImage(image);
return bitmapImage;
}
WindowCaptureHelper
代码如下:
public class WindowCaptureHelper
{
[DllImport("user32.dll")]
private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rectangle rect);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
private static extern int DeleteDC(IntPtr hdc);
[DllImport("user32.dll")]
private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, int nFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
public static Bitmap GetShotCutImage(IntPtr hWnd)
{
var hscrdc = GetWindowDC(hWnd);
var windowRect = new Rectangle();
GetWindowRect(hWnd, ref windowRect);
int width = Math.Abs(windowRect.Width- windowRect.X);
int height = Math.Abs(windowRect.Height- windowRect.Y);
var hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
var hmemdc = CreateCompatibleDC(hscrdc);
SelectObject(hmemdc, hbitmap);
PrintWindow(hWnd, hmemdc, 0);
var bmp = Image.FromHbitmap(hbitmap);
DeleteDC(hscrdc);
DeleteDC(hmemdc);
return bmp;
}
}
BitmapConveters
:代码如下:
public class BitmapConveters
{
[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);
public static BitmapSource ConvertToBitMapSource(Bitmap bitmap)
{
IntPtr intPtrl = bitmap.GetHbitmap();
BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(intPtrl,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(intPtrl);
return bitmapSource;
}
public static BitmapImage ConvertToBitmapImage(Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
BitmapImage result = new BitmapImage();
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
}
截图后显示如下:
二、窗口截图失败
窗口A
在特定场景下,我们截到的窗口内容是黑色的:
截图获取失败了,
窗口A
做了什么处理?
定位发现是属性
AllowsTransparency="True"
的锅,搜索了下,网上也有同样的反馈:
Taking a screenshot of windows with AllowsTransparency="True" (microsoft.com)[1]
c# - Capture transparent WPF Window for streaming - Stack Overflow[2]
.net - Transparent child window renders as black when screen sharing main window on Microsoft Teams - Stack Overflow[3]
有个Issue在跟进: Screen capture semi-transparent windows? · Issue #334 · microsoft/WindowsCompositionSamples (github.com)[4]
官方大佬说,这是他们的一个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)[5]
github[6]
参考资料
[1]
Taking a screenshot of windows with AllowsTransparency=True: https://social.msdn.microsoft.com/Forums/office/en-US/3368f8f5-efb3-40cc-add5-f5311a74a954/taking-a-screenshot-of-windows-with-allowstransparencytrue
[2]c# - Capture transparent WPF Window for streaming - Stack Overflow: https://stackoverflow.com/questions/50888023/capture-transparent-wpf-window-for-streaming
[3].net - Transparent child window renders as black when screen sharing main window on Microsoft Teams - Stack Overflow: https://stackoverflow.com/questions/65514472/transparent-child-window-renders-as-black-when-screen-sharing-main-window-on-mic
[4]Screen capture semi-transparent windows? · Issue #334 · microsoft/WindowsCompositionSamples (github.com Screen capture semi-transparent windows? · Issue #334: https://github.com/microsoft/WindowsCompositionSamples/issues/334
[5]Taking a screenshot of windows with AllowsTransparency=True · Issue #358 ·: https://github.com/microsoft/WindowsCompositionSamples/issues/358
[6]github: https://github.com/Kybs0
技术群:添加小编微信并备注进群
小编微信:mm1552923
公众号:dotNet编程大全