A
Abhishek R Prajapati
Guest
I am using ExtTextOut wingdi function to draw text. Also, I am using SetWorldTransform for scaling text but now I want to rotate text(at all angles) too. How can I change/pass parameters to it so it will scale as well as rotate too.
I am using this code to draw text:
var inputString = "Sample text";
var fontSize = 31f;
var font = new Font("Avenir Black", fontSize, new FontStyle());
var startX1 = 50;
var startY1 = 50;
LOGFONT lf = new LOGFONT();
font.ToLogFont(lf, e.Graphics);
IntPtr hPrinterDC = e.Graphics.GetHdc();
StringBuilder sbText = new StringBuilder(inputString);
if (hPrinterDC != IntPtr.Zero)
{
int nPrintHorzRes = GetDeviceCaps(hPrinterDC, HORZRES);
int nPrintVertRes = GetDeviceCaps(hPrinterDC, VERTRES);
int nPhysWidth = GetDeviceCaps(hPrinterDC, PHYSICALWIDTH);
int nPhysHeight = GetDeviceCaps(hPrinterDC, PHYSICALHEIGHT);
int nPhysOffsetX = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETX);
int nPhysOffsetY = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETY);
IntPtr hDCScreen = GetDC(IntPtr.Zero);
float nLogPixelsXScreen = GetDeviceCaps(hDCScreen, LOGPIXELSX);
float nLogPixelsYScreen = GetDeviceCaps(hDCScreen, LOGPIXELSY);
ReleaseDC(hDCScreen, IntPtr.Zero);
float nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
float nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
float nScaleX = Math.Max(nLogPixelsXScreen, nLogPixelsXPrinter) / Math.Min(nLogPixelsXScreen, nLogPixelsXPrinter);
float nScaleY = Math.Max(nLogPixelsYScreen, nLogPixelsYPrinter) / Math.Min(nLogPixelsYScreen, nLogPixelsYPrinter);
System.Drawing.Drawing2D.Matrix transform = new System.Drawing.Drawing2D.Matrix();
transform.Scale(nScaleX, nScaleY);
XFORM renderTransform = new XFORM();
var elements = transform.Elements;
var m11 = elements[0];
var m12 = elements[1];
var m21 = elements[2];
var m22 = elements[3];
var dx = elements[4];
var dy = elements[5];
renderTransform.eM11 = (float)m11;
renderTransform.eM12 = (float)m12;
renderTransform.eM21 = (float)m21;
renderTransform.eM22 = (float)m22;
int nOffsetX = 0;
int nOffsetY = 0;
renderTransform.eDx = (float)transform.OffsetX + nOffsetX;
renderTransform.eDy = (float)transform.OffsetY + nOffsetY;
SetGraphicsMode(hPrinterDC, GM_ADVANCED);
SetMapMode(hPrinterDC, MM_TEXT);
bool bRet = SetWorldTransform(hPrinterDC, ref renderTransform);
var startX2 = startX1;
var startY2 = startY1;
RECT rc = new RECT(startX2, startY2, nPhysWidth, nPhysHeight);
SetViewportOrgEx(hPrinterDC, -nPhysOffsetX, -nPhysOffsetY, IntPtr.Zero);
lf.lfHeight = (int)(lf.lfHeight / nScaleY);
IntPtr hFontNew = CreateFontIndirect(lf);
IntPtr hFontOld = SelectObject(hPrinterDC, hFontNew);
SetBkMode(hPrinterDC, TRANSPARENT);
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Blue));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Green));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
var nExtra = -10.0f / nScaleX;
SetTextCharacterExtra(hPrinterDC, (int)nExtra);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Red));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
SelectObject(hPrinterDC, hFontOld);
DeleteObject(hFontNew);
}
Below are the pinvokes used in above code sample:
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetWorldTransform(IntPtr hdc, ref XFORM lpxf);
[StructLayout(LayoutKind.Sequential)]
public struct XFORM
{
public float eM11;
public float eM12;
public float eM21;
public float eM22;
public float eDx;
public float eDy;
}
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetGraphicsMode(IntPtr hdc, int iMode);
public const int GM_COMPATIBLE = 1;
public const int GM_ADVANCED = 2;
public const int GM_LAST = 2;
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
public const int TRANSPARENT = 1;
public const int OPAQUE = 2;
public const int BKMODE_LAST = 2;
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetBkMode(IntPtr hdc, int mode);
A.R.Prajapati
Continue reading...
I am using this code to draw text:
var inputString = "Sample text";
var fontSize = 31f;
var font = new Font("Avenir Black", fontSize, new FontStyle());
var startX1 = 50;
var startY1 = 50;
LOGFONT lf = new LOGFONT();
font.ToLogFont(lf, e.Graphics);
IntPtr hPrinterDC = e.Graphics.GetHdc();
StringBuilder sbText = new StringBuilder(inputString);
if (hPrinterDC != IntPtr.Zero)
{
int nPrintHorzRes = GetDeviceCaps(hPrinterDC, HORZRES);
int nPrintVertRes = GetDeviceCaps(hPrinterDC, VERTRES);
int nPhysWidth = GetDeviceCaps(hPrinterDC, PHYSICALWIDTH);
int nPhysHeight = GetDeviceCaps(hPrinterDC, PHYSICALHEIGHT);
int nPhysOffsetX = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETX);
int nPhysOffsetY = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETY);
IntPtr hDCScreen = GetDC(IntPtr.Zero);
float nLogPixelsXScreen = GetDeviceCaps(hDCScreen, LOGPIXELSX);
float nLogPixelsYScreen = GetDeviceCaps(hDCScreen, LOGPIXELSY);
ReleaseDC(hDCScreen, IntPtr.Zero);
float nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
float nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
float nScaleX = Math.Max(nLogPixelsXScreen, nLogPixelsXPrinter) / Math.Min(nLogPixelsXScreen, nLogPixelsXPrinter);
float nScaleY = Math.Max(nLogPixelsYScreen, nLogPixelsYPrinter) / Math.Min(nLogPixelsYScreen, nLogPixelsYPrinter);
System.Drawing.Drawing2D.Matrix transform = new System.Drawing.Drawing2D.Matrix();
transform.Scale(nScaleX, nScaleY);
XFORM renderTransform = new XFORM();
var elements = transform.Elements;
var m11 = elements[0];
var m12 = elements[1];
var m21 = elements[2];
var m22 = elements[3];
var dx = elements[4];
var dy = elements[5];
renderTransform.eM11 = (float)m11;
renderTransform.eM12 = (float)m12;
renderTransform.eM21 = (float)m21;
renderTransform.eM22 = (float)m22;
int nOffsetX = 0;
int nOffsetY = 0;
renderTransform.eDx = (float)transform.OffsetX + nOffsetX;
renderTransform.eDy = (float)transform.OffsetY + nOffsetY;
SetGraphicsMode(hPrinterDC, GM_ADVANCED);
SetMapMode(hPrinterDC, MM_TEXT);
bool bRet = SetWorldTransform(hPrinterDC, ref renderTransform);
var startX2 = startX1;
var startY2 = startY1;
RECT rc = new RECT(startX2, startY2, nPhysWidth, nPhysHeight);
SetViewportOrgEx(hPrinterDC, -nPhysOffsetX, -nPhysOffsetY, IntPtr.Zero);
lf.lfHeight = (int)(lf.lfHeight / nScaleY);
IntPtr hFontNew = CreateFontIndirect(lf);
IntPtr hFontOld = SelectObject(hPrinterDC, hFontNew);
SetBkMode(hPrinterDC, TRANSPARENT);
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Blue));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Green));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
var nExtra = -10.0f / nScaleX;
SetTextCharacterExtra(hPrinterDC, (int)nExtra);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Red));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
SelectObject(hPrinterDC, hFontOld);
DeleteObject(hFontNew);
}
Below are the pinvokes used in above code sample:
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetWorldTransform(IntPtr hdc, ref XFORM lpxf);
[StructLayout(LayoutKind.Sequential)]
public struct XFORM
{
public float eM11;
public float eM12;
public float eM21;
public float eM22;
public float eDx;
public float eDy;
}
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetGraphicsMode(IntPtr hdc, int iMode);
public const int GM_COMPATIBLE = 1;
public const int GM_ADVANCED = 2;
public const int GM_LAST = 2;
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
public const int TRANSPARENT = 1;
public const int OPAQUE = 2;
public const int BKMODE_LAST = 2;
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetBkMode(IntPtr hdc, int mode);
A.R.Prajapati
Continue reading...