GDI+ and GDI interop mix failing on Graphics objects

  • Thread starter oskilian ~at~ rapapaing #dot# com
  • Start date
O

oskilian ~at~ rapapaing #dot# com

I'm developing a small image editor as a component in my app in C#. I have the following Image

Image srcImage

Which is currently loaded with the image in the file, and I'm painting it into the Graphics of a PictureBox basically doing the following

private void pictureBox_Paint(object sender, PaintEventArgs e

Graphics dest = e.Graphics
dest.DrawImage(srcImage, destRect, srcRect, GraphicsUnit.Pixel)


And it works well. Now I need to pass through an intermediate Graphics, so I can do several changes to it before passing it on to the final destination. Since the only Blitting method I found for two memory GDI+ objects is Graphics.DrawImage(), I've only found a way to go from Bitmap to Graphics, but not the other way around, and there are no Graphics-Graphics Blitting methods, I chose to use the GDI. My new code goes like this

private void pictureBox_Paint(object sender, PaintEventArgs e

IntPtr hdcSrc
IntPtr hdcDest
Graphics src = Graphics.FromImage(srcImage)
Graphics dest = e.Graphics
hdcDest = dest.GetHdc()
hdcSrc = src.GetHdc();
// More GDI code will go here once I get this to work..
GDI.StretchBlt(hdcDest, destRect.X, destRect.Y, destRect.Width, destRect.Height
hdcSrc, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, RasterOperations.SRCCOPY)
src.ReleaseHdc()
src.Dispose()
dest.ReleaseHdc()


But the result is a black image. I have RasterOperations.SRCCOPY equal to 0x00CC0020. The interop invoke is properly defined, as using RasterOperations.WHITENESS=0x00FF0062 gives a white rectangle in the destination properly

My current guess is that Graphics.FromImage() is loading the image with some parameters incorrectly

I also tried this

private void pictureBox_Paint(object sender, PaintEventArgs e

IntPtr hdcSrc
IntPtr hdcDest
Graphics src = Graphics.FromImage(srcImage)
Graphics dest = e.Graphics
dest.DrawImageUnscaled(srcImage, 0, 0, srcImage.Width, srcImage.Height)
hdcDest = dest.GetHdc()
hdcSrc = src.GetHdc();
// More GDI code will go here once I get this to work..
GDI.StretchBlt(hdcSrc, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height
hdcDest, destRect.X, destRect.Y, destRect.Width, destRect.Height, RasterOperations.SRCCOPY)
GDI.StretchBlt(hdcDest, destRect.X, destRect.Y, destRect.Width, destRect.Height
hdcSrc, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, RasterOperations.SRCCOPY)
src.ReleaseHdc()
src.Dispose()
dest.ReleaseHdc()


And it works, probably because the first StretchBlt sets these missing parameters, but impressively, adding this

src.ReleaseHdc()
dest.ReleaseHdc()
hdcDest = dest.GetHdc()
hdcSrc = src.GetHdc()

between both calls to StretchBlt makes it fail again, probably because these parameters are lost when the HDC is released. The MSDN says that "Any state changes you make to the device context between GetHDC and ReleaseHDC will be ignored by GDI+ and will not be reflected in rendering done by GDI+." But it doesn't say what a "state" is

I would appreciate it if somebody told me how to either
* Perform managed StretchBlt operations between two Graphics objects
* Get the Bitmap out of a Graphics (to use Graphics.DrawImage()
* Get FromImage() to work properly when GDI calls are called upon the resulting Graphics.GetHdc(

o

* Know what do I have to change on a Graphics object after doing FromImage() so GDI calls on its hdc will work

Thank you very much, and please excuse my very long message, this is as short as I could make it

Oskilian
 
B

Bob Powell [MVP]

When you bang your head against a brick wall for a while you'll find it's
lovely when you stop.

#1 Don't use PictureBox as a drawing surface. its for displaying pictures
placed in it's Image property, nothing else.
#2 Don't try to use the screen as a record-keeping area for your drawing
operations. Do all the drawing on back-buffer style in memory images and
composite as you go for the final image.
#3 Create a Control based object that encapsulates the image data and the
operations. Don't mess about with handling events from child controls on a
form etc.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top