[C#] Screenshot von Form / Control erstellen und Drucken

Drucken
( 1 Vote )
Hauptkategorie: Programmieren Kategorie: C#
Erstellt am 17.07.2012 Zuletzt aktualisiert am 13.01.2014 Geschrieben von Jonny132
In der Praxis kommt es des öfteren vor, dass Benutzer Screenshots eines Programmes erstellen und ausdrucken, um auf diese dann Notizen machen zu können bzw an Sachbearbeiter weitergeben zu können.

Da der normale Benutzer nicht immer mit der Druck- bzw Alt+Druck-Taste vertraut ist, wollen wir ihm eine einfache Möglichkeit geben, den Screenshot und das Drucken im Programm automatisiert zu erledigen.

Dazu erstellen wir eine neue statische Klasse mit dem Namen Print, welche einen privaten statischen Member vom Typ Control besitzt welches wir Drucken wollen (Da eine Form ebenfalls vom Typ Control erbt, können wir ebenfalls Screenshots vom Typ Form drucken).

Grundgerüst Statische Print - Klasse:
        using System.Drawing.Printing;
using System.Drawing.Imaging;

public static class Print { private static Control m_ControlToPrint; }
In dieser Klasse, erstellen wir nun eine Statische Methode namens 'PrintControl', welche als Übergabeparameter das Control welches wir drucken wollen und die PrinterSettings enthält.
Wie man den Benutzer selber die Möglichkeit bietet Druckereinstellungen auszuwählen könnt ihr euch hier ansehen:
[C#] Eigener Druckerdialog erstellen

PrintControl - Methode:
            public static void PrintControl(Control control, PrinterSettings printerSettings)
            {
                m_ControlToPrint = control;
                using (PrintDocument printDoc = new PrintDocument())
                {
                    printDoc.PrinterSettings = printerSettings;
                    printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
                    printDoc.DocumentName = "Screenshot";
                    printDoc.DefaultPageSettings.Margins = new Margins(50,50,50,50);
                    printDoc.DefaultPageSettings.Landscape = (m_ControlToPrint.Width > m_ControlToPrint.Height);
                    printDoc.DefaultPageSettings.Color = printDoc.PrinterSettings.DefaultPageSettings.Color;
                    printDoc.PrintController = new StandardPrintController();
                    printDoc.Print();
                    printDoc.PrintPage -= new PrintPageEventHandler(printDoc_PrintPage);
                }
            }
Zuerst wird das Control und die PrinterSettings zugewiesen. In einem using - Block wird eine Instanz der PrintDocument - Klasse erstellt.
Wir abbonieren das PrintPage - Ereignis in der wir den Screenshot unseres Controls Drucken und setzten gewisse Einstellungen. Diese müssten für sich selbst sprechen.

Am Ende wird noch die Print - Methode des PrintDocuments aufgerufen, welche den Druck startet bzw das PrintPage - Ereignis auslöst. Dieses Ereignis deregistrieren wir zu Schluss noch.

PrintPage - Ereignis:
            private static void printDoc_PrintPage(object sender, PrintPageEventArgs e)
            {
                Image bmp = CaptureControl(m_ControlToPrint);
                int height = (bmp.Height * e.MarginBounds.Width) / bmp.Width;
                Rectangle destRect;
                if (height > e.MarginBounds.Height)
                {
                    destRect = new Rectangle(e.MarginBounds.X, e.MarginBounds.Y,
                        (bmp.Width * e.MarginBounds.Height) / bmp.Height,
                        e.MarginBounds.Height);
                }
                else
                {
                    destRect = new Rectangle(e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.Width,
                        height);
                }
                e.Graphics.DrawImage(bmp, destRect);
            }
Hier rufen wir eine kleine statische Hilfsfunktion CaptureControl auf, welche uns den Screenshot des Controls bzw der Form als Image zurückgibt. Mit dieser Information können wir uns die Dimension des zu Druckenden Bildes ausrechnen und in eine Rectangle - Variable speichern, welche wir dann per e.Graphics.DrawImage übergeben können.

Alles was wir per e.Graphics 'zeichnen', wird später auf dem Druck zu sehen sein.

Capture Control - Funktion:
            private static Bitmap CaptureControl(Control ctl)
            {
               Bitmap bitmap = new Bitmap(ctl.Width, ctl.Height);
               ctl.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
               return bitmap;
            }
Diese Funktion liefert als Ergebnis ein Screenshot des übergebenen Controls per CopyFromScreen zurück.
Somit wäre unsere statische Klasse vollständig und kann aufgerufen werden.

Aufrufbeispiel (Button Klick - Ereignis einer Form):
Print.PrintControl(this, new PrinterSettings());

  • Onpeex

    schrieb am 2014-01-13 18:18:31

    haha verdammt ich noch mal auch alle neuen posts weg es liegt an dem Browser den ich hier drin habe :(

    Auf Kommentar antworten

    • Jonny132

      schrieb am 2014-01-14 10:34:43

      Hallo Kevin,

      die Kommentare werden von mir manuell freigeschalten, da es öfters Spam-Attacken gibt, deshalb werden sie nicht sofort dargestellt.

      Ich glaube somit wird es doch ein Forumsthema, denn so kann ich dir leider nicht helfen.

      Poste dort bitte nochmals dein anliegen + Code + am besten die designer.cs der Form, dann kann ich das nachvollziehen :)

      Danke

      Auf Kommentar antworten

  • Onpeex

    schrieb am 2014-01-13 18:02:52

    Hay ich bins Kevin ;)

    muss da mal meinen Post verbessern da doch mein Button dargestellt wird jedoch nur wenn er ist der ersten Zeile ist also ganz oben an der Form.
    Tausche ich jetzt Label gegen Button wird nur das Labe angezeigt weil es oben steht.

    Auf Kommentar antworten

  • Kevin

    schrieb am 2014-01-13 12:36:51

    Hallo, Danke erstmal :)

    gibt es auch die Möglichkeit das nur die Form gedruckt wird auch wenn ein andres Fenster darüber ist :/

    Auf Kommentar antworten

    • Jonny132

      schrieb am 2014-01-13 12:48:11

      Hallo Kevin,

      ein Workaraund wäre, die Form mittels der TopMost-Eigenschaft zuerst in den Vordergrund zu bringen und danach die Eigenschaft wieder auf false zu setzen. Einen eleganten Weg sehe ich leider nicht, denn Screenshot besagt ja, dass er das was auf dem Bildschirm (Screen) angezeigt wird, drucken soll und nicht das was sich irendwo dahinter versteckt.

      sg

      Auf Kommentar antworten

      • Kevin

        schrieb am 2014-01-13 12:55:21

        Okay und kennt Ihr jetzt noch eine andere Möglichkeit müsste den Screen auch nicht mal speichern da ich ihn direkt in der Anwendung auch auswerten möchte.

        Auf Kommentar antworten

        • Kevin

          schrieb am 2014-01-13 17:48:10

          Hay, Danke leider ist jedoch zwar die Form zu sehen also auch der Rand Name und das Close etc. Jedoch nicht das was in der Form ist also Keine Button oder so

        • Jonny132

          schrieb am 2014-01-13 15:07:07

          Hallo nochmals,
          anscheinend gibts doch eine einfache und schöne Version.
          Ich habe im Tutorial die CaptureControl-Funktion umgeschrieben.

          Versuche diese mal aus :)

          sg

        • Jonny132

          schrieb am 2014-01-13 14:51:20

          Wie gesagt ohne diese Workarounds, wirds ohne weiteres nicht klappen.
          Was meinst du nicht speichern?! In irgend eine Variable musst du das Bitmap bzw. den Screenshot speichern.

          Falls das Thema noch weiterverfolgt werden soll, bitte ich dich einen Forumsbeitrag zu erstellen, denn hier ist nicht wirklich der richtige Ort um solchiges zu besprechen ;)

          Danke

Veröffentlichen Sie ihre Kommentare ...