1

我正在尝试使用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 包含蓝色/黄色矩形(目标中的初始位图),而不是应该从源位图中删除的红色/绿色矩形?

导入是这样完成的:

    [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);
4

1 回答 1

1

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

跨托管位图的 BitBlt()

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

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

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

有人知道为什么这个组合有效吗?...

于 2013-06-04T21:05:21.070 回答