• 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;
            }
        }
    }
  • 相关阅读:
    VirtualBox Linux服务vboxservicetemplate
    oracle 11g常用命令
    haproxy dataplaneapi
    使用jproflier 分析dremio
    cube.js 支持oceanbase 的mysql driver
    fastdfs 集群异常修复实践
    使用jHiccup 分析java 应用性能
    dremio mysql arp 扩展
    cube.js graphql 支持
    apache kyuubi 参考架构集成
  • 原文地址:https://www.cnblogs.com/xhubobo/p/12789466.html
Copyright © 2020-2023  润新知