L’obiettivo è quello di inviare del testo alla stampante utilizzando i font nativi al suo interno e la libreria gdi32.dll di Windows. Questa volta integreremo tutto in una semplice applicazione in C#.
Anzitutto creiamo un semplice form con una TextBox chiamata txtTesto ed un Button chiamato btnStampa.
Aggiungiamo poi una nuova classe che estenda la classe System.Drawing.Printing.PrintDocument
1 2 3 4 5 6 7 |
class Stampante : System.Drawing.Printing.PrintDocument { public Stampante() : base() { } } |
Per usare la classe anzitutto dobbiamo implementare alcuni metodi e creare i corrispondenti per le funzioni della libreria GDI32.
A tale scopo utilizzeremo l’istruzione [DllImport("gdi32.dll")]
prima delle specifiche definizioni.
Le funzioni che dobbiamo implementare sono rispettivamente: CreateFont, SelectObject, DrawText, DeleteObject
Per maggiori riferimenti alle singole funzioni consiglio di visionare il sito Pinvoke.net
Detto tutto questo costruiamo la classe nel modo seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace EsempioStampante { class Stampante : System.Drawing.Printing.PrintDocument { private float testX, testY, testW, testH; private String testTesto; private String fontString; private int dimensione; public Stampante() : base() { } public Stampante(String testo, String font, String size, String x, String y, String w, String h) : base() { testTesto = testo; fontString = font; dimensione = Convert.ToInt32(size); testX = Convert.ToSingle(x); testY = Convert.ToSingle(y); testW = Convert.ToSingle(w); testH = Convert.ToSingle(h); } protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e) { base.OnBeginPrint(e); } [DllImport("gdi32.dll")] static extern IntPtr CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, uint fdwItalic, uint fdwUnderline, uint fdwStrikeOut, uint fdwCharSet, uint fdwOutputPrecision, uint fdwClipPrecision, uint fdwQuality, uint fdwPitchAndFamily, string lpszFace); [DllImport("gdi32.dll", EntryPoint = "SelectObject")] public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj); [StructLayout(LayoutKind.Sequential)] public struct DRAWTEXTPARAMS { public uint cbSize; public int iTabLength; public int iLeftMargin; public int iRightMargin; public uint uiLengthDrawn; } private struct RectStr { public int Left, Top, Right, Bottom; public RectStr(Rectangle r) { this.Left = r.Left; this.Top = r.Top; this.Bottom = r.Bottom; this.Right = r.Right; } } [DllImport("user32.dll")] static extern int DrawText(IntPtr hDC, string lpString, int nCount, ref RectStr lpRect, uint uFormat); [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteObject([In] IntPtr hObject); protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e) { base.OnPrintPage(e); IntPtr hdc = e.Graphics.GetHdc(); IntPtr hfEPC = CreateFont(dimensione, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fontString); IntPtr hSostituto = SelectObject(hdc, hfEPC); RectStr r = new RectStr(new Rectangle((int)testX, (int)testY, (int)testW, (int)testH)); Int32 testo = DrawText(hdc, testTesto, testTesto.Length, ref r, 0); SelectObject(hdc, hSostituto); DeleteObject(hfEPC); e.Graphics.ReleaseHdc(hdc); } } } |
Eseguiamo il test della funzione nel form principale:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
namespace EsempioStampante { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void BtnStampa_Click(object sender, EventArgs e) { Stampante stampante = new Stampante(txtTesto.Text, "Courier New", "140", "50", "50", "2500", "200"); stampante.Print(); } } } |
In questo modo stamperemo attraverso la stampante predefinita.
Nel mio caso una stampante Samsung M2070, che riconosce come font “Courier New“.