Thursday, August 28, 2008

How to do a CDC.Escape() in .NET

There may be ways around using the old CDC Escape function from MFC, but when you are porting C++ to C#, it is nice to just call the same Win32api functions that you were using before. For printing, I used the Escape function to get information about the printer, but since this method can return a Point structure the PInvoke was more difficult. Here is the code necessary to call the Escape method:

First you need the POINT structure defined in .NET:

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}



Then you need the Signature for the Escape method ):

[DllImport("gdi32.dll")]
private static extern int Escape(IntPtr hdc, int nEscape, int cbInput, string lpvInData, IntPtr lpvOutData);



There are also the constants that are sent as the Escape type (I just provide a couple of example that return a Point structure):

private const int GETPRINTINGOFFSET = 13;
private const int GETPHYSPAGESIZE = 12;



Then you can call the method. You can get the Graphics object from various places, but you need the HDc from it regardless:


IntPtr hDC = e.Graphics.GetHdc();
IntPtr pnt;
long stat;
POINT printingOffsetPoint = new POINT(0,0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(printingOffsetPoint));
Marshal.StructureToPtr(printingOffsetPoint, pnt, false);
stat = Escape(hDC,GETPRINTINGOFFSET, 0, null, pnt);
printingOffsetPoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);



POINT physPageSizePoint = new POINT(0, 0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(physPageSizePoint));
Marshal.StructureToPtr(physPageSizePoint, pnt, false);
stat = Escape(hDC, GETPHYSPAGESIZE, 0, null, pnt);
physPageSizePoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);

No comments: