Drucken einer Windows Form (WinForm) mit C#
Nachdem ich kürzlich in C# eine TextPrinter Klasse programmiert habe, wurde ich heute gefragt, wie man ein Windows Form, oder jede andere grafische Komponente, so wie sie auf dem Bildschirm dargestellt ist, ausdrucken kann.
Hmm..., das hab ich noch nie gemacht! Im Web findet man schnell einmal Beispiele zum Ausdrucken von Text-Dokumenten, aber in der Tat, die Beispiele für den Ausdruck von grafischen Elementen sind entweder schwer zu finden oder für den Anfänger viel zu kompliziert. Um den Einstieg in die Materie zu erleichtern habe ich deshalb das nachfolgende Beispiel mit C# unter .NET 2.0 kreiert.
Im Beispiel wird eine Windows Applikation mit einem Fenster (Form1) erstellt. Auf der Maske wird ein Button (button1) platziert, der mit Print beschriftet wird und nachstehend als "Print Button" bezeichnet wird.
Zum Druckvorgang muss man folgendes wissen. Es gibt unter .NET 2.0 eine PrintDocument Klasse. Mindestens eine Instanz dieser Klasse muss dem Projekt hinzugefügt werden. Unter Visual Studio 2005 zieht man dazu aus der Toolbox einfach die Komponente PrintDocument auf die Form im Design Mode. Dies erzeugt dann die Instanz printDocument1, die im unteren Teil des Dokumentenfensters mit der Maske angezeigt wird.
Die PrintDokument Klasse hat als wichtigste Methode die Methode Print(). Mit dem Aufruf dieser Methode wird der Druckvorgang eingeleitet. Zu diesem Zweck platzieren wir den Code für den Aufruf der Print() Methode im Click Event (button1_Click) des oben erwähnten Print Buttons. Der Code dazu lautet ganz einfach printDocument1.Print();
Wird die Print() Methode von printDocument1 aufgerufen, dann wird für jede zu druckende Seite der Event printDocument1_PrintPage so oft ausgelöst, bis es nichts mehr zu drucken gibt. Was und wie ausgedruckt wird, muss jedoch der Programmierer selbst bestimmen. Den Code dazu platziert man im entsprechenden PrintPage Event (printDocument1_PrintPage).
Jetzt ist noch wichtig zu wissen, dass der Ausdruck in jedem Fall über ein Graphics Object erfolgt das mit den Event Argumenten des Print Page Events mitgeliefert wird. Normalerweise sieht der Rumpf des PrintPage Events etwa so aus:
private void printDocument1_PrintPage(
object sender, System.Drawing.Printing.PrintPageEventArgs e) {}
In diesem Fall haben wir mit e.Graphics Zugriff auf das Graphics Objekt mit dem die Seite gedruckt wird.
Um unsere Aufgabe zu lösen, geht es also darum, die grafische Darstellung unseres Fenster auf das e.Graphics Objekt zu übertragen. Eine Möglichkeit dies zu tun besteht darin, dass wir von unserem Fenster mit der Methode DrawToBitmap, die in allen Controls zur Verfügung steht, eine Bitmap erzeugen und diese dann mit der Methode DrawImage von e.Graphics zeichnen lassen, was hiermit bedeutet, dass unsere Bitmap dabei ausgedruckt wird. Diesen Vorgang können wir mit nur drei Befehlen durchführen. Die verfügbaren Parameter helfen uns dabei die richtige Grösse zu bestimmen und unsere Bitmap auf dem Ausdruck innerhalb der Seite und mit einem Abstand von den Rändern zu platzieren.
Wäre unsere Bitmap grösser als eine Seite, dann müssten wir noch die Logik programmieren, die erforderlich ist um die Bitmap aufzuteilen und über mehrere Seiten verteilt auszudrucken. Solche Programme können dann schon recht komplex werden. An diese Stelle geht es aber nur darum an einem einfachen Beispiel aufzuzeigen, wie das Prinzip funktioniert.
Vorgehen in 7 Schritten:
1. Neue Applikation PrintDemo mit Maske Form1 erstellen
2. Aus Toolbox PrintDocument hinzufügen
-> printDocument1
3. Doppelcklick auf printDocument1
-> printDocument1_PrintPage Event Handler
4. Print Button hinzufügen und Doppelcklick
-> button1_Click
5. In button1_Click Event Code zum Aufruf von printDocument1.Print() hinzufügen.
6. printDocument1_PrintPage Event Code zum Drucken der Bitmap der aktuellen Komponente hinzufügen.
// a. Neue Bitmap mit den Abmessungen der aktuellen Komponente erstellen
Bitmap b = new Bitmap(this.Width, this.Height);
// b. Aktuelle Komponente unter Einhaltung der Seitenbegrenzungen
// des Ausdrucks in die neu erstellte Bitmap zeichnen
this.DrawToBitmap(b, e.PageBounds);
// c. Bitmap mit Abstand 15 von links und 50 von oben zeichnen (= drucken)
e.Graphics.DrawImage(b, new Point(15, 50));
7. Testen
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace PrintDemo {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
///
/// PrintPage Event von printDocument1.
/// Leere Vorlage wird durch Doppelclick auf Komponente
/// printDocument1 (Schritt3) automatisch erzeugt.
/// </summary>
/// <param name="sender">
/// <param name="e">
/// <remarks>
/// Wird von der Print() Methode mit jeder zu druckenden
/// Seite als Callback Methode aufgerufen.
/// </remarks>
private void printDocument1_PrintPage(
object sender, System.Drawing.Printing.PrintPageEventArgs e) {
// Schritt 6:
// Neue Bitmap mit den Abmessungen der zu druckenden
// Komponente erstellen
Bitmap b = new Bitmap(this.Width, this.Height);
// Zu druckende Komponente unter Einhaltng der
// Seitenbegrenzungen des Ausdrucks in die neu
// erstellte Bitmap zeichnen.
this.DrawToBitmap(b, e.PageBounds);
// Bitmap mit Abstand 15 von links und 50 von oben
// zeichnen, bzw. drucken (e.Graphics ist dabei das
// eigentliche Graphics Objekt, das gedruckt wird).
e.Graphics.DrawImage(b, new Point(15, 50));
}
/// <summary>
/// Click Event von Print Button (button1).
/// Schritt 4: Leere Vorlage wird durch Doppelclick
/// auf Komponente button1 automatisch erzeugt.
/// </summary>
/// <param name="sender">
/// <param name="e">
private void button1_Click(object sender, EventArgs e) {
// Schritt 5: Aufruf der Print() Methode von printDocument1.
printDocument1.Print();
}
}
}
4.9.2006 /pg