• entries
743
1924
• views
578705

# Come back C#, all is forgiven

147 views

I take it all back. Interfacing with GDI in C# is EASY!

Here's the relevant class:

using System;using System.Runtime.InteropServices;public class GDI{    [DllImport("gdi32.dll",EntryPoint="MoveToEx")]    public static extern IntPtr MoveToEx(IntPtr HDC,int X,int Y,IntPtr Point);    [DllImport("gdi32.dll",EntryPoint="LineTo")]    public static extern IntPtr LineTo(IntPtr HDC,int X,int Y);    [DllImport("gdi32.dll",EntryPoint="SetROP2")]    public static extern int SetROP2(IntPtr HDC,int Mode);    public static int R2_NOT=6;    public static int R2_COPYPEN=13;}

Here's the code in the pictureBox_paint:

private void pictureBox_Paint(object sender,PaintEventArgs e){    // top secret tile drawing code snipped    IntPtr HDC=e.Graphics.GetHdc();    GDI.SetROP2(HDC,GDI.R2_NOT);    GDI.MoveToEx(HDC,10,10,new IntPtr());    GDI.LineTo(HDC,100,100);    GDI.SetROP2(HDC,GDI.R2_COPYPEN);    e.Graphics.ReleaseHdc();}

And the result:

If you look really closely, in the top left corner of the map is a diagonal line that has been drawn with a inverse raster operation.

Happy happy happy.

I'm wondering, if I figured out how to access BitBlt in C#, if it would be any faster than Graphics.DrawImage() in C#? Thoughts?

[LATER] Interestingly, no it doesn't. I've just been comparing the .NET and C++ versions of my Map application, stress testing by scrolling a big screen being filled with 8x8 rectangles and a CreateHatchBrush() brush.

Even when the C# version imports all the Win32 API GDI calls and basically uses exactly the same functions as the C++ version, the C++ version is still substantially quicker.

Shame but never mind. The C# version is prettier and easier to develop. Swings and roundabouts, I guess. I just don't understand the reason for the difference since I thought that the .NET code was JIT compiled into native machine language when it was run and so would be basically as efficient as the C++ code.

Huh, that is kind of odd, I'd have thought the C# wouldn't perform substantially worse than the C++ version. Is JIT compiling always done by default, or do you have to specify that per-binary? Blah, some .NET wizard will probably come along and ask if you forgot to check some magical "MAKE MY APPLICATION FAST" box in some obscure page in the project settings.

Anyway. At least .NET shortens the development cycle :[

Quote:
 Original post by Mushu Blah, some .NET wizard will probably come along and ask if you forgot to check some magical "MAKE MY APPLICATION FAST" box in some obscure page in the project settings.

I hope so [smile].

From my understanding of how things work, the reason that you aren't seeing speed gains is because the managed code needs to go through the native unmanaged GDI+ DLL for every call. From my experience (and your own here), this is sorely expensive.

From my understanding of how things work, the reason that you aren't seeing speed gains is because the managed code needs to go through the native unmanaged GDI+ DLL for every call. From my experience (and your own here), this is sorely expensive.

If your interested in more details on why the C# version is slower theres some entries in Washu's journal about the costs of calling from managed into unmanaged code.

Cheers for the link, Julian90. Was a bit beyond me to be honest [smile].

HopeDagger - do you mean that even when I'm calling a GDI function, it is still having to go through the GDI+ dll? That would explain it. But if GDI+ does not support raster operations, how does using a R2_NOT pen with SetROP2() work like that?

I reckon over the weekend I'm going to write a quantitive test for this. I'll write a C++ app that stress tests the GDI and measures the framerate, then write the equivalent in C#, but do the drawing by importing the Win32 GDI functions and measure that as well.

I'll post the results and the two exes.