2013-04-30 323 views
0

自从我上一次进入GDI已经过去了几年,但我不记得之前有过这样的问题。我没有得到一个异常,但BitBlt返回0(False),检查GetLastWIN32Error显示6.这似乎是一个无效的句柄。目标图像保持空白。BitBlt返回false,GetLastError返回6(无效句柄)?

我加入了对SelectObject的调用,但是这不应该也不会影响无效句柄错误。

关于我失踪的任何想法?

void MySub() 
{ 
    var bmpSrc = new Bitmap("c:\\temp\\test.bmp", false); 
    var bmpDst= new Bitmap(1000, 1000); 
    var gSrc = Graphics.FromImage(bmpSrc); 
    var gDst = Graphics.FromImage(bmpDst); 
    IntPtr HDCSrc = gSrc.GetHdc(); 
    IntPtr HDCDst = gDst.GetHdc(); 
    if (!BitBlt(HDCDst, 0, 0, 55, 94, HDCSrc, 0, 0, SRCCOPY)) 
    { 
     int er = Marshal.GetLastWin32Error(); 
     MessageBox.Show(er.ToString()); 
    } 
    gDst.ReleaseHdc(HDCDst); 
    gSrc.ReleaseHdc(HDCSrc); 
    pictureBox1.Image = iDst; 
} 

public static long SRCCOPY = 0x00CC0020; 

[DllImport("gdi32.dll", CallingConvention = CallingConvention.ThisCall, SetLastError = true)] 
public static extern bool BitBlt(
    IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, long dwRop); 

回答

0

好了,所以这可能是一个评论,但有代码,我在这里发帖:

是否有任何理由,为什么你需要的P/Invoke?出了什么问题:

using(var bmpSrc = new Bitmap("c:\\temp\\test.bmp", false)) 
using(var bmpDst = new Bitmap(1000, 1000)) 
using(var gDst = Graphics.FromImage(bmpDst)) 
{ 
    gDst.DrawImage(bmpSrc,0,0,55,94); 
    //... 
} 
+0

好问题!我实际上看到了Graphics.Draw的性能问题......渲染量和我们碰到的用户数量的规模。我的计划是比较DrawImage和直接调用BitBlt的性能,看它是否值得追求。 – ThatRickGuy 2013-04-30 18:54:36

1

您对Win32 API的调用约定错误。使用:

CallingConvention = CallingConvention.StdCall 

另外最后一个参数应该是UInt32或equiv。虽然不具有权威性,但pinvoke.net非常有用。在这种情况下,它会为最后一个参数定义一个很好的枚举,以防您将使用BitBlt的任何其他栅格操作。

+0

另一个重点,我的回应受限于我对此更改的全面影响缺乏了解,但使用CallingConvention.StdCall导致BitBlt调用出现异常: 对PInvoke函数“Form1 :: BitBlt”的调用已经失去了平衡。这很可能是因为托管的PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名相匹配。 如果使用StdCall,有没有其他一些配置我错过了,以确保兼容性? – ThatRickGuy 2013-04-30 18:58:00

+0

感谢指向pinvoke.net的指针,这对于获得bitblt定义是否正确非常有帮助! – ThatRickGuy 2013-05-01 02:04:05

1

最后设法追查什么,我试图完成一个确切的例子,那就是:

 var bmpSrc = new Bitmap("c:\\temp\\test.bmp"); 
     var bmpDst = new Bitmap(1000, 1000); 

     // Get source image in memory 
     Graphics sourceImageGraphics = Graphics.FromImage(bmpDst); 
     IntPtr sourceImageHDC = sourceImageGraphics.GetHdc(); 
     IntPtr sourceImageCDC = CreateCompatibleDC(sourceImageHDC); 
     IntPtr sourceImageHandle = bmpDst.GetHbitmap(); 
     SelectObject(sourceImageCDC, sourceImageHandle); 

     // Get overlay image in memory 
     Graphics overlayImageGraphics = Graphics.FromImage(bmpSrc); 
     IntPtr overlayImageHDC = overlayImageGraphics.GetHdc(); 
     IntPtr overlayImageCDC = CreateCompatibleDC(overlayImageHDC); 
     IntPtr overlayImageHandle = bmpSrc.GetHbitmap(); 
     SelectObject(overlayImageCDC, overlayImageHandle); 

     for (int x = 0; x < _Iterations; x++) 
       if (!BitBlt(sourceImageHDC, 0, 0, 55, 94, overlayImageCDC, 0, 0, TernaryRasterOperations.SRCCOPY)) 
       { 
        var er = Marshal.GetLastWin32Error(); 
        MessageBox.Show(er.ToString()); 
       } 

     // Release source Image memory. 
     DeleteDC(sourceImageCDC); 
     DeleteObject(sourceImageHandle); 
     sourceImageGraphics.ReleaseHdc(sourceImageHDC); 
     sourceImageGraphics.Dispose(); 

     // Release overlay Image memory. 
     DeleteDC(overlayImageCDC); 
     DeleteObject(overlayImageHandle); 
     overlayImageGraphics.ReleaseHdc(overlayImageHDC); 
     overlayImageGraphics.Dispose(); 

     pictureBox1.Image = bmpDst; 

而且超过10万个bitblts VS 100000个.DrawImages,BitBlt的是破碎.DrawImages〜8:1上我的笔记本电脑。 :)

+0

这是您的努力的良好回报! – spender 2013-05-06 01:33:39