Answered by:
Need an expert advice regarding GDI & C#

Question
-
Hi,
Need GDI expert help!!!
Help..
Will explain my problem if any expert is here now.
- Moved by Cookie Luo Tuesday, July 12, 2011 6:56 AM (From:Visual C# General)
Friday, July 8, 2011 11:02 PM
Answers
-
You're performing a SRCINVERT on a dc that came from GDI+. I'd be inclined to do all the ROP stuff with GDI DC's. GDI+ doesn't support ROPs, so the GetHdc stuff worries me a little. I'll have to do some digging to see if this is actually supported.
Alternatives:
- Do your screenshot using Graphics.CopyFromScreen. Do the invert another way.
- Do the Invert to a GDI bitmap created using CreateCompatibleBitmap and then just use the resulting bitmap in GDI+ using Bitmap.FromHBITMAP.
Again, I'm not sure the GDI and GDI+ DC's are compatible for ROPs. Methinks not.
:/
Monday, July 11, 2011 3:43 AM -
No, thanks.
I've done it finally in managed code. Works... but it took 6 days to find out that GDIPLUS doesn't support XOR operation on GDIPLUS bitmap.
As gdi32 and Gdiplus Bitmaps are very different, and DCs as well...
they're just different.
I use DIB API and never convert it to managed bitmap if the bitmap's context is used to BitBlt on top of another GDI32 bitmap.
so if someone needs the solution - you welcome - poke me up here or in skype: robbkirk
Tuesday, July 12, 2011 4:13 PM
All replies
-
My advice is to ask your question. The most you will get in life is what you ask for.Saturday, July 9, 2011 8:19 AM
-
Ok, here is the example.
Why XORCycleA doesn't work while XORCycleB works...
Here is quite serious riddle for an expert.
Hope you can "speak" C# and will understand my strings without additional comments :))
XOR_Paint will be invoked each time you move the dialog window and smth overlays it.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Drawing; using System.Windows.Forms; using System.Drawing.Imaging; namespace ConsoleTestApplication { class Program { static void Main(string[] args) { new XOR().ShowDialog(); } } internal class XOR : Form { [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, Int32 dwRop); [DllImport("gdi32.dll")] public static extern bool TextOut(IntPtr hdc, int x, int y, string lpString, int cbString); const Int32 SRCCOPY = 0x00CC0020; const Int32 SRCAND = 0x008800C6; const Int32 SRCINVERT = 0x00660046; // INVERT means XOR public XOR() { // Bit map created once with screen data in it bmA = new Bitmap(s.Width, s.Height, PixelFormat.Format32bppRgb); Graphics gfxBMP = Graphics.FromImage(bmA); gfxBMP.CopyFromScreen(0, 0, 0, 0, new Size(s.Width, s.Height), CopyPixelOperation.SourceCopy); gfxBMP.Dispose(); this.Paint += new PaintEventHandler(XOR_Paint); } void XOR_Paint(object sender, PaintEventArgs e) { xorCycleA(); xorCycleB(); } Bitmap bmA; Size s = Screen.PrimaryScreen.Bounds.Size; unsafe void xorCycleA() { Graphics grfxScreen = Graphics.FromHwnd(IntPtr.Zero); Graphics grfxBitmap = Graphics.FromImage(bmA); bmA.Save(@"c:\before_xorA.bmp", ImageFormat.Bmp); IntPtr hdcBitmap = grfxBitmap.GetHdc(); IntPtr hdcScreen = grfxScreen.GetHdc(); // without any changes just copy screen data with XOR BitBlt(hdcBitmap, 0, 0, bmA.Width, bmA.Height, hdcScreen, 0, 0, SRCINVERT); grfxScreen.ReleaseHdc(hdcScreen); grfxBitmap.ReleaseHdc(hdcBitmap); grfxScreen.Dispose(); grfxBitmap.Dispose(); bmA.Save(@"c:\after_xorA.bmp", ImageFormat.Bmp); } Bitmap bmB; unsafe void xorCycleB() { Graphics grfxScreen = Graphics.FromHwnd(IntPtr.Zero); bmB = new Bitmap((int)grfxScreen.VisibleClipBounds.Width, (int)grfxScreen.VisibleClipBounds.Height, grfxScreen); Graphics grfxBitmap = Graphics.FromImage(bmB); bmB.Save(@"c:\before_xorB.bmp", ImageFormat.Bmp); IntPtr hdcBitmap = grfxBitmap.GetHdc(); IntPtr hdcScreen = grfxScreen.GetHdc(); BitBlt(hdcBitmap, 0, 0, bmB.Width, bmB.Height, hdcScreen, 0, 0, SRCCOPY); TextOut(hdcBitmap, 100, 100, "Hi, I'm here", 12); // comment BitBlt to make sure the bitmap contains screen data and the string on it inside after_xorB.bmp BitBlt(hdcBitmap, 0, 0, bmB.Width, bmB.Height, hdcScreen, 0, 0, SRCINVERT); grfxScreen.ReleaseHdc(hdcScreen); grfxBitmap.ReleaseHdc(hdcBitmap); grfxScreen.Dispose(); grfxBitmap.Dispose(); bmB.Save(@"c:\after_xorB.bmp", ImageFormat.Bmp); } } }
Saturday, July 9, 2011 10:41 AM -
Let me make it easier to understand:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Drawing; using System.Windows.Forms; using System.Drawing.Imaging; using System.Threading; namespace XOR { internal class XOR : Form { [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, Int32 dwRop); [DllImport("gdi32.dll")] public static extern bool TextOut(IntPtr hdc, int x, int y, string lpString, int cbString); [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj); [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); const Int32 SRCCOPY = 0x00CC0020; const Int32 SRCAND = 0x008800C6; const Int32 SRCINVERT = 0x00660046; // INVERT means XOR public XOR() { //********************** // Cycle 1 //********************** Bitmap bm; bm = new Bitmap(s.Width, s.Height, PixelFormat.Format32bppRgb); Graphics grfxBitmap = Graphics.FromImage(bm); IntPtr hdcBitmap = grfxBitmap.GetHdc(); //IntPtr ptr = SelectObject(hdcBitmap, bm.GetHbitmap()); Graphics grfxScreen = Graphics.FromHwnd(IntPtr.Zero); IntPtr hdcScreen = grfxScreen.GetHdc(); BitBlt(hdcBitmap, 0, 0, s.Width, s.Height, hdcScreen, 0, 0, SRCCOPY); // if uncomment second BitBlt then cycle1.bmp is really black, means XOR worked //BitBlt(hdcBitmap, 0, 0, s.Width, s.Height, hdcScreen, 0, 0, SRCINVERT); grfxBitmap.ReleaseHdc(hdcBitmap); grfxScreen.ReleaseHdc(hdcScreen); grfxScreen.Dispose(); grfxBitmap.Dispose(); // without second BitBlt the bitmap contains screen shot bm.Save("cycle1.bmp", ImageFormat.Bmp); { /*breakpoint 1*/ } //********************** // Cycle 2 //********************** grfxBitmap = Graphics.FromImage(bm); hdcBitmap = grfxBitmap.GetHdc(); //SelectObject(hdcBitmap, bm.GetHbitmap()); grfxScreen = Graphics.FromHwnd(IntPtr.Zero); hdcScreen = grfxScreen.GetHdc(); // We put something on the bitmap with screen content, to make some changes //TextOut(hdcBitmap, 100, 100, "Hello World", 11); // now XOR the same screen on top of saved Bitmap with "Hello World" BitBlt(hdcBitmap, 0, 0, s.Width, s.Height, hdcScreen, 0, 0, SRCINVERT); grfxBitmap.ReleaseHdc(hdcBitmap); grfxScreen.ReleaseHdc(hdcScreen); grfxScreen.Dispose(); grfxBitmap.Dispose(); // here we suppose to get black screen with Hello World mark. // but screen is not black as expected. Why? bm.Save("cycle2.bmp", ImageFormat.Bmp); { /*breakpoint 2*/ } } } }
Sunday, July 10, 2011 1:02 PM -
it's absolutely doable in unmanaged c++
easy code. works fine.
maybe problem's in Graphics from Bitmap has some incompatible format.. maybe it stores data in png or even bugged code.
i'm not sure. will do it with c++ written dll.
hate to spend week fighting against gdi inside .net
- Edited by RobbKirk Monday, July 11, 2011 10:18 AM
Monday, July 11, 2011 12:18 AM -
You're performing a SRCINVERT on a dc that came from GDI+. I'd be inclined to do all the ROP stuff with GDI DC's. GDI+ doesn't support ROPs, so the GetHdc stuff worries me a little. I'll have to do some digging to see if this is actually supported.
Alternatives:
- Do your screenshot using Graphics.CopyFromScreen. Do the invert another way.
- Do the Invert to a GDI bitmap created using CreateCompatibleBitmap and then just use the resulting bitmap in GDI+ using Bitmap.FromHBITMAP.
Again, I'm not sure the GDI and GDI+ DC's are compatible for ROPs. Methinks not.
:/
Monday, July 11, 2011 3:43 AM -
DCs are compatible. XOR works inside GetDC() - ReleaseDC() pair and inside one method call.
But when you call the same Bitmap next time and creates hdc from it (by Graphics.FromImage), then the new DC differs from what it was after GetDC-ReleaseDC pair. after XOR with saved Bitmap and current screen DC : http://bit.ly/n3sYmN
What is DC basically? - just a pointer to structure with bytes buffer which is equal to Width*Height*BPP - nothing more.
Graphics object - is an instance of Graphics class, including its methods like DrawLine and such...
GetDC - takes the pointer and blocks the buffer for your drawings. XOR is just byte to byte simple operation.
Monday, July 11, 2011 10:17 AM -
>Do the Invert to a GDI bitmap created using CreateCompatibleBitmap and then just use the resulting bitmap in GDI+ using Bitmap.FromHBITMAP.
Once it saved in GDI+ Bitmap, that's it, no way. Graphics from Image just creates new instance of Graphics class based on the Bitmap color and metric details... if it would be possible to apply SelectObject to that DC with Bitmap handle, then that would work, but it's not applicable.
From other hand, if I would be able to convert .NET Bitmap object to BITMAPINFO Win32 structure, then that would work with gdi32 XORing.
Say: BitmapGdi bmp = Bitmap.ToGdiWin32();
then GetHandle and pass it to SelectObject of destination DC... that would work I believe.
Monday, July 11, 2011 10:26 AM -
Hi
GDI+ fourm should be more proper for this issue.
http://forums.asp.net/150.aspx?System.Drawing%2fGDI%2b
Cookie Luo[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Tuesday, July 12, 2011 6:56 AM -
No, thanks.
I've done it finally in managed code. Works... but it took 6 days to find out that GDIPLUS doesn't support XOR operation on GDIPLUS bitmap.
As gdi32 and Gdiplus Bitmaps are very different, and DCs as well...
they're just different.
I use DIB API and never convert it to managed bitmap if the bitmap's context is used to BitBlt on top of another GDI32 bitmap.
so if someone needs the solution - you welcome - poke me up here or in skype: robbkirk
Tuesday, July 12, 2011 4:13 PM -
As gdi32 and Gdiplus Bitmaps are very different, and DCs as well...
they just different.
Tuesday, July 12, 2011 5:33 PM -
Hi, all
All of them are useful for me!
Thank you!
Wednesday, July 13, 2011 7:38 AM