测试[C#]GDI+中使用BitBlt绘制图像到窗口

安神颗粒的哈喽

复制代码
### 2024-5-28 WindowsFormPaint FormTES_ESEB 测试[C#]GDI+中使用BitBlt绘制图像到窗口
```
#region 测试[C#]GDI+中使用BitBlt绘制图像到窗口
        private void pbx01_Paint(object sender, PaintEventArgs e)
        {
            #region MyRegion
            //using (Bitmap bp = new Bitmap("1234.png"))
            ////using (Bitmap bp =  (Bitmap)Bitmap.FromFile("123.png"))
            //{
            //    using (var mHdcGraphics = Graphics.FromHwnd(pbx01.Handle))//主设备
            //    {
            //        using (var aHdcGraphics = Graphics.FromImage(bp))//辅助设备
            //        {
            //            //var mHdc = mHdcGraphics.GetHdc();
            //            //var aHdc = aHdcGraphics.GetHdc();
            //            ////BitBlt(mHdc,0,0,pbx01.Width,pbx01.Height, aHdc, 0,0, (uint)TernaryRasterOperations.SRCCOPY); // 0x00CC0020 
            //            ////BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, 0x00CC0020); // 0x00CC0020 
            //            //BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, (uint)RasterOperationMode.SRCCOPY); // 0x00CC0020 
            //            //mHdcGraphics.ReleaseHdc(mHdc);
            //            //aHdcGraphics.ReleaseHdc(aHdc);

            //            //也就是说,在BitBlt之前,先将和Graphics有联系的Bitmap选作DC的背景图。
            //            //猜测,使用Graphics.FromImage的时候,.Net底层并没有将Bitmap对应的HBitmap选入HDC而只是将两个.Net对象联系起来了,而后在DrawImage中有两次SelectObject分别选入和选出以在HBitmap上绘图。所以独立于.Net进行GDI操作的时候,需要在GDI层面再将两者联系起来,使用SelectObject。


            //            //下面解决方式如下
            //            var mHdc = mHdcGraphics.GetHdc();
            //            var auxiliaryHdc = aHdcGraphics.GetHdc();

            //            var hbitmap = bp.GetHbitmap();
            //            var holdObject = SelectObject(auxiliaryHdc, hbitmap);
            //            if (holdObject != IntPtr.Zero)
            //            {
            //                //BitBlt(mHdc,0,0,pbx01.Width,pbx01.Height, aHdc, 0,0, (uint)TernaryRasterOperations.SRCCOPY); // 0x00CC0020 
            //                //BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, 0x00CC0020); // 0x00CC0020 
            //                bool result = BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, auxiliaryHdc, 0, 0, (uint)RasterOperationMode.SRCCOPY); // 0x00CC0020 
            //                if (result)
            //                {
            //                    TraceLog($"[C#]GDI+中使用BitBlt绘制图像到窗口 成功:{result}");
            //                }
            //                else
            //                {
            //                    TraceLog($"[C#]GDI+中使用BitBlt绘制图像到窗口 失败:{result}");
            //                }
            //            }
            //            //pbx01.Refresh();
            //            //释放资源
            //            DeleteObject(hbitmap);
            //            mHdcGraphics.ReleaseHdc(mHdc);
            //            aHdcGraphics.ReleaseHdc(auxiliaryHdc);

            //        }
            //    }
            //} 
            #endregion
        }

        private void btnTestGDI_Click(object sender, EventArgs e)
        {
            //pbx01.Invalidate();
            //pbx01.Update();
            //pbx01.Refresh();

            using (Bitmap bp = new Bitmap("1234.png"))
            //using (Bitmap bp =  (Bitmap)Bitmap.FromFile("123.png"))
            {
                using (var mHdcGraphics = Graphics.FromHwnd(pbx01.Handle))//主设备
                {
                    using (var aHdcGraphics = Graphics.FromImage(bp))//辅助设备
                    {
                        //var mHdc = mHdcGraphics.GetHdc();
                        //var aHdc = aHdcGraphics.GetHdc();
                        ////BitBlt(mHdc,0,0,pbx01.Width,pbx01.Height, aHdc, 0,0, (uint)TernaryRasterOperations.SRCCOPY); // 0x00CC0020 
                        ////BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, 0x00CC0020); // 0x00CC0020 
                        //BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, (uint)RasterOperationMode.SRCCOPY); // 0x00CC0020 
                        //mHdcGraphics.ReleaseHdc(mHdc);
                        //aHdcGraphics.ReleaseHdc(aHdc);

                        //也就是说,在BitBlt之前,先将和Graphics有联系的Bitmap选作DC的背景图。
                        //猜测,使用Graphics.FromImage的时候,.Net底层并没有将Bitmap对应的HBitmap选入HDC而只是将两个.Net对象联系起来了,而后在DrawImage中有两次SelectObject分别选入和选出以在HBitmap上绘图。所以独立于.Net进行GDI操作的时候,需要在GDI层面再将两者联系起来,使用SelectObject。


                        //下面解决方式如下
                        var mHdc = mHdcGraphics.GetHdc();
                        var auxiliaryHdc = aHdcGraphics.GetHdc();

                        var hbitmap = bp.GetHbitmap();
                        var holdObject = SelectObject(auxiliaryHdc, hbitmap);
                        if (holdObject != IntPtr.Zero)
                        {
                            //BitBlt(mHdc,0,0,pbx01.Width,pbx01.Height, aHdc, 0,0, (uint)TernaryRasterOperations.SRCCOPY); // 0x00CC0020 
                            //BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, aHdc, 0, 0, 0x00CC0020); // 0x00CC0020 
                            bool result = BitBlt(mHdc, 0, 0, pbx01.Width, pbx01.Height, auxiliaryHdc, 0, 0, (uint)RasterOperationMode.SRCCOPY); // 0x00CC0020 
                            if (result)
                            {
                                TraceLog($"[C#]GDI+中使用BitBlt绘制图像到窗口 成功:{result}");
                            }
                            else
                            {
                                TraceLog($"[C#]GDI+中使用BitBlt绘制图像到窗口 失败:{result}");
                            }
                        }
                        //pbx01.Refresh();
                        //释放资源
                        DeleteObject(hbitmap);
                        mHdcGraphics.ReleaseHdc(mHdc);
                        aHdcGraphics.ReleaseHdc(auxiliaryHdc);

                    }
                }
            }
        }

        [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 Rect lpRect);

        [DllImport("user32.dll")]
        public static extern bool GetClientRect(IntPtr hWnd, out 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 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);



        [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;
        }

        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
        }
        #endregion
```
复制代码

 

posted @   龙骑科技  阅读(177)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示