AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Maßeinheitengenau ein Canvas ausdrucken

Ein Thema von PAX · begonnen am 27. Mär 2007 · letzter Beitrag vom 8. Apr 2007
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#1

Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 14:28
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
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 14:53
Schalte den MapMode entsprechend um: MSDN-Library durchsuchenSetMapMode.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#3

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 14:54
Zitat von PAX:
Beispielsweise dürften 50 Pixel auf verschiedenen Druckern unterschiedliche Längen haben, oder irre ich mich?
Hi,
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:
  1. SetMapMode
  2. GetDeviceCaps

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
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#4

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 18:43
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;
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#5

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 19:20
Zitat von PAX:
PHYSICALHEIGHT scheint mir bei der GetDeviceCaps-Funktion am zutreffendsten zu sein.
Das ist soweit korrekt!

Zitat von PAX:
Auch frag ich mich schon seit längerem, was der Typ "Handle" eigentlich genau ist. Ein Zeiger?
Es handelt sich dabei mehr um eine Identifikationsnummer, der Sinn kommt aber dem eines Zeigers sehr nahe/gleich. Windows verwaltet alle Ressourcen über Handles. Ein Handle ist dabei ein Zahl (glaube ein DWord), die eine beliebige Ressource identifiziert. Letztlich geht man hier aber über eine zusätzliche Indirektion sicher, dass niemand direkt auf Adressen zugreift. Man muss immer den "Umweg" über Windows-Funktionen gehen (ohne ginge es eh nicht), die dann sicherstellen können, dass ein konsistenter Zustand erhalten bleibt.

Zitat von PAX:
Code:
 if(!PrintDialog1->Execute()) return;

//Form1->Caption=SetMapMode(GetDC(Form1->Handle),MM_HIMETRIC);
int i=GetDeviceCaps(GetDC(Handle),PHYSICALHEIGHT);
Form1->Caption =i;
Du musst für das Handle der Funktion GetDC das Handle des Druckers verwenden. Du müsstest in der Bibliothek Printers eine Funktion printer() finden, die ein TPrinter-Objekt zurück gibt. Dieses Objekt hat dann wiederum die Eigenschaft Handle besitzt. Übergibst Du dieses Handle an die Methode, solltest Du einen korrekten Wert bekommen (wäre zumindest der Delphi Weg, sollte aber für die Borland C++ IDE gleich sein).

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
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#6

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 27. Mär 2007, 22:54
meinst du soetwas wie:
Code:
TPrinter* druck = new TPrinter();

int i=GetDeviceCaps(GetDC(druck->Handle),PHYSICALHEIGHT);
Form1->Caption =i;
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.

Irgendwie funktioniert es nicht so, wie ich es mir dachte.
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
matashen

Registriert seit: 29. Jan 2007
Ort: daheim
460 Beiträge
 
Delphi XE2 Enterprise
 
#7

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 28. Mär 2007, 07:58
Nimm zum Drucken eines Bildes am besten folgenden Code

Delphi-Quellcode:
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};
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.

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
Matthias
Das Leben ist eines der härtesten.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#8

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 28. Mär 2007, 10:19
Zitat von PAX:
meinst du soetwas wie:
Code:
TPrinter* druck = new TPrinter();
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.
So was in der Richtung meinte ich. Der aktuell ausgewählte Drucker wird in einer globalen Variable gespeichert. Es sollte deswegen eine Methode geben, mit der Signatur
Code:
TPrinter* printer(void) {...}
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).
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:
TPrinter* druck = printer();

int height = GetDeviceCaps(druck->Handle, PHYSICALHEIGHT);
...
Gruß
  Mit Zitat antworten Zitat
Benutzerbild von PAX
PAX

Registriert seit: 22. Jun 2003
Ort: Karlsruhe
88 Beiträge
 
Delphi 7 Personal
 
#9

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 28. Mär 2007, 13:21
@matashen

Ich danke dir für den Code - nun kann ich gucken, wie das nachher ungefähr aussehen sollte.

@soEinigesWissender

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.

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
Andreas
"Wenn man irgendwann mal von allen akzeptiert wird, dann weiß man, dass man irgendwas falsch gemacht hat." Zitat: Herr Weidner

  Mit Zitat antworten Zitat
matashen

Registriert seit: 29. Jan 2007
Ort: daheim
460 Beiträge
 
Delphi XE2 Enterprise
 
#10

Re: Maßeinheitengenau ein Canvas ausdrucken

  Alt 28. Mär 2007, 13:30
gern geschehen

Matthias
Das Leben ist eines der härtesten.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz