![]() |
Maßeinheitengenau ein Canvas ausdrucken
Seid gegrüßt, Freundinnen und Freunde,
es brennt mir mal wieder eine Frage auf dem Herzen, welche mich schon nächtelang nicht schlafen und zur Flasche greifen lässt. :) Ich möchte gerne eine mit Canvas gezeichnete Grafik mit Hilfe der TPrint-Klasse drucken. Allerdings soll der Ausdruck dann eine bestimme Größe einhalten. Beispiel: Sagen wir, ich habe eine horizontale Linie gezeichnet, welche eine spezifische Pixelanzahl lang ist, die einem centimeter entsprechend soll. Nun soll das ausgedruckte Resultat ebenfalls tatsächlich 1 cm lang sein. Beispielsweise dürften 50 Pixel auf verschiedenen Druckern unterschiedliche Längen haben, oder irre ich mich? Wie geht das? Beste Grüße und viva los tioz! PAX :nerd: |
Re: Maßeinheitengenau ein Canvas ausdrucken
Schalte den MapMode entsprechend um:
![]() |
Re: Maßeinheitengenau ein Canvas ausdrucken
Zitat:
da hast Du schon recht, aber das Problem geht noch ein kleines Stück weiter, selbst auf einem Drucker können 50 Pixel unterschiedliche Längen/Größen haben. Immerhin unterstützen die meisten Drucker unterschiedliche Auflösungen. Die Auflösung gibt nun gerade an, wieviele Pixel / Maßeinheit gesetzt werden. Je geringer also die Auflösung, desto größer jedes Pixel. Alles was Du also machen musst ist auf die Auflösung zu achten. Dazu gibt es zwei Möglichkeiten:
Das sind zwei Funktionen, die Windows zur Verfügung stellt (einfach in der API-Hilfe bzw. im PSDK nachschauen). Mit der ersten Methode setzt Du den MapMode eines Canvas. Dieser Modus passt an, in welcher Einheit Du Angaben zur Position machst. Hier kannst Du z.B. Millimeter oder zehntel millimeter wählen. Statt nun eine Linie von x-Pixeln würdest Du damit eine Linie von x-millimeter zeichnen. Mit der Methode GetDeviceCaps (ebenfalls API-Hilfe bzw. PSDK) kannst Du Eigenschaften eines Canvas abfragen. Die für Dich interessanten Eigenschaften dürften dann natürlich in der Auflösung liegen. Kennst Du die Auflösung, musst Du dich um das Umrechnen von Deinen Pixelangaben kümmern. Gruß Der Unwissende |
Re: Maßeinheitengenau ein Canvas ausdrucken
PHYSICALHEIGHT scheint mir bei der GetDeviceCaps-Funktion am zutreffendsten zu sein. Allerdings liefert die Funktion bei mir immer 0 zurück. Auch frag ich mich schon seit längerem, was der Typ "Handle" eigentlich genau ist. Ein Zeiger?
Ich kann diese ganze Druckergeschichte nicht testen, da ich keinen Drucker zur Verfügung habe, aber ich kann jeden Druck als PDF-Datei erzeugen lassen. Ist PHYSICALHEIGHT richtig? Das war das einzige, welches sich auf einen Druck mit "Geräteeinheiten" bezog. :|
Delphi-Quellcode:
if(!PrintDialog1->Execute()) return;
//Form1->Caption=SetMapMode(GetDC(Form1->Handle),MM_HIMETRIC); int i=GetDeviceCaps(GetDC(Handle),PHYSICALHEIGHT); Form1->Caption =i; |
Re: Maßeinheitengenau ein Canvas ausdrucken
Zitat:
Zitat:
Zitat:
Ansonsten bliebe der nur der Weg über die Methode EnumPrinters (Win-API), über die Du dann das Handle des Druckers ermitteln müsstest. Gruß Der Unwissende |
Re: Maßeinheitengenau ein Canvas ausdrucken
meinst du soetwas wie:
Code:
Ich habe allerdings für die Klasse TPrintDialog keine Attribute gefunden, wo ich den ausgewählten Drucker abfangen und dem Objekt der TPrinter-Klasse zuweisen kann.
TPrinter* druck = new TPrinter();
int i=GetDeviceCaps(GetDC(druck->Handle),PHYSICALHEIGHT); Form1->Caption =i; Irgendwie funktioniert es nicht so, wie ich es mir dachte. :| |
Re: Maßeinheitengenau ein Canvas ausdrucken
Nimm zum Drucken eines Bildes am besten folgenden Code
Delphi-Quellcode:
hab hier mal vor einiger Zeit Getmem durch getdibsizes ersetzt, da ich bei getmem zum teil falsche Wérte bekommen habe. Sollte so funktionieren. Den Grundcode hab ich irgendwo gegoogelt.
PROCEDURE PrintBitmap(Canvas: TCanvas; DestRect: TRect; Bitmap: TBitmap);
// PROC eingeführt am 10.1.07 da bessere ausgabeergebnisse VAR BitmapHeader: pBitmapInfo; BitmapImage,header,bits : POINTER; HeaderSize, BitsSize: Cardinal; //HeaderSize : DWORD; // Use DWORD for D3-D5 compatibility ImageSize : DWORD; nographics:boolean; BEGIN // TEST //if GetDeviceCaps(Printer.Handle, RASTERCAPS) then NoGraphics := True; GetDIBSizes(Bitmap.Handle, HeaderSize, ImageSize); //GetMem(BitmapHeader, HeaderSize); //GetMem(BitmapImage, ImageSize); Bitmapheader := VirtualAlloc(nil, HeaderSize, MEM_COMMIT, PAGE_READWRITE); BitmapImage := VirtualAlloc(nil, ImageSize, MEM_COMMIT, PAGE_READWRITE); TRY GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapHeader^, BitmapImage^); StretchDIBits(Canvas.Handle, DestRect.Left, DestRect.Top, // Destination Origin DestRect.Right - DestRect.Left, // Destination Width DestRect.Bottom - DestRect.Top, // Destination Height 0, 0, // Source Origin Bitmap.Width, Bitmap.Height, // Source Width & Height BitmapImage, TBitmapInfo(BitmapHeader^), DIB_RGB_COLORS, SRCCOPY) FINALLY //FreeMem(BitmapHeader); //FreeMem(BitmapImage) VirtualFree(Bitmapheader, 0, MEM_FREE); VirtualFree(bitmapimage, 0, MEM_FREE); END END {PrintBitmap}; um dann das ganze auf eine bestimmte Größe anpassen zu können nutzt du das:
Delphi-Quellcode:
printer.title:=Dein Programmname '+filetext;
if printer.printing then printer.abort; printer.begindoc; //Drucker-Daten ermitteln: (Hoehe und Breite in cm und Pixeln) //durch 10, da mm in cm umrechnen BreiteCm :=GetDeviceCaps(Printer.Handle,HORZSIZE) div 10; BreitePixel :=GetDeviceCaps(Printer.Handle,HORZRES); HoeheCm :=GetDeviceCaps(Printer.Handle,VERTSIZE) div 10; HoehePixel :=GetDeviceCaps(Printer.Handle,VERTRES); //wieviel Pixel auf 1 cm kommen: HorizPixelProCm :=BreitePixel div BreiteCm; VertPixelProCm :=HoehePixel div HoeheCm; breitereal:=BreitePixel/BreiteCm; hoehereal:=(HoehePixel/HoeheCm); horp:= HorizPixelProCm; verp:= VertPixelProCm; faktor:=10; LRand := HorizPixelProCm; ORand :=VertPixelProCm; ... ... Printbitmap(...) printer.enddoc; gruß Matthias |
Re: Maßeinheitengenau ein Canvas ausdrucken
Zitat:
Code:
Die gibt Dir eben den aktuellen Drucker zurück, anders gesagt der TPrintDialog setzt die Variable, die hier zurückgeliefert wird für Dich. Danach sollte diese Methode eben den ausgewählten Drucker (mit eingestellten Eigenschaften) liefern. Die angesprochene Funktion sollte (bei Borland) in einer Datei wie Printers.h deklariert sein (hier kann natürlich der Name abweichen, aber denke müsste hinkommen).
TPrinter* printer(void) {...}
Zudem kannst Du das GetDC weglassen. Das ist nur nötig, wenn Du ein Fensterhandle übergeben würdest. Der Code hätte eher die Form:
Code:
Gruß
TPrinter* druck = printer();
int height = GetDeviceCaps(druck->Handle, PHYSICALHEIGHT); ... |
Re: Maßeinheitengenau ein Canvas ausdrucken
@matashen
Ich danke dir für den Code - nun kann ich gucken, wie das nachher ungefähr aussehen sollte. @soEinigesWissender :wink: Jetzt kennt der Compiler die Methode printer(), nachdem ich die Unit printers.h eingebunden habe - ich dachte zuerst noch, dass ich die nicht brauche, weil alles andere ja auch so klappte. :lol: Jetzt werden auch zu den verschiedenen dpi-Einstellungen des PDF-Writers unterschiedliche "physikalische Geräteeinheiten" zurückgegeben. Ich musste allerdings das Objekt, "druck", als global instanziieren, sonst kamen immer nach wiederholtem Abfragen des Wertes Speicherzugriffsverletzungen. @Luckie, soEinigesWissender, matashen Ich danke euch, dass ihr bereit wart, so viel Zeit in meine Fragen zu investieren! Ihr glaubt garnicht, wie viel mir immer soetwas wert ist. Ich werde mich nun mal mit dieser Sache weiter befassen, da ich denke, dass ich erstmal alles weiß, was ich dafür wissen muss. Es kann aber sein, dass sich im Laufe dessen, weitere Fragen auftun. Diesen Thread also bitte noch nicht schließen. Danke, Freunde! :) Mit besten Grüßen PAX |
Re: Maßeinheitengenau ein Canvas ausdrucken
gern geschehen :love:
:cheers: :dp: :hello: |
Re: Maßeinheitengenau ein Canvas ausdrucken
Zitat:
|
Re: Maßeinheitengenau ein Canvas ausdrucken
So, das exakte Drucken von gezeichneten Linien funktioniert maßgenau. Textausgabe auf dem Drucker klappt zwar einigermaßen exakt, allerdings scheint es dennoch kleinere Schrifthöhenunterschiede zu geben, wenn ich einen Druck von 600dpi mit 150dpi vergleiche...
TrackBar1 enthält die Schrifthöhe. Mit dieser Formel berechne ich die Ausdruckschrifthöhe:
Code:
Aber wie gesagt, es weicht ganz leicht von der Bildschirmvorschau ab und auch von unterschiedlichen dpi-Einstellungen des Druckers. Die Schriftgröße scheint bei 16-facher Vergrößerung identisch zu sein, allerdings wird bei der niedrigeren dpi-Zahl der ganze Text um einige Pixel nach rechts und nach unten versetzt.
druck->Canvas->Font->Height = -Form1->TrackBar1->Position/25.4 *druck->Canvas->Font->PixelsPerInch;
Was habe ich nicht bedacht? |
Re: Maßeinheitengenau ein Canvas ausdrucken
Zitat:
wahrscheinlich, dass die Druckertreiber generell alles andere als perfekt sind. Ich habe mich mit dem Problem schon häufiger herumgeschlagen (für technische Linienzeichnungen) und festgestellt, dass Drucker an sich schon in der Lage sind, auf 0.1 mm genau zu drucken, dass aber von Drucker zu Drucker und von Treiber zu Treiber Unterschiede im mm-Bereich bestehen. Manche hochwertigen Druckertreiber sehen eine manuelle Korrektur vor (unter Eigenschaften kann man Prozente eingeben), aber auch die sind oft nicht genau genug - 0.1 % sind bei A4 immerhin schon 0.3 mm. Ich denke, es wäre notwendig, in den eigenen Drucker-Routinen eine zusätzliche Korrektur an den berechneten Faktoren vorzusehen mit etwa +- 5% und einer Auflösung von 0.01% (!). Dann sollte man nach entsprechendem Vermessen einiger Ausdrucke eine Genauigkeit von 0.2mm oder so hinkriegen. Die Umrechnung von Schriftgrössen muss damit nicht übereinstimmen, notfalls müsste man die extra behandeln. Gruss Reinhard |
Re: Maßeinheitengenau ein Canvas ausdrucken
Hallo,
ein Visitenkarten-Programm, dass ich benutze, versucht zuerst ein Fadenkreuz mit Skala in die Mitte des Blattes zu drucken und fordert den Benutzer dann auf, das Blatt in der Mitte zu falten und die Abweichung zwischen Falz und Fadenkreuz anzugeben. Daraus wird dann ein Korrektiv berechnet. Wenns dir also um genaue Ausrichtung geht, kannst du es so machen. Um das Korrektiv umzusetzen gibt es eine API-Funktion, mit der du den Koordinatennullpunkt des Druckercanvas verschieben kannst - ![]() |
Re: Maßeinheitengenau ein Canvas ausdrucken
Der Zeichenabstand weicht auch ab, musste ich gerade feststellen.
Ich hatte auch schon den Gedanken, den Rahmen und den Text als eine Gesamtgrafik zu betrachten und diese entsprechend zu vergrößern für den Druck, allerdings bin ich mir nicht sicher, welche optische Qualität der Text dann nachher hat. Testen konnte ich dies bisher nicht, weil während des Vergrößerungsvorgangs jedes Mal der gesamte Computer massiv einfriert, wenn die Grafik schon vorher ziemlich groß war. Oder vielleicht lags auch am Adobe PDFwriter? Ich habs noch nie direkt ausgedruckt - wäre ja während der Entwicklungsphase reine Papierverschwendung! Wie macht es eigentlich das Microsoft Office-Paket? Ist dort das Druckresultat nicht immer äußerst genau? Die arbeiten doch auch nicht mit Kallibrierungsdrucken? Ich verstehe halt nicht, warum der Textdruck so ungenau ist (mit Methode TextOutA oder so) und die gezeichneten Linien hingehen völlig exakt? Also nochmal zusammengefasst: Der Text erscheint bei unterschiedlichen dpi-Auflösungen nicht exakt an der selben Stelle, obwohl mein Code determiniert ist, und der Zeichenabstand variiert dann ebenfalls. Ich danke euch. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz