C#使用PrintWindow进行窗口抓图
本文和C++使用PrintWindow进行窗口抓图对应,使用C#实现。
Win32封装同C#使用BitBlt进行窗口抓图。
这种方式对1920*1080大小的窗口,一次抓图的时间参考(VS2015+i5 9400F):20~30ms(平均23ms)。
参见:C#抓图服务。
PrintCaptureHelper.cs
using System; namespace CaptureSharp { internal class PrintCaptureHelper { public IntPtr BitmapPtr => _hBitmap; public Win32Types.BitmapInfo BitmapInfo { get; } = new Win32Types.BitmapInfo(); public Win32Types.Rect WindowRect => _windowRect; public Win32Types.Rect ClientRect => _clientRect; public int BitmapDataSize => _bmpDataSize; private IntPtr _hWnd = IntPtr.Zero; private IntPtr _hScrDc = IntPtr.Zero; private IntPtr _hMemDc = IntPtr.Zero; private IntPtr _hBitmap = IntPtr.Zero; private IntPtr _hOldBitmap = IntPtr.Zero; private Win32Types.Rect _windowRect; private Win32Types.Rect _clientRect; private int _bmpDataSize; public bool Init(IntPtr handle) { _hWnd = handle; //获取窗口大小 if (!Win32Funcs.GetWindowRect(_hWnd, out _windowRect) || !Win32Funcs.GetClientRect(_hWnd, out _clientRect)) { return false; } _bmpDataSize = _windowRect.Width * _windowRect.Height * 3; _hScrDc = Win32Funcs.GetWindowDC(_hWnd); _hBitmap = Win32Funcs.CreateCompatibleBitmap(_hScrDc, _windowRect.Width, _windowRect.Height); _hMemDc = Win32Funcs.CreateCompatibleDC(_hScrDc); _hOldBitmap = Win32Funcs.SelectObject(_hMemDc, _hBitmap); return true; } public bool Init(string windowName) { var handle = Win32Funcs.FindWindow(null, windowName); if (handle.Equals(IntPtr.Zero)) { return false; } return Init(handle); } public void Cleanup() { if (_hBitmap.Equals(IntPtr.Zero)) { return; } //删除用过的对象 Win32Funcs.SelectObject(_hMemDc, _hOldBitmap); Win32Funcs.DeleteObject(_hBitmap); Win32Funcs.DeleteDC(_hMemDc); Win32Funcs.ReleaseDC(_hWnd, _hScrDc); _hWnd = IntPtr.Zero; _hScrDc = IntPtr.Zero; _hMemDc = IntPtr.Zero; _hBitmap = IntPtr.Zero; _hOldBitmap = IntPtr.Zero; } public bool RefreshWindow() { return ChangeWindowHandle(_hWnd); } public bool ChangeWindowHandle(string windowName) { Cleanup(); return Init(windowName); } public bool ChangeWindowHandle(IntPtr handle) { Cleanup(); return Init(handle); } public IntPtr Capture() { if (_hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero)) { return IntPtr.Zero; } var ret = Win32Funcs.PrintWindow(_hWnd, _hMemDc, (uint) Win32Consts.PrintWindowMode.PW_CLIENTONLY | (uint) Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT); return ret ? _hBitmap : IntPtr.Zero; } public bool Capture(out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect rect) { bitsPtr = _hBitmap; bufferSize = _bmpDataSize; rect = _clientRect; if (_hBitmap.Equals(IntPtr.Zero) || _hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero)) { return false; } var ret = Win32Funcs.PrintWindow(_hWnd, _hMemDc, (uint) Win32Consts.PrintWindowMode.PW_CLIENTONLY | (uint) Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT); return ret; } } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器