C#bitblt位图呈现控制

时间:2016-09-16 09:20:40

标签: c# bitmap rendering gdi+

我正在开展一个小型实时项目,其中非常需要快速位图渲染技术。我需要每秒在图片框中显示许多(数百个)小块,我在pinvoke.net网站上找到了Invalidate()示例。

我使用while循环(现在它是无限的)来检索特定的位图,然后调用Paint方法来触发 protected override void OnPaint(PaintEventArgs e) { IntPtr pTarget = e.Graphics.GetHdc(); IntPtr pSource = CreateCompatibleDC(pTarget); IntPtr pOrig = SelectObject(pSource, bmp.GetHbitmap()); BitBlt(pTarget, 0, 0, bmp.Width, bmp.Height, pSource, 0, 0, TernaryRasterOperations.SRCCOPY); DeleteObject(pOrig); DeleteDC(pSource); e.Graphics.ReleaseHdc(pTarget); } private void Display() { while (true) { frame = desktopDuplicator.GetLatestFrame(); if (frame != null) { bmp = frame.DesktopImage;//retrieve image. this.Invoke(new Action(() => this.Invalidate()));//trigger the repaint event } } } 事件。

这是我的代码:

System.ArgumentException

它可以正常工作几秒钟,然后我在这一行得到 BitBlt(pTarget, 0, 0, bmp.Width, bmp.Height, pSource, 0, 0, TernaryRasterOperations.SRCCOPY);

{{1}}

有没有人知道这里有什么问题?我一直在释放使用过的资源(在油漆事件中)......为什么我会收到这个错误?

提前致谢。

2 个答案:

答案 0 :(得分:2)

  

有没有人知道这里有什么问题?我一直在释放使用过的资源(在油漆事件中)......为什么我会收到这个错误?

实际上你释放所有使用的资源,特别是bmp.GetHbitmap()调用返回的位图句柄。正确的顺序是选择将原始默认位图句柄返回到设备上下文中,然后删除位图句柄,如SelectObject documentation中所述:

  

此函数返回先前选定的指定类型的对象。应用程序应该在使用新对象完成绘制后,始终用原始的默认对象替换新对象。

IntPtr targetDC = e.Graphics.GetHdc();
IntPtr sourceDC = CreateCompatibleDC(targetDC);
IntPtr sourceBitmap = bmp.GetHbitmap();
IntPtr originalBitmap = SelectObject(sourceDC, sourceBitmap);
BitBlt(targetDC, 0, 0, bmp.Width, bmp.Height, sourceDC, 0, 0, TernaryRasterOperations.SRCCOPY);
SelectObject(sourceDC, originalBitmap);
DeleteObject(sourceBitmap);
DeleteDC(sourceDC);
e.Graphics.ReleaseHdc(targetDC);

答案 1 :(得分:1)

来自Bitmap.GetHbitmap方法的文档:

  

您负责调用GDI DeleteObject方法来释放GDI位图对象使用的内存。

您目前似乎没有调用它,这将导致泄漏。完成资源后,您应该致电DeleteObject,所以可能会这样:

protected override void OnPaint(PaintEventArgs e)
{
    IntPtr pTarget = e.Graphics.GetHdc();
    IntPtr pSource = CreateCompatibleDC(pTarget);
    IntPtr pOrig = SelectObject(pSource, bmp.GetHbitmap());
    BitBlt(pTarget, 0, 0, bmp.Width, bmp.Height, pSource, 0, 0, TernaryRasterOperations.SRCCOPY);
    DeleteObject(pOrig);
    DeleteDC(pSource);
    e.Graphics.ReleaseHdc(pTarget);
}