Leaders snarfblam Posted July 1, 2003 Leaders Posted July 1, 2003 I am making a user control in vb.net. I am trying to use GDI, however, to handle the blitting, since GDI is faster. I am using the hdc's that i retreive from graphics objects to pass to bitblt, and bitblt return values indicate a successful blit. But after I release the hdcs and try to display the bitmap on the screen, i get nothing but blackness. It works, however with GDI+ functions. Here is the GDI+ Version Dim Source As New Bitmap("D:\Visual studio projects\console\LEDWindows.bmp") Dim GSource As Graphics = Graphics.FromImage(Source) Dim hDCSource As IntPtr Dim Persist As Bitmap Dim GPersist As Graphics Dim hDCPersist As IntPtr Private Sub NewSize() Dim i, j As Integer Persist = New Bitmap(m_ConsoleSize.Width * 12, m_ConsoleSize.Height * 20) GPersist = Graphics.FromImage(Persist) For i = 0 To m_ConsoleSize.Width - 1 For j = 0 To m_ConsoleSize.Height - 1 GPersist.DrawImage(Source, i * CharWidth, j * CharHeight, New Rectangle(0, 40, 12, 20), GraphicsUnit.Pixel) Next Next Me.BackgroundImage = Persist Me.Refresh() End Sub Here is the GDI Version Dim Source As New Bitmap("D:\Visual studio projects\console\LEDWindows.bmp") Dim GSource As Graphics = Graphics.FromImage(Source) Dim hDCSource As IntPtr Dim Persist As Bitmap Dim GPersist As Graphics Dim hDCPersist As IntPtr Private Sub NewSize() Dim i, j As Integer Persist = New Bitmap(m_ConsoleSize.Width * 12, m_ConsoleSize.Height * 20, Imaging.PixelFormat.Format24bppRgb) GPersist = Graphics.FromImage(Persist) hDCPersist = GPersist.GetHdc hDCSource = GSource.GetHdc For i = 0 To m_ConsoleSize.Width - 1 For j = 0 To m_ConsoleSize.Height - 1 BitBlt(hDCPersist, i * CharWidth, j * CharHeight, 12, 20, hDCSource, 0, 40, vbSrcCopy) Next Next GPersist.ReleaseHdc(hDCPersist) GSource.ReleaseHdc(hDCSource) Me.BackgroundImage = Persist Me.Refresh() End Sub Note that the only difference is that the GDI+ version uses drawimage() and the GDI version grabs the hdc's, uses bitblt(), then releases the hdcs, which would be the GDI equivalent, so I can't figure out why this wont work. Quote [sIGPIC]e[/sIGPIC]
*Experts* Volte Posted July 1, 2003 *Experts* Posted July 1, 2003 If you are making a control, just stick with GDI+. GDI32 is faster, but you won't notice it in a control like this (you would only notice it in a graphic intensive application, like a game, and it's possible that in the case of many many calls to the GDI32, GDI+ would end up being faster). Recently there has been a lot of discussion about "Oh, GDI32 is faster than GDI+", but that doesn't mean you should use GDI32 instead of GDI+; GDI+ is a managed part of the .NET Framework that .NET natively supports, while GDI32 requires calls to GDI32.DLL. When I tested it, the speed ratio was about 5:1 - it took about 500ms to draw 2000 images with DrawImage, and about 100ms to draw 2000 images with BitBlt. In that case, it would probably take around 0.25ms to draw with DrawImage and 0.05ms to draw with BitBlt. Not a big deal at all. Quote
Leaders snarfblam Posted July 1, 2003 Author Leaders Posted July 1, 2003 Ok, dont start this. I am making up to, depending on the size of the control, up to 3200 calls to the blitting function (generally more like 480). Thats graphic intensive. There is a noticable lag when the control is initially drawn, or when the size is changed. I don't want that, and I am NOT using GDI+. In the case of many, many calls to GDI+ vs GDI, GDI wins. No question about it. I've made many applications like this in vb6 with no visible lag, and a few in .net with GDI+, ALWAYS with visible lag. And why would i mind calling GDI32.dll? And what is wrong with calling unmanaged code that is not part of .net? To me it is a big deal, i want my programs to run smoothly. Please, no one tell me not to use GDI. I want to use GDI. When GDI+ is appropriate, as in drawing only a few images, or performing skewing and stretching effects, etc., i will GLADLY use GDI+. But I want to use GDI, it does exactly what I want it to with no unwanted side effects. So PLEASE don't tell me to use GDI+ or DirectX. Pretty please? Quote [sIGPIC]e[/sIGPIC]
*Experts* Volte Posted July 1, 2003 *Experts* Posted July 1, 2003 Heh, OK, I didn't realize you were the one that we'd already had this discussion with. From your code, it didn't look like it was being called that many times. Have you declared vbSrcCopy as anything? If Option Explicit is not on, then that will evaluate to 0. vbSrcCopy is not a constant in .NET. Quote
Leaders snarfblam Posted July 1, 2003 Author Leaders Posted July 1, 2003 Yeah, thats me. Anyways, I always use option explicit, and all my constants are declared. I got the value of vbSrcCopy from vb6. Also, I'm an idiot. I copied the bitblt declaration for vb6 and didnt change the parameters from longs to integers. I fixed it though, and it is still behaving the same. Quote [sIGPIC]e[/sIGPIC]
Leaders snarfblam Posted July 1, 2003 Author Leaders Posted July 1, 2003 Oops. I know why this doesnt work. HDC's aquired from graphics objects backed by bitmaps (like my bitmap named Source) are meant to be write only. You cant copy graphics from them, or you will turn up with blackness. So I need to create a GDI compatible source DC. Quote [sIGPIC]e[/sIGPIC]
*Gurus* divil Posted July 1, 2003 *Gurus* Posted July 1, 2003 In future, can all GDI questions be posted in the Interop forum, thanks. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
Polymorpher Posted August 20, 2006 Posted August 20, 2006 vbSrcCopy??? I got the value of vbSrcCopy from vb6. could you please tell me the value of vbSrcCopy? I have been looking everywhere. Quote
Leaders snarfblam Posted August 20, 2006 Author Leaders Posted August 20, 2006 could you please tell me the value of vbSrcCopy? I have been looking everywhere. Google Search: The first link has the answer. vbSourceCopy is the same as the Windows API SRCCOPY constant. In the future, new questions should generally go in new threads. Quote [sIGPIC]e[/sIGPIC]
Polymorpher Posted August 24, 2006 Posted August 24, 2006 Thanks alot! Maybe I sould install vb6 just for stuff like this LOL Quote
headkaze Posted October 19, 2006 Posted October 19, 2006 I know this is an old thread, but I found this use of bitblt in C# on the web a while ago if it's of any help. public static void DrawBitBlt(Graphics g, Bitmap bmp, ref Rectangle destRec) { IntPtr hDC = g.GetHdc(); IntPtr hBmp = bmp.GetHbitmap(); IntPtr ImageDC= a.Api.CreateCompatibleDC(hDC); IntPtr offscreenDC= a.Api.CreateCompatibleDC(hDC); IntPtr drawBmp= a.Api.CreateCompatibleBitmap(hDC, destRec.Size.Width, destRec.Size.Height); IntPtr oldBmp= a.Api.SelectObject(ImageDC, hBmp); IntPtr oldDrawBmp= a.Api.SelectObject(offscreenDC, drawBmp); if(bmp.Size.Equals(destRec.Size)) { a.Api.BitBlt(offscreenDC, 0, 0, destRec.Width, destRec.Height, ImageDC, 0, 0, SrcCopy); } else a.Api.StretchBlt(offscreenDC, 0, 0, destRec.Width, destRec.Height, ImageDC, 0, 0, bmp.Width, bmp.Height, SrcCopy); a.Api.BitBlt(hDC, destRec.X, destRec.Y, destRec.Width, destRec.Height, offscreenDC, 0, 0, SrcCopy); a.Api.SelectObject(ImageDC, oldBmp); a.Api.DeleteObject(hBmp); a.Api.SelectObject(offscreenDC, oldDrawBmp); a.Api.DeleteObject(drawBmp); a.Api.DeleteDC(ImageDC); a.Api.DeleteDC(offscreenDC); g.ReleaseHdc(hDC); } Quote
Recommended Posts