c#gdi32 bitblt似乎什么都不做

时间:2013-06-04 14:36:25

标签: c# .net winforms winapi bitblt

我正在尝试使用 BitBlt 获取图形区域并将其存储在位图中。 但在这里,我更容易理解我的问题:

        Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
        Graphics sourceGraphics = Graphics.FromImage(sourceBitmap);

        Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
        Graphics destGraphics = Graphics.FromImage(destBitmap);

        sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30));
        sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30));

        destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30));
        destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30));

        IntPtr destDC = destGraphics.GetHdc();
        IntPtr destHB = destBitmap.GetHbitmap();
        IntPtr old = SelectObject(destDC, destHB);

        IntPtr sourceDC = sourceGraphics.GetHdc();
        IntPtr sourceHB = sourceBitmap.GetHbitmap();
        old = SelectObject(sourceDC, sourceHB);

        int success = BitBlt(
            destDC, 0, 0, 64, 64, sourceDC, 0, 0, 0x00CC0020
        );

为什么在BitBlt之后我的destBitmap包含蓝色/黄色矩形(目标中的初始位图)而不是应该从源位图blit的红色/绿色矩形?

进口是这样完成的:

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    private static extern int BitBlt(
      IntPtr hdcDest,     // handle to destination DC (device context)
      int nXDest,         // x-coord of destination upper-left corner
      int nYDest,         // y-coord of destination upper-left corner
      int nWidth,         // width of destination rectangle
      int nHeight,        // height of destination rectangle
      IntPtr hdcSrc,      // handle to source DC
      int nXSrc,          // x-coordinate of source upper-left corner
      int nYSrc,          // y-coordinate of source upper-left corner
      System.Int32 dwRop  // raster operation code
      );

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    public static extern void DeleteObject(IntPtr obj);

最后清理代码和位图流以查看位图内容:

        DeleteObject(destHB);
        DeleteObject(sourceHB);
        destGraphics.ReleaseHdc();
        sourceGraphics.ReleaseHdc();

        string path = "c:/tmp/dest.png";
        destBitmap.Save(path);

1 个答案:

答案 0 :(得分:1)

找到一个有效的组合......但我不明白为什么(绝对不是GDI专家):

BitBlt() across Managed Bitmaps

我添加了使用CreateCompatibleDC()创建兼容DC的调用。

但是请注意,在对BitBlt()的实际调用中,我仍然使用原始DC“destDC”作为目标DC(而不是新的“destCDC”),但新的兼容DC“sourceCDC”为源DC。似乎没有其他组合工作。我仍然,然而,必须为目的地创建一个兼容的DC,即使我没有在BitBlt()调用中使用它:

    private const int SRCCOPY = 0xCC0020;

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    private static extern int BitBlt(
      IntPtr hdcDest,     // handle to destination DC (device context)
      int nXDest,         // x-coord of destination upper-left corner
      int nYDest,         // y-coord of destination upper-left corner
      int nWidth,         // width of destination rectangle
      int nHeight,        // height of destination rectangle
      IntPtr hdcSrc,      // handle to source DC
      int nXSrc,          // x-coordinate of source upper-left corner
      int nYSrc,          // y-coordinate of source upper-left corner
      int dwRop  // raster operation code
      );

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);

    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
    public static extern void DeleteObject(IntPtr obj);

    private void button1_Click(object sender, EventArgs e)
    {
        Bitmap sourceBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
        Graphics sourceGraphics = Graphics.FromImage(sourceBitmap);

        Bitmap destBitmap = new Bitmap(64, 64, PixelFormat.Format32bppRgb);
        Graphics destGraphics = Graphics.FromImage(destBitmap);

        sourceGraphics.FillRectangle(new SolidBrush(Color.Red), new Rectangle(0, 0, 30, 30));
        sourceGraphics.FillRectangle(new SolidBrush(Color.Green), new Rectangle(30, 30, 30, 30));

        destGraphics.FillRectangle(new SolidBrush(Color.Blue), new Rectangle(0, 0, 30, 30));
        destGraphics.FillRectangle(new SolidBrush(Color.Yellow), new Rectangle(30, 30, 30, 30));

        IntPtr destDC = destGraphics.GetHdc();
        IntPtr destCDC = CreateCompatibleDC(destDC);
        IntPtr destHB = destBitmap.GetHbitmap();
        IntPtr oldDest = SelectObject(destCDC, destHB);

        IntPtr sourceDC = sourceGraphics.GetHdc();
        IntPtr sourceCDC = CreateCompatibleDC(sourceDC);
        IntPtr sourceHB = sourceBitmap.GetHbitmap();
        IntPtr oldSource = SelectObject(sourceCDC, sourceHB);

        int success = BitBlt(
            destDC, 0, 0, 64, 64, sourceCDC, 0, 0, SRCCOPY
        );

        SelectObject(destCDC, oldDest);
        SelectObject(sourceCDC, oldSource);

        DeleteObject(destCDC);
        DeleteObject(sourceCDC);

        DeleteObject(destHB);
        DeleteObject(sourceHB);

        destGraphics.ReleaseHdc();
        sourceGraphics.ReleaseHdc();

        pictureBox1.Image = sourceBitmap;
        pictureBox2.Image = destBitmap;
    }

任何人都知道为什么这个组合有效?...