C#使用BitBlt进行窗口抓图
时间:2020-04-27
本文章向大家介绍C#使用BitBlt进行窗口抓图,主要包括C#使用BitBlt进行窗口抓图使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文和C++使用BitBlt进行窗口抓图对应,使用C#实现。
1、Win32封装
Win32Consts
using System.ComponentModel; namespace CaptureSharp { public sealed class Win32Consts { public enum DibColorMode : uint { DIB_RGB_COLORS = 0x00, DIB_PAL_COLORS = 0x01, DIB_PAL_INDICES = 0x02 } public enum BitmapCompressionMode : uint { BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2, BI_BITFIELDS = 3, BI_JPEG = 4, BI_PNG = 5 } public enum RasterOperationMode : uint { SRCCOPY = 0x00CC0020, SRCPAINT = 0x00EE0086, SRCAND = 0x008800C6, SRCINVERT = 0x00660046, SRCERASE = 0x00440328, NOTSRCCOPY = 0x00330008, NOTSRCERASE = 0x001100A6, MERGECOPY = 0x00C000CA, MERGEPAINT = 0x00BB0226, PATCOPY = 0x00F00021, PATPAINT = 0x00FB0A09, PATINVERT = 0x005A0049, DSTINVERT = 0x00550009, BLACKNESS = 0x00000042, WHITENESS = 0x00FF0062, CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see wingdi.h) } public enum PrintWindowMode : uint { [Description( "Only the client area of the window is copied to hdcBlt. By default, the entire window is copied.")] PW_CLIENTONLY = 0x00000001, [Description("works on windows that use DirectX or DirectComposition")] PW_RENDERFULLCONTENT = 0x00000002 } } }
Win32Types
using System.Runtime.InteropServices; namespace CaptureSharp { public sealed class Win32Types { [StructLayout(LayoutKind.Sequential)] public struct Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } } [StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; //最左坐标 public int Top; //最上坐标 public int Right; //最右坐标 public int Bottom; //最下坐标 public int Width => Right - Left; public int Height => Bottom - Top; } [StructLayout(LayoutKind.Sequential, Pack = 2)] public struct BitmapFileHeader { public ushort bfType; public uint bfSize; public ushort bfReserved1; public ushort bfReserved2; public uint bfOffBits; } [StructLayout(LayoutKind.Sequential)] public struct BitmapInfoHeader { public uint biSize; public int biWidth; public int biHeight; public ushort biPlanes; public ushort biBitCount; public uint biCompression; public uint biSizeImage; public int biXPelsPerMeter; public int biYPelsPerMeter; public uint biClrUsed; public uint biClrImportant; public void Init() { biSize = (uint)Marshal.SizeOf(this); } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct RgbQuad { public byte rgbBlue; public byte rgbGreen; public byte rgbRed; public byte rgbReserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BitmapInfo { public BitmapInfoHeader bmiHeader; public RgbQuad bmiColors; } } }
Win32Funcs
using System; using System.Runtime.InteropServices; namespace CaptureSharp { public sealed class Win32Funcs { [DllImport("User32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out Win32Types.Rect lpRect); [DllImport("user32.dll")] public static extern bool GetClientRect(IntPtr hWnd, out Win32Types.Rect lpRect); [DllImport("user32.dll", EntryPoint = "GetWindowDC")] public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC(IntPtr hDc); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleBitmap(IntPtr hDc, int nWidth, int nHeight); [DllImport("gdi32.dll")] public static extern bool DeleteDC(IntPtr hDc); [DllImport("user32.dll")] public static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] public static extern IntPtr CreateDIBSection(IntPtr hdc, ref Win32Types.BitmapInfo bmi, uint usage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset); [DllImport("gdi32.dll")] public static extern IntPtr SelectObject(IntPtr hDc, IntPtr hObject); [DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); [DllImport("gdi32.dll", SetLastError = true)] public static extern bool BitBlt( IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, uint dwRop); [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); } }
2、DibCaptureHelper.cs
using System; namespace CaptureSharp { internal class DibCaptureHelper { public IntPtr BitmapPtr => _hBitmap; public Win32Types.BitmapInfo BitmapInfo => _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 IntPtr _bitsPtr = IntPtr.Zero; private Win32Types.BitmapInfo _bitmapInfo; private Win32Types.Rect _windowRect; private Win32Types.Rect _clientRect; private int _bmpDataSize; public bool Init(string windowName) { var handle = Win32Funcs.FindWindow(null, windowName); if (handle.Equals(IntPtr.Zero)) { return false; } return Init(handle); } public bool Init(IntPtr handle) { _hWnd = handle; //获取窗口大小 if (!Win32Funcs.GetWindowRect(_hWnd, out _windowRect) || !Win32Funcs.GetClientRect(_hWnd, out _clientRect)) { return false; } _bmpDataSize = _clientRect.Width * _clientRect.Height * 3; //位图信息 _bitmapInfo = new Win32Types.BitmapInfo {bmiHeader = new Win32Types.BitmapInfoHeader()}; _bitmapInfo.bmiHeader.Init(); _bitmapInfo.bmiHeader.biWidth = _clientRect.Width; _bitmapInfo.bmiHeader.biHeight = _clientRect.Height; _bitmapInfo.bmiHeader.biPlanes = 1; _bitmapInfo.bmiHeader.biBitCount = 24; _bitmapInfo.bmiHeader.biSizeImage = (uint) (_clientRect.Width * _clientRect.Height); _bitmapInfo.bmiHeader.biCompression = (uint) Win32Consts.BitmapCompressionMode.BI_RGB; _hScrDc = Win32Funcs.GetWindowDC(_hWnd); _hMemDc = Win32Funcs.CreateCompatibleDC(_hScrDc); _hBitmap = Win32Funcs.CreateDIBSection(_hMemDc, ref _bitmapInfo, (uint) Win32Consts.DibColorMode.DIB_RGB_COLORS, out _bitsPtr, IntPtr.Zero, 0); _hOldBitmap = Win32Funcs.SelectObject(_hMemDc, _hBitmap); return true; } 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; _bitsPtr = IntPtr.Zero; } public bool RefreshWindow() { var hWnd = _hWnd; Cleanup(); return Init(hWnd); } public bool ChangeWindowHandle(string windowName) { Cleanup(); return Init(windowName); } public bool ChangeWindowHandle(IntPtr handle) { Cleanup(); return Init(handle); } public IntPtr Capture() { if (_hBitmap.Equals(IntPtr.Zero) || _hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero)) { return IntPtr.Zero; } var ret = Win32Funcs.BitBlt( _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height, _hScrDc, 0, 0, (uint) Win32Consts.RasterOperationMode.SRCCOPY); return ret ? _bitsPtr : IntPtr.Zero; } public bool Capture(out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect rect) { bitsPtr = _bitsPtr; bufferSize = _bmpDataSize; rect = _clientRect; if (_hBitmap.Equals(IntPtr.Zero) || _hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero)) { return false; } var ret = Win32Funcs.BitBlt( _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height, _hScrDc, 0, 0, (uint) Win32Consts.RasterOperationMode.SRCCOPY); return ret; } } }
原文地址:https://www.cnblogs.com/xhubobo/p/12789466.html
- js的动态加载、缓存、更新以及复用(四)
- ajax的再次封装!(改进版) —— new与不 new 有啥区别?
- ajax的再次封装!
- 【自然框架】js版的QuickPager分页控件 V2.0
- 你的SQL语句放在了哪里?
- oclhashcat:离线hash密码破解工具官方文档(中文版)
- 如何动态加载js?
- 【自然框架】数据访问之精雕细琢(一)存储过程的参数
- 100w条记录分页,可以有多快?—— DataReader分页与SQL语句分页的对比测试(在线演示)
- Mimikatz小实验:黄金票据+dcsync
- 【自然框架】n级下拉列表框的原理
- 【自然框架】分享 n级联动下拉列表框
- GSM Hacking Part ②:使用SDR捕获GSM网络数据并解密
- 【自然框架】之数据访问 —— 再小的类库也需要设计。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 学习Vim合并行的方法和技巧
- 九种查找算法
- 代码防御性编程的十条技巧
- Ubuntu终端多窗口分屏Terminator
- linux 编译安装python3.6的教程详解
- Unix/Linux系统下的nobody用户与nologin详细介绍
- 详解flutter engine 那些没被释放的东西
- Centos7安装PHP及Nginx的教程详解
- Flutter Image实现图片加载
- Centos7系统下搭建.NET Core2.0+Nginx+Supervisor环境
- CentOS7 LNMP+phpmyadmin环境搭建 第二篇LNMP环境搭建教程
- 详解Linux 下开发微信小程序安装开发工具
- Linux一个增强的截图及分享工具:ScreenCloud
- linux 命名管道实例详解
- 11个JavaScript代码重构最佳实践