[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.drawing

Graphics.GetHdc/Graphics.FromImage/R2_MASKPEN Woos

gdi_plus

1/10/2005 11:11:00 PM

Hello all,

I'm trying to draw a rectangle with ROP2 = R2_MASKPEN on a GDI+ image.
The method below (TestDraw) works when I pass it a Graphics object from
a paint event. However, when I pass in the result from
Graphics.FromImage, it seems the ROP2 is ignored and I end up with a
solid black rectangle. Any help is appreciated.

private const int R2_MASKPEN = 9;
private System.Windows.Forms.Button button1;
private const int NULL_PEN = 8;

[DllImport("gdi32")] private static extern IntPtr CreateSolidBrush(int
crColor);
[DllImport("gdi32")] private static extern IntPtr SelectObject(IntPtr
hdc, IntPtr hgdiobj);
[DllImport("gdi32")] private static extern bool DeleteObject(IntPtr
hObject);
[DllImport("gdi32")] private static extern IntPtr GetStockObject(int
fnObject);
[DllImport("gdi32")] private static extern int SetROP2(IntPtr hdc, int
fnDrawMode);
[DllImport("gdi32")] private static extern bool Rectangle(IntPtr hdc,
int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);

private void TestDraw(Graphics g)
{
// some light blue rectangle using GDI+
g.FillRectangle(Brushes.LightBlue, 0, 0, 200, 200);

// now use GDI to draw a smaller yellow rectangle with AND rop
IntPtr hdc = g.GetHdc();

IntPtr hBrush =
CreateSolidBrush(ColorTranslator.ToWin32(Color.Yellow));
IntPtr hOldBrush = SelectObject(hdc, hBrush);
IntPtr hPen = GetStockObject(NULL_PEN);
IntPtr hOldPen = SelectObject(hdc, hPen);

int oldRop2 = SetROP2(hdc, R2_MASKPEN);
Rectangle(hdc, 50, 50, 150, 150);
SetROP2(hdc, oldRop2);

SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hBrush);

g.ReleaseHdc(hdc);
}

// now if I call it from Form1_Paint like this, it works fine:
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
TestDraw(e.Graphics);
}

// Call it from this, the result is a solid black rectangle
// inside the blue rectangleprivate void button1_Click(object sender,
System.EventArgs e)
{
Bitmap btmp = new Bitmap(200, 200);
Graphics g = Graphics.FromImage(btmp);
TestDraw(g);
g.Dispose();
btmp.Save(@"c:\temp\test.bmp",
System.Drawing.Imaging.ImageFormat.Bmp);
btmp.Dispose();
}

Thanks,
Kousay Alani

5 Answers

Bob Powell

1/11/2005 12:03:00 AM

0

You have to do this through interop. Use CreateCompatibleDC, Select the
image into the DC using the image handle provided by Image and draw on it
using the ROP code of your choice. All in GDI of course.

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

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

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

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





<gdi_plus@yahoo.com> wrote in message
news:1105398660.348968.275050@f14g2000cwb.googlegroups.com...
> Hello all,
>
> I'm trying to draw a rectangle with ROP2 = R2_MASKPEN on a GDI+ image.
> The method below (TestDraw) works when I pass it a Graphics object from
> a paint event. However, when I pass in the result from
> Graphics.FromImage, it seems the ROP2 is ignored and I end up with a
> solid black rectangle. Any help is appreciated.
>
> private const int R2_MASKPEN = 9;
> private System.Windows.Forms.Button button1;
> private const int NULL_PEN = 8;
>
> [DllImport("gdi32")] private static extern IntPtr CreateSolidBrush(int
> crColor);
> [DllImport("gdi32")] private static extern IntPtr SelectObject(IntPtr
> hdc, IntPtr hgdiobj);
> [DllImport("gdi32")] private static extern bool DeleteObject(IntPtr
> hObject);
> [DllImport("gdi32")] private static extern IntPtr GetStockObject(int
> fnObject);
> [DllImport("gdi32")] private static extern int SetROP2(IntPtr hdc, int
> fnDrawMode);
> [DllImport("gdi32")] private static extern bool Rectangle(IntPtr hdc,
> int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
>
> private void TestDraw(Graphics g)
> {
> // some light blue rectangle using GDI+
> g.FillRectangle(Brushes.LightBlue, 0, 0, 200, 200);
>
> // now use GDI to draw a smaller yellow rectangle with AND rop
> IntPtr hdc = g.GetHdc();
>
> IntPtr hBrush =
> CreateSolidBrush(ColorTranslator.ToWin32(Color.Yellow));
> IntPtr hOldBrush = SelectObject(hdc, hBrush);
> IntPtr hPen = GetStockObject(NULL_PEN);
> IntPtr hOldPen = SelectObject(hdc, hPen);
>
> int oldRop2 = SetROP2(hdc, R2_MASKPEN);
> Rectangle(hdc, 50, 50, 150, 150);
> SetROP2(hdc, oldRop2);
>
> SelectObject(hdc, hOldPen);
> SelectObject(hdc, hOldBrush);
> DeleteObject(hBrush);
>
> g.ReleaseHdc(hdc);
> }
>
> // now if I call it from Form1_Paint like this, it works fine:
> private void Form1_Paint(object sender,
> System.Windows.Forms.PaintEventArgs e)
> {
> TestDraw(e.Graphics);
> }
>
> // Call it from this, the result is a solid black rectangle
> // inside the blue rectangleprivate void button1_Click(object sender,
> System.EventArgs e)
> {
> Bitmap btmp = new Bitmap(200, 200);
> Graphics g = Graphics.FromImage(btmp);
> TestDraw(g);
> g.Dispose();
> btmp.Save(@"c:\temp\test.bmp",
> System.Drawing.Imaging.ImageFormat.Bmp);
> btmp.Dispose();
> }
>
> Thanks,
> Kousay Alani
>


gdi_plus

1/11/2005 3:01:00 PM

0

Bob, thanx for the reply.

I'm already using Interop. The problem is this:

a. If I pass TestDraw above the Graphics object I get from a paint
event, it works fine.
b. If I pass it the Graphics object I get from Graphics.FromImage, it
does not.

It is a GDI+/GDI sync problem and I don't know how to fix it. I tried
the various Graphics.Flush methods as well as the GdiFlush API with no
help.

Thanks,
Kousay Alani

Bob Powell

1/11/2005 3:22:00 PM

0

I understood the problem the first time.

You have to gereate a compatible DC using interop and pass the handle of the
bitmap you wish to draw on using GDI to the Select method in the Win32 API.

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

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

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

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





<gdi_plus@yahoo.com> wrote in message
news:1105455656.283149.266480@f14g2000cwb.googlegroups.com...
> Bob, thanx for the reply.
>
> I'm already using Interop. The problem is this:
>
> a. If I pass TestDraw above the Graphics object I get from a paint
> event, it works fine.
> b. If I pass it the Graphics object I get from Graphics.FromImage, it
> does not.
>
> It is a GDI+/GDI sync problem and I don't know how to fix it. I tried
> the various Graphics.Flush methods as well as the GdiFlush API with no
> help.
>
> Thanks,
> Kousay Alani
>


gdi_plus

1/11/2005 4:06:00 PM

0

Bob,

I do not have a bitmap to draw on, I have a Graphics object. My method
is this:
void TestDraw(Graphics g)
This is part of a package that my customers use. I have no telling
whether they are passing a Graphics objects from a paint event (works
fine) or from a Graphics.FromImage (problem).
This is another code that shows the problem:

// Test is part of a package that my customer can use
// Note, that I have no control where g comes from
private const uint SRCCOPY = 0x00CC0020;
[DllImport("gdi32")] private static extern bool BitBlt(IntPtr hdcDest,
int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int
nXSrc, int nYSrc, uint dwRop);
public void Test(Graphics g)
{
// 2 100 pixels boxes, red on the left, blue on the right
g.FillRectangle(Brushes.Red, 0, 0, 100, 100);
g.FillRectangle(Brushes.Blue, 100, 0, 100, 100);

// now, I want to use GDI to blt the red box over the blue
IntPtr hdc = g.GetHdc();
// Case1: works fine
// Case2: GDI does not "see" the surface of the Graphics object, the
previous operations are ignored.
// At this point, any GDI call that involves using the background of
hdc (including ROP2 operations as in original problem)
// do not work. The background is pure black.
BitBlt(hdc, 100, 0, 100, 100, hdc, 0, 0, SRCCOPY);
g.ReleaseHdc(hdc);
}

Case1: Now if my customer uses this code, everything works fine:
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
Test(e.Graphics);
}

Case2: However, this is a problem:
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
Bitmap btmp = new Bitmap(200, 200);
Graphics g = Graphics.FromImage(btmp);
Test(g); // PROBLEM!!!
g.Dispose();
e.Graphics.DrawImage(btmp, 0, 0, btmp.Width, btmp.Height);
btmp.Dispose();
}

Bob Powell

1/11/2005 8:23:00 PM

0

You're looking at it from the wrong angle. You cannot pass the handle of the
graphics object passed to you from a bitmap and successfully create a useful
GDI DC from it.

#1 for case 2 greate a compatible DC using the interop API's
#2 obtain a bitmap handle for the bitmap
#3 select it into the DC
#4 create a GDI+ object from the GDI handle and draw on it.

something like

Bitmap btmp=new Bitmap(200,200);
IntPtr gdiHande=CreateCompatibleDC(....);
IntPtr bmHandle=btmp.Handle();
Select(gdiHandle,bmHandle)
Graphics g=Graphics.FromHandle(gdiHandle)
Test(g)
.... release the GDI DC
.... select the old bitmap handle back into the DC
.... destroy the gdi DC
etc.... etc.....

Obviously I've not compiled this but i'm sure you'll get the picture. (if
you'll pardon the pun)

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

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

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

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





<gdi_plus@yahoo.com> wrote in message
news:1105459537.774095.88520@z14g2000cwz.googlegroups.com...
> Bob,
>
> I do not have a bitmap to draw on, I have a Graphics object. My method
> is this:
> void TestDraw(Graphics g)
> This is part of a package that my customers use. I have no telling
> whether they are passing a Graphics objects from a paint event (works
> fine) or from a Graphics.FromImage (problem).
> This is another code that shows the problem:
>
> // Test is part of a package that my customer can use
> // Note, that I have no control where g comes from
> private const uint SRCCOPY = 0x00CC0020;
> [DllImport("gdi32")] private static extern bool BitBlt(IntPtr hdcDest,
> int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int
> nXSrc, int nYSrc, uint dwRop);
> public void Test(Graphics g)
> {
> // 2 100 pixels boxes, red on the left, blue on the right
> g.FillRectangle(Brushes.Red, 0, 0, 100, 100);
> g.FillRectangle(Brushes.Blue, 100, 0, 100, 100);
>
> // now, I want to use GDI to blt the red box over the blue
> IntPtr hdc = g.GetHdc();
> // Case1: works fine
> // Case2: GDI does not "see" the surface of the Graphics object, the
> previous operations are ignored.
> // At this point, any GDI call that involves using the background of
> hdc (including ROP2 operations as in original problem)
> // do not work. The background is pure black.
> BitBlt(hdc, 100, 0, 100, 100, hdc, 0, 0, SRCCOPY);
> g.ReleaseHdc(hdc);
> }
>
> Case1: Now if my customer uses this code, everything works fine:
> private void Form1_Paint(object sender,
> System.Windows.Forms.PaintEventArgs e)
> {
> Test(e.Graphics);
> }
>
> Case2: However, this is a problem:
> private void Form1_Paint(object sender,
> System.Windows.Forms.PaintEventArgs e)
> {
> Bitmap btmp = new Bitmap(200, 200);
> Graphics g = Graphics.FromImage(btmp);
> Test(g); // PROBLEM!!!
> g.Dispose();
> e.Graphics.DrawImage(btmp, 0, 0, btmp.Width, btmp.Height);
> btmp.Dispose();
> }
>