Hallo,
besteht die Möglichkeit ein Windows Control zu drucken? Ich arbeite mit ZedGraph von Sourcefourge.net und erzeuge mir damit ein Diagramm. Nun möchte ich gerne dieses Diagramm drucken. Allerdings möchte ich nicht im Quellcode von ZedGraph herumpfuschen. Den Graph selber kann man als Image speichern, was aber nur über Rechte Maustaste->Kontextmenue geht. Kann ich ein Control an den Drucker übergeben?
Schon mal danke.
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Die Idee, das Control an den Drucker zu übergeben war wohl ne Schnapsidee. 🙁
Jetzt hatte ich mir überlegt, das Diagramm Control an eine neue Form zu übergeben und diese neue Form zu drucken ohne sie dabei anzuzeigen. Allerdings finde ich da keinen Zugang. In der MSDN wird auch nix über Screenshot oder ählichem geschrieben.
Heisst das der Drucker kann nur Graphics Elemente verarbeiten und es ist absolut unmöglich das Control irgendwie zu drucken? X(
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Gibt es keinen Weg, irgendwie die Paint Methode eines jeden Controls aufzurufen und der das Papier als Unterlage mitzugeben?
Das wäre SUPER! Dann könnte man auch treeviews zum beispiel wunderbar drucken(dass es da noch Probleme mit sichtbar und so gibt ist mir klar, aber das kann man ja in den Griff kriegen!)
Grüße Quallo
http://msdn.microsoft.com/library/deu/default.asp?url=/library/DEU/dv_vbcode/html/vbtskCodeExamplePrintingForm.asp
Habe jetzt versucht das Beispiel aus VB nach C# zu übertragen, aber in VB hab ich null Wissen. Kann mir im Beispiel nicht jede Codezeile erklären. Hier mal meine Adaption. Hoffe mir kann man dabei helfen.
private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics grfx = e.Graphics;
Graphics g = this.CreateGraphics();
Size s = this.Size;
bitmap = new Bitmap(s.Width, s.Height, g);
Graphics mg = Graphics.FromImage(bitmap);
Graphics pgrfx = grfx;
e.Graphics.DrawImage(bitmap,0,0);
}
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Ich habe kurz ein lauffähiges Sample in C# hingemalt....
Vorteil: Du kannst auch nur ein Control drucken ....
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
namespace WindowsApplication23
{
/// <summary>
/// Summary description for PrintScreen.
/// </summary>
public class PrintFunctions
{
public PrintFunctions()
{
}
[DllImport("gdi32.dll")]
private static extern long BitBlt(
IntPtr hdcDest,
int xDest,
int yDest,
int nWidth,
int nHeight,
IntPtr hdcSource,
int xSrc,
int ySrc,
Int32 dwRop);
const int SRCCOPY=13369376;
private Image _ImageToPrint;
/// <summary>
/// Druckt ein Control (oder Form)
/// </summary>
/// <param name="pCtrl">Das zu druckende Control</param>
public void PrintControl(Control pCtrl)
{
this.PrintControl(pCtrl,null);
}
/// <summary>
/// Druckt ein Control (oder Form) auf einen speziellen Drucker
/// </summary>
/// <param name="pCtrl">Das zu druckende Control (oder Form)</param>
/// <param name="pPrinterName">Der Name des Druckers (z.B: aus System.Drawing.Printing.PrinterSettings.InstalledPrinters)</param>
public void PrintControl(Control pCtrl, string pPrinterName)
{
//weil wir eine Variable auf Klassenebene verändern
//gegen andere Threads blocken
lock(this)
{
//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;
}
//PrintPage anschnallen
doc.PrintPage+=new PrintPageEventHandler(doc_PrintPage);
//Quellobjekte für den Kopiervorgang erstellen
Graphics gSource=Graphics.FromHwnd(pCtrl.Handle);
Rectangle rectSource=pCtrl.ClientRectangle;
_ImageToPrint=new Bitmap(rectSource.Width,rectSource.Height,gSource);
//Source hdc erstellen
IntPtr hdcSource=gSource.GetHdc();
//Zielobjekte für den Kopiervorgang erstellen
Graphics gTarget=Graphics.FromImage(_ImageToPrint);
IntPtr hdcTarget=gTarget.GetHdc();
//per BitBlt das Image vom hdcSource auf hdcTarget kopieren
BitBlt(hdcTarget,0,0,rectSource.Width,rectSource.Height,hdcSource,0,0,SRCCOPY);
//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;
}
}
/// <summary>
/// Wird für jede zu druckende Seite aufgerufen
/// </summary>
/// <param name="sender">der sender</param>
/// <param name="e">die PrintPageEventArgs, in welche das Image gepinselt werden muss</param>
private void doc_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(_ImageToPrint,0,0);
}
}
}
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo Programmierhans,
erst einmal nen fettes THX für die Mühe die du dir gemacht hast. Leider will es bei mir nicht laufen. Bei dieser Codezeile
//Zielobjekte für den Kopiervorgang erstellen
_ImageToPrint=new Bitmap(rectSource.Width,rectSource.Height,gSource);
steigt der Debugger mit der Meldung:
_
Eine nicht behandelte Ausnahme des Typs 'System.InvalidOperationException' ist in system.drawing.dll aufgetreten.
Zusätzliche Informationen: Das Objekt wird zur Zeit anderswo verwendet._
aus.
Ich habe deine Klasse direkt eingebunden, will heissen: Beim entsprechenden Klick erzeuge ich eine neue Instanz, übergebe ihr die Form oder das Control mit dem Aufruf PrintFunctions.PrintControl(this);. Ich glaube nicht das es notwendig sein sollte von deiner Klasse zu erben, oder irre ich mich da?
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Original von dschmoegner
Hallo Programmierhans,erst einmal nen fettes THX für die Mühe die du dir gemacht hast. Leider will es bei mir nicht laufen. Bei dieser Codezeile
//Zielobjekte für den Kopiervorgang erstellen _ImageToPrint=new Bitmap(rectSource.Width,rectSource.Height,gSource);
steigt der Debugger mit der Meldung:
_
Eine nicht behandelte Ausnahme des Typs 'System.InvalidOperationException' ist in system.drawing.dll aufgetreten.Zusätzliche Informationen: Das Objekt wird zur Zeit anderswo verwendet._
aus.
Sorry das war mein Fehler.... hatte den ganzen Code sauber aufgebaut und dann aber zur Dokumentation die Zeilen neu geordnet (zuerst Source-Objekte dann Target-Objekte).... tja dann leider nicht mehr getestet....
Es liegt nur an der Reihenfolge der Zeilen..... habs im Originalbeitrag korrigiert
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Danke, das hat mir sehr viel weiter geholfen. Wobei mir die Sache mit Quelle und Ziel auch hätte auffallen müssen.
Die gdi32.dll, stamm die aus der MFC?
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
gdi steht für Graphical Display Interface und ist ein BetriebssystemFile (MFC verwendet dieses auch)
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Original von Noodles
Original von Programmierhans
gdi steht für Graphical Display InterfaceNicht ganz,
>
OK thx Noodles .....
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
brauch ich diesen ganzen code um eine form zu printen? oder gibts da schon was einfacheres evt. mit .NET 2?
mfg
Original von torkel
brauch ich diesen ganzen code um eine form zu printen? oder gibts da schon was einfacheres evt. mit .NET 2?mfg
Da kriegst Du eine Lösung frei Haus geliefert.... und bist nicht mal zufrieden 🤔
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
hi... dieser code ist für mich leider nicht verständlich...
wie kann ich denn sagen, dass er mir genau der inhalt dieser form zb. form2 drucken soll und wie starte ich den druck???
mfg
Guten morgen torkel!
Als erstes: musst Du den kompletten Code verstehen?
Naja, ich hab Dir versprochen intensiver zu helfen, also...
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]
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
@norman_timo
Danke für's erklären... insgesamt hast Du es recht gut erklärt 👍 wenn auch im Detail nicht ganz alles korrekt war (vernachlässigbar)....
hdc ist aber keine hardcopy sondern ein
Handle auf einen Device Context
Device Context = Gerätecontext
Der Gerätekontext ist eine auf Windows GDI basierende Struktur, die eine Gruppe von grafischen Objekten und deren zugeordnete Attribute sowie die Grafikmodi definiert, die sich auf die Ausgabe auswirken.
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo zusammen,
bin auch noch ein relativer Neuling in C#, und hatte auch das problem das ich eine Druckroutine gesucht habe. Bei mir ist es so, das ich als Hintergrundbild ein Formular habe, und als auszufüllende Felder in dem Formular Textboxen in die Form gesetzt habe.
Hab den oben geposteten Code in mein Projekt kopiert, klappt alles eigentlich super, bei mir druckt er nur komischweise Teile des Bildschirm mit (die Taskleiste). Vielleicht kann mir jemand erklären warum er das macht, wäre super.
LG, Dennis
Ein Formular als Hintergrundbild? Das versteh ich net so ganz.
Dein Problem hatte ich, als ich versucht hatte das Control, für den User nicht sichtbar, zu manipulieren und dann zu drucken. Ich denke mal das hängt mit dem Fensterhandle zusammen. Wenn mich nicht alles täuscht wird es aus dem Windows Forms gewonnen aus dem der Druck angestossen wird. Controls die in anderen Windows Forms untergebracht waren konnten nicht gedruckt werden. Dies ist zumindestens meine Erfahrung.
Gruss dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Hi,
vielleicht habe ich mich etwas komisch ausgedrückt. Das Fenster (Form) das ich drucken möchte bekommt von mir ein Hintergrundbild in Form eines Formulars (wie z.B. einen Antrag, Vertrag etc.). Dann setze ich Textboxen auf die Form, die die auszufüllenden Felder des 'Formulars' darstellen. Am Schluss soll dann das ganze ausgedruckt werden.
Beim Drucken dann habe ich das oben genannte Problem das er nicht nur den Inhalt der Form druckt, sondern Teile des restlichen Bildschirms gleich mit.
Grüße..
Was übergibst der Druckmethode als Control? Dein gesammtes Programmfenster?
Ansich würd ich nach deiner Beschreibung mir eher ein Drucklayout selber bauen. Ich habe für den inneren Rahmen des Drucklayoutes die Berechnung aus Windows Programmierung mit C# von Charles Petzold verwendet. Alles was ich drucken möchte wird in Rectangles gepackt, denn damit lassen sich die einzelnen Elemente wunderbar positionieren.
Warum er bei dir den Restbildschirm mitdruckt, kann ich jetzt auf Anhieb nicht sagen.
Grüsse dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Habs mit verschiedenen Controls probiert. Zuerst habe ich die ganze Form übergeben. Beim zweiten Versuch habe ich alles auf ein Panel gepackt, und dann dieses Panel übergeben. Gleiches Ergebnis.
Wenn es so halt nicht klappt, muss ich mir wohl oder übel ein Drucklayout basteln, dies hier wäre halt eine sehr komfortable Variante gewesen..
Danke schon mal für die bisherige Hilfe.
Verwendust Du ein Scale ?
Hast Du mal versucht AutoScale des Forms auszuschalten ?
Wie sieht es aus wenn Du ein leeres Form1 druckst ?
Was für eine Screen-Auflösung verwendest Du ?... schon mal mit 1024*768 probiert ?
Was für einen WindowState hat das Form wenn Du es druckst ?
Ich will Dich nicht quälen, aber versuchen herauszufinden wieso da was falsch läuft...
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hi,
meine Auflösung : 1280*1024
AutoScale ist auf none.
WindowState : normal
Hab jetzt rausgefunden das er da wirklich nur Probleme macht wenn die Form größer ist als die sichtbare Fläche des Bildschirms. Dann druckt er anstatt dem verdeckten Teil der Form (der aus dem Bilschirm rausragt) den unteren Bilschirmrand. Was mich allerding ein wenig wundert.
Danke für eure Hilfe..und gequält fühle ich mich nicht, finds ja super das ihr euch so bemüht.
Gruß, Dennis
hallo
erstmals danke für die gute beschreibung. ich verstehe es noch immer nicht ganz, aber zumindest einiges besser als vorher.
aber das mit dem aufrufen klappt noch nicht:
PrintControl(myWinForm2)
ich hab jetzt den kompletten code von programmierhans eingefügt und wollte es dann über den oben genanten code aufrufen... ging aber net.
was mache ich falsch?
greetz
Original von torkel
ich hab jetzt den kompletten code von programmierhans eingefügt und wollte es dann über den oben genanten code aufrufen... ging aber net.
Fehlermeldung ?
Verhalten ?
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
ich muss zu hause schauen... ich hab deine ganze klasse in eine bestehnder Namespace in meiner Form kopiert. da macht er keine Fehler beim kompilieren, aber ich kann es dann nicht aufrufen mit
PrintControl(From2);
da kennt er mir From2 nicht.
thanxx
@torkel
Das hat dann aber absolut gar nichts mit meinem Code zu tun.... da hast Du eine andere Baustelle !!! 😜
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo torkel,
evtl. From2 => Form2
herbivore
Original von herbivore
evtl. From2 => Form2
Lach herbivore.... auch ein graue Masse Patient ?
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo Programmierhans,
eher ein Fall für den Augenoptiker 🙂 Aber der Gerechtigkeit halber: Ich hatte schon mal zwei Namen, die mir der Compiler als unterschiedlich angemeckert hat, direkt untereinander kopiert und den Unterschied trotzdem nicht gesehen (in einem Namen stand aber statt einem t ein l).
herbivore
hi... ne an dem liegt es nicht, denn meine Form heisst eh anders, habe das nur als beispiel geschrieben, dass es verständlich ist.
ich glaube ich habe den code einfach falsch platziert. ich nehme die ganze klasse in meine bestehende Form, oder ist das falsch???
Ich hab ja im Beispiel absichtlich ne eigene Klasse gemacht
dann machst Du
PrintFunctions pf=new PrintFunctions();
pf.PrintControl(-----das was du Drucken willst)
Das kannst Du dann aus jedem Form aufrufen....
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo torkelm
mag sein, dass es dann geht, aber eine Klasse so lange zu verschieben, bis sie da steht, dass sich der Code übersetzen lässt, ist keine besonders sinnvolle Vorgehensweise. Genausowenig, wie man mit private, protected und public solange spielen sollte, bis die die Zugriffe gehen, die man gerne hätte. In der Objektorientierung sind ja absichtlich mache Zugriffe verboten.
Aber bezogen auf dein Beispiel kann ich es nicht beurteilen, weil es ja gerade darauf ankommt, was das für Klassen sind.
herbivore
@prgrammierhans: ja, jetzt hat es geklappt! merci.
aber ich kann jetzt meine form2 nicht printen.
mit
PrintFunctions pf=new PrintFunctions();
pf.PrintControl(form2);
kann ich denn da nicht nur den namen der form eingeben? es geht auch nicht mit der instanz der form.
wenn ich es mit this mache, drückt er mir zwar, aber ein gemisch aus form1 und form2. ich bräuchte wirklich nur den inhalt der form, kein rahmen, nix. und auch der graue hintergrund soll nicht geprintet werden.
geht das irgendwie?
mfg
Hi torkel,
wenn du eine gesammte Form als Control übergibst, dann druckt dir diese Klasse auch die gesammte Form. Diese Klasse ist in der Lage Controls zu drucken. Wenn du mehrere Controls einer Form drucken möchtest dann solltes du die Klasse verwenden um die einzelnen Bitmaps zu generieren und dann in der OnPrint Eventmethode im Layout zu platzieren und schlussendlich zu drucken.
Die Klasse ist erweiterbar auf mehrer Controls. Ich selber habe sie um ein weiteres Control erweitert. Des funzt also.
Wenn ich dich richtig verstanden habe willst du ein komplettes WindowsForms drucken. Von welcher Form aus stösst du den Druck an? Veranlasst du in Form1 den Druck von Form2 oder veranlasst du von Form2 aus den Druck selbiger?
Gruss
dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
@dschoegner:
nein, eigentlich weill ich nicht die ganze Form drucken. ich will nur zb. den Inhalt eines Panels oder auch von zwei Panels drucken.
zudem möchte ich den print von der form1 starten. das heisst, ich habe auf der form1 ein button und wenn der gedrückt wird, soll mir form2 gedruckt werden.
Kann ich mit dieser Klasse auch seiteneinstellungen druchtgeben? wie gross der ausdruck werden soll, und wo er auf dem blatt angeordnet wird?
sorry für diese vielen Fragen, aber das mit dem Print ist nicht so einfach, wie ich es mir gedacht habe.
greetz
Hi torkel,
das was du möchtest, kannst du in der OnPrint-Methode erledigen ohne die Klasse von Programmierhans zu verwenden.
Nimm das was in den Panels ist und zeichne es auf den Drucker, falls es eben nicht irgendein Grafikcontrol ist.
Ich kann dir nur das Buch Windows Programmierung in C# von Charles Petzold empfehlen. Der Druck wird dort recht ausführlich mit Beispielen erklärt.
Was mich zu einer Frage führt. Ich musste feststellen, dass bei einem Merhseitendruck bei jedem 2. Druck die Seiten überlagert werden. Genauer gesagt, habe ich im 1. Druck 14 Seiten druckt er mir beim 2. Druck die Seiten überlagert also nur 7 Seiten dann.
Irgendwie verlassen mich da grad die Geister.
private void prndoc_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics grfx = e.Graphics;
Font myFont = new Font("Times New Roman", 10);
Pen myPen = new Pen(Brushes.Black);
StringFormat strFormat = new StringFormat();
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.System);
Image imgtop = Image.FromFile(path + "\\logotop.bmp");
//Hier folgt Generierung des Drucklayouts
PageNumber++;
int rows = ((int)((e.MarginBounds.Bottom - 60 - rectfNotes.Bottom +5)/sizeFTime.Height)*2);
if(((int)this.MVToPrint.TimeToPrint.Length%rows)!=0)
{
//Prüfen ob eine weitere Seite gedruckt werden soll
e.HasMorePages = PageNumber<((this.MVToPrint.TimeToPrint.Length/rows)+1);
}
else
{
e.HasMorePages = PageNumber<(this.MVToPrint.TimeToPrint.Length/rows);
}
if(!e.HasMorePages)
{
grfx.DrawLine(myPen,new PointF(rectfSign.Left,rectfSign.Top - 1), new PointF(e.MarginBounds.Right-5,rectfSign.Top - 1));
grfx.DrawString("Datum, Unterschrift", myFont, Brushes.Black, rectfSign, strFormat);
PageNumber = 0;
NumberValues = 0;
}
}
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
HI...
gibt es da irgendwo ein Codebeispiel?
was hat das buch für eine IBAN Nummer?
gruss
Original von torkel
HI...gibt es da irgendwo ein Codebeispiel?
was hat das buch für eine IBAN Nummer?
gruss
ISBN: 3-86063-652-9
Codebeispiele.....hmmm im Grunde verfährt man in der OnPrint genauso wie man es in der OnPaint machen würde.....sich das Graphicsobject besorgen und damit zeichnen.
Ich weiss jetzt nicht wie stark du mit der OnPaint vertraut bist, aber vielleicht solltest du dich damit noch einmal kurz auseinander setzen.
gruss
dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Hallo!
Habe den Code probiert.... scheint auch zu funktionieren.
Bei mir kommt jedoch immer die Fehlermeldung, "Kein Drucker installier". Habe es mit dem Document Image Writer bzw. mit einem Drucker vom Netzwerk, als Standarddrucker probiert. Jedes Mal die Fehlermeldung...
Woran liegt das? Was muss ich machen?
Danke, im voraus....
MfG Bacella
Hi bacella,
vielleicht ein bißchen billig aber auf Anhieb fällt mir nix weiter ein:
this.prndoc = new PrintDocument();
this.setdlg = new PageSetupDialog();
this.prndlg = new PrintDialog();
this.prndlg.Document = this.prndoc;
this.setdlg.Document = this.prndoc;
private void FileToPrint()
{
if(this.prndlg.ShowDialog() == DialogResult.OK)
{
this.prndoc.DocumentName = "Datenblatt";
this.prndoc.PrintPage += new PrintPageEventHandler(OnPrintPage);
this.prndoc.Print();
}
}
Haste das alles im Code??????
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
Hab den Code vom Programmierhans übernommen... brauch ich das dann auch nocht.... sollte ja so auch funktionieren....
Hab keine Ahnung mit Drucken... mache es zum ersten Mal
MfG Bacella
JA dieser Code ist notwendig, die ersten 5 stehen bei mir im Konstruktor und die Methode rufe ich auf wenn ich drucken will.
Schau dir besser noch einmal in der MSDN die Druckerfunktionen und -optionen an. Den Code einfach zu übernehmen wird dir nur sehr kurzfristig helfen.
gruss dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
hallo
wie kann ich den Backcolor ändern, bei einem PrintOut?
hätte gerne, dass nicht der graue hintergrund gedruckt wird, sondern nur den text auf weisem background.
und gibt es irgendwo ein tutorial für diese OnPrint-Methode?
thanxx
Hi torkel,
wie schon erwähnt kann man in der OnPrint alle Zeichnen-Operationen wie in der OnPaint Methode vornehmen.....ich weiss jetzt nicht ob es für OnPrints nen Tutorial gibt, aber für die gesammte Paintgeschichte bestimmt irgendwo. Damit kann ich dir aber leider nicht dienen.
gruss
dschmoegner
Dennie Schmögner
Dipl. Ing. Informatik / Fachrichtung Automatisierungstechnik
Microsoft Business Intelligence 2005
SharePoint Portal Server 2007
In .NET 2.0 gibt die Methode Control.DrawToBitmap .Damit kann man auch ganz einfach ein Control drucken.
Beispiel:
Bitmap b=new Bitmap(this.textBox1.Width,this.textBox1.Height);
this.textBox1.DrawToBitmap(b, e.PageBounds);
e.Graphics.DrawImage(b, new Point(15, 50));
Ich habe mal eine Frage zu dem schon angesprochenen Buch.
Ich programmiere mit .net 2.0 und stehe genau vor dem Problem, dass ich
ein Programm schreiben muss, dass mir Adressetiketten bedruckt.
Den Drucker ansprechen klappt nur kann ich keinen String usw. übergeben. Deshalb wollte ich wissen ob das Buch (3-86063-652-9) auch für .net 2.0 geeignet ist?
Danke schonmal.
Für Ettikettendruck gibt es fertige, kommerzielle Lösungen. Wenn du im kommerziellen Umfeld programmierst, dann würde ich zum Einsatz raten. Sei mal List&Label als eines der bekanntesten Produkte genannt. Kostet zwar ein paar Euros für eine Entwicklerlizenz, ist aber allemal billiger als eine handgefrickelte Lösung.
Original von svenson
List&Label als eines der bekanntesten Produkte genannt. Kostet zwar ein paar Euros für eine Entwicklerlizenz, ist aber allemal billiger als eine handgefrickelte Lösung.
Und läuft auch wirklich gut 👍
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
naja ich habe das Programm für eine Arbeitskollegin geschrieben. Und nun möchte ich es erweitern, dass es ihr die Etiketten auf Endlospapier ausdruckt.
Sicher gibt es dafür kommerzielle Software aber damit kann ich nicht meine C# Kenntnisse erweitern und verbessern 🙂