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 }
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 }
截图后显示如下:
二、窗口截图失败
窗口A在特定场景下,我们截到的窗口内容是黑色的:

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

定位发现是属性AllowsTransparency="True"的锅,搜索了下,网上也有同样的反馈:
- Taking a screenshot of windows with AllowsTransparency="True" (microsoft.com)
- c# - Capture transparent WPF Window for streaming - Stack Overflow
- .net - Transparent child window renders as black when screen sharing main window on Microsoft Teams - Stack Overflow
官方大佬说,这是他们的一个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)
C# 根据窗口句柄获取窗口截图的更多相关文章
- 根据获取的窗口句柄遍历窗口Edit控件
网上说遍历窗口控件有两种方法: 1),使用EnumChildWindows,没有深究, 学习网址如下:http://blog.sina.com.cn/s/blog_60ac1c4b010116 ...
- selenium常用操作,查找元素,操作Cookie,获取截图,获取窗口信息,切换,执行js代码
目录: 1. 常用操作 2. 查找元素 3. 操作Cookie 4. 获取截图 5. 获取窗口信息 6. 切换 7. 执行JS代码 简介 selenium.webdriver.remote.webdr ...
- C# 非顶端窗口截图 - 用于查找指定窗口并截图
原文地址:http://blog.csdn.net/u013096568/article/details/53400389 panel上可以通过DrawToBitmap截图,不管是否在屏幕外是否有遮挡 ...
- ATL中窗口句柄与窗口过程的关联方法
ATL中采用了一种动态生成机器指令的方式进行窗口句柄与窗口对象进行关联,以是详细分析: CWindowImpl会在第一次调用Create时注册窗口类,该窗口类是的信息是在CWindowImpl的子类中 ...
- C#获取窗口,模拟按键操作
C#获取窗口,模拟按键操作,实现计算器模拟操作.首先引用. using System.Runtime.InteropServices; 使用DllImport引入两个函数: // Get a hand ...
- (转载博文)MFC 窗口句柄获取
句柄获取方法(获取该窗口的句柄后,即可向该窗口类类发送消息.处理程序):0.获取所在类窗口的句柄: this->m_hwnd 1.主窗口的句柄: 无论在主窗口类内,还是子窗口类内,获取主窗口句柄 ...
- Ocr答题辅助神器 OcrAnswerer4.x,通过百度OCR识别手机文字,支持屏幕窗口截图和ADB安卓截图,支持四十个直播App,可保存题库
http://www.cnblogs.com/Charltsing/p/OcrAnswerer.html 联系qq:564955427 最新版为v4.1版,开放一定概率的八窗口体验功能,请截图体验(多 ...
- VC++的窗口句柄和窗口ID
原文地址:VC++的窗口句柄和窗口ID作者:放放 句柄是窗口资源的标识,它标识资源在系统中所占用的内存块,应用程序通过窗口句柄对窗口进行操作.除了窗口句柄之外,任何一种资源都有它自己的句柄,比如光标句 ...
- Selenium3 + Python3自动化测试系列十二——窗口截图与关闭浏览器
窗口截图 自动化用例是由程序去执行的,因此有时候打印的错误信息并不十分明确.如果在脚本执行出错的时候能对当前窗口截图保存,那么通过图片就可以非常直观地看出出错的原因.WebDriver提供了截图函数g ...
随机推荐
- FFT及NTT
FFT--快速傅里叶变换(附NTT--快速数论变换) FFT是一种能在O(nlogn)时空复杂度内求解两个函数卷积的优秀算法. 算法思想(DFT): 对于函数 \(f(x)=\Sigma_{i=0}^ ...
- lnmp重新安装mysql
安装mysql好长时间,一直没去管,后来一直频繁重启,各种网上找方案去解决,最后问题太异常,一顿操作猛如虎之后把mysql彻底搞垮,无奈只能进行重装. whereis mysql mysql: /us ...
- angularJS依赖注入的个人理解
依赖注入:一句话 --- 没事你不要来找我,有事我会去找你. AngularJS 5个核心组件用来作为依赖注入: value factory service provider constant ...
- 一个小数据库SQLite
参考 https://blog.csdn.net/csdnhsh/article/details/93376733 https://www.runoob.com/sqlite/sqlite-creat ...
- Python库之os库和logging库的基本使用说明
使用os库操作目录及文件 使用os.sep() 方法获取系统分隔符 print(os.sep) 使用os.name()方法获取操作系统的平台类型 print(os.name) 使用os.getcwd( ...
- 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商(2021年发布产品)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商(2021). 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量 ...
- 2.C/C++的const
1.C语言的const修饰的变量都有空间 2.C语言的const修饰的全局变量具有外部链接属性 3.C++语言的const修饰的变量有时有空间,有时没有空间(发生常量折叠,且没有对变量进行取址操作) ...
- 陈大好:持续创造小而美的产品丨独立开发者 x 开放麦
本文内容来自RTE NG-Lab 计划中「独立开发者 x 开放麦」活动分享,分享嘉宾独立开发者 @陈大好. 本次活动中,来自 W2solo 独立开发者社区的管理员 @Eric Woo 也以<独立 ...
- 使用Net将HTML简历导出为PDF格式
现在有许多将HTML导出PDF的第三方包,这里介绍使用的是Select.HtmlToPdf.NetCore 使用Select.HtmlToPdf.NetCore 整体思路是将cshtml内容读出来,然 ...
- Rainbond PipeLine插件部署与springboot应用部署实践
前言:上一篇介绍额rainbond单机部署+单个节点的k8s环境搭建,本篇介绍rainbond5.12新增的pipeline插件的使用 1.Pipeline插件的安装 安装gitlab与gitlab- ...