我从事一个小型实时项目,其中非常需要快速位图渲染技术。我需要每秒在图片框中显示许多(数百)个小块,我从 pinvoke.net 中找到了 bitblt
示例网站。
我使用 while 循环(现在是无限循环)来检索特定位图,然后调用 Invalidate()
方法来触发 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);
有人知道这里出了什么问题吗?我一直在释放已使用的资源(在绘画事件中)...为什么会出现此错误?
提前致谢。
最佳答案
Does anyone have an idea what is wrong here? i keep releasing the used resources(in the paint event)...why i'm getting this error?
实际上您没有释放所有使用的资源,特别是bmp.GetHbitmap()
调用返回的位图句柄。正确的顺序是将原始默认位图句柄选回设备上下文,然后删除您的位图句柄,如 SelectObject
documentation 中所述。 :
This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.
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);
关于C# bitblt位图渲染控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39527865/