Guten morgen torkel!
Als erstes: musst Du den kompletten Code verstehen?
Naja, ich hab Dir versprochen intensiver zu helfen, also...
- Es gibt in dieser Klasse 1 öffentliche Methode, einmal überladen (PrintControl()).
- Einmal mit dem Aufrufparameter "Control" und einmal "Control" + "spez. Drucker"
- Beim ersten wird meines Erachtens der Standarddrucker benutzt, beim 2. benötigst Du den Druckernamen (z.B: aus System.Drawing.Printing.PrinterSettings.InstalledPrinters).
- Die erste Überladung ruft die 2. auf mit dem zweiten Parameter = "null" -> spart doppelter Code
Dann gehts so in der Methode weiter...
//erstelle das PrintDoc
PrintDocument doc=new PrintDocument();
//Wenn ein PrinterName übergeben wurde ändere den Printer für dieses Doc
if (pPrinterName!=null && pPrinterName!=string.Empty)
{
doc.PrinterSettings.PrinterName=pPrinterName;
}
Ein Print-dokument erstellen und den Printer festlegen, bei == "null" wird Standarddrucker benutzt.
//PrintPage anschnallen
doc.PrintPage+=new PrintPageEventHandler(doc_PrintPage);
Eine neue Ereignisbehandlungsroutine wird hier festgelegt. Bei eintreten des Ereignises
PrintPage vom Print-Dokument wird in die Methode "doc_PrintPage()" gesprungen. (Wird hier nur festgelegt, nicht ausgeführt!)
//Quellobjekte für den Kopiervorgang erstellen
Graphics gSource=Graphics.FromHwnd(pCtrl.Handle);
Rectangle rectSource=pCtrl.ClientRectangle;
_ImageToPrint=new Bitmap(rectSource.Width,rectSource.Height,gSource);
In diesen Zeilen wird direkt das Handle auf ein Control geholt und weitere Objekte wie zunächst das
Rectangle und dann das
Bitmap erzeugt, die im Folgenden dann noch mit Inhalt gefüllt und später dann das bmp ausgedruckt wird.
In C/C++ Zeiten konnte man das mit Pointern lösen, hier ist das etwas .NET-like angepasst.
//Source hdc erstellen
IntPtr hdcSource=gSource.GetHdc();
Ich vermute, dass hdc hardcopy heißen soll. Hier wird also ein Objekt "hdcSource" erstellt, das gleich mit dem Hardcopy des angegebenen Controls verknüpft wird. Hier wird meines Erachtens sozusagen wieder nur "Pointer" festgelegt, noch kein Inhalt transferiert.
//Zielobjekte für den Kopiervorgang erstellen
Graphics gTarget=Graphics.FromImage(_ImageToPrint);
IntPtr hdcTarget=gTarget.GetHdc();
Analog zu den Quellenobjekten wird hier das gleiche für die Zielobjekte gemacht.
//per BitBlt das Image vom hdcSource auf hdcTarget kopieren
BitBlt(hdcTarget,0,0,rectSource.Width,rectSource.Height,hdcSource,0,0,SRCCOPY);
HIER wird der Kopiervorgang durchgeführt in das Zielobjekt auf Bitbasis. Was die Konstante (letzter Parameter) macht weiss ich nicht, das müsste man in der Doku finden. Das ist eine Methode die zuvor per DLL-Import bekannt gemacht wurde. In den vorigen Beiträgen wurde ja erklärt, was die "gdi32.dll" ist.
//verwendete objekte freigeben
gSource.ReleaseHdc(hdcSource);
gTarget.ReleaseHdc(hdcTarget);
//Druck synchron auslösen
doc.Print();
//Druck wurde durchgeführt
//PrintPage abschnallen
doc.PrintPage-=new PrintPageEventHandler(doc_PrintPage);
_ImageToPrint=null;
Das dürfte jetzt wieder einfach sein. Die "Pointer" also das Handle direkt auf die Objekte wieder freigeben, den Druck auslösen und anschließend dem Event-Handler die am Anfang bereitgestellte Methode wieder entziehen (auch hier bedeutet das Ressourcenfreigabe).
Wenn ich nicht falsch liege, dann wird bei "doc.Print()" auch das Ereignis ausgelöst, und springt in "doc_PrintPage()" in der dann auch der eigentliche Druck als Druck-eine-Grafik-Anweisung ausgeführt wird.
Die komplette Methode ist hierbei mit einem
lock{} versehen, was dazu führt, wenn gleichzeitig dieselbe Methode aufgerufen wird, dass die Ausführungen dieser Methode immer komplett und damit nacheinander ausgeführt werden. Das ist deshalb notwendig, weil
a) Handles erzeugt werden, was dazu führt, dass diese Objekte blockiert sind, und sich ein Dead-Lock ereignen könnte, und
b) weil für die Methode "doc_PrintPage()" die Variable
_ImageToPrint benutzt wird, die bei einem "gleichzeitigen" benutzen total verpfuscht werden würde.
Quintessenz:
Du bist sicherlich noch nicht so weit, dass Du solchen Code in .NET selbst schreiben kannst, wenn ich das richtig weiss hast Du erst vor kurzem mit C# angefangen. Aber Dir sind die Prinzipien von Programmierung bekannt, und kannst sicherlich etwas mit meinen Erläuterungen anfangen.
@An alle:
Bitte korrigiert mich, wenn meine Erklärungen hier falsch waren, ich bin auch (noch nicht) DER WinForms- und Controls-Programmierer, dass ich das im ersten Moment 100%ig verstanden hätte.
Ciao und gute Nacht
Norman-Timo
[EDIT
Ja, jetzt hab ich viel erklärt, aber noch nicht Deine Frage beantwortet ;-)
Diesen Code nach belieben in Dein Projekt einfügen.
Dann kannst Du durch aufrufen von "PrintControl(myWinForm2);" das Form2 ausdrucken. Du brauchst Dich um nix kümmern, der Rest wird erledigt...
[/EDIT]