Autor |
Beitrag |
petergensfeld
      
Beiträge: 46
Windows Vista 32-Bit
Delphi XE Professional
|
Verfasst: Do 01.12.05 15:20
Hallo zusammen,
ich hoffe, mir kann jemand bei meinem Problem weiterhelfen, verzweifle nämlich langsam darüber...
Das Ziel ist das Erstellen eines Enhanced Metafiles (*.emf), das vollständig durch die Plot-Routine erzeugt und für den späteren Ausdruck auf der Festplatte gespeichert werden soll. Es soll grundsätzlich ein umgebender Rahmen gezeichnet werden, in den eine Kontur gezeichnet wird, deren Koordinaten vom Anwender in beliebiger Skalierung vorgegeben werden dürfen. In diese Kontur sollen abschließend Messpunkte mittels kleiner, immer gleich großer Kreise eingezeichnet werden, denen dann in einer genügend kleinen Schriftgröße Messwerte zugeordnet werden.
Das Zeichnen des Rahmens und der Kontur funktioniert soweit gut. Das Problem sind die Messpunkte und deren Beschriftung. Kann ich einem EMF eine definierte Größe vorgeben? Sehr kleine Elemente lassen sich nicht in hinreichender Auflösung darstellen, Kreise werden eckig, kleine Schriftarten unleserlich. Die Auflösung richtet sich ja offensichtlich nach dem angegebenen Referenz-Device, also standardmäßig dem Bildschirm. Um diese zu erhöhen, habe ich mal testweise ausprobiert, einen angeschlossenen Drucker als Referenz-Device zu wählen. Leider ohne Erfolg, denn dann wird das EMF einfach entsprechend in der Größe herunterskaliert.
Damit es nicht allzu unübersichtlich wird, hier mal ein paar Ausschnitte meines Codes, von denen ich denke, dass sie relevant sein könnten.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102:
| procedure TIfiplot.Plot(const EmfFile: String); var fs: TFileStream; mf: TMetafile; mfc: TMetafileCanvas; xsize, ysize, cx, cy, xmin, xmax, ymin, ymax, hres, vres, hsize, vsize: Integer; rc: TRect; pt: TPoint; rgn: HRGN; begin if not FInitOk then exit; try fs:=TFileStream.Create(EmfFile, fmCreate or fmShareDenyWrite); except FErrorCode:=cErrSaveEmfFile; exit; end;
try mf:=TMetafile.Create; mf.MMWidth:=21000; mf.MMHeight:=29700; except FErrorCode:=cErrInternal; exit; end;
mfc:=TMetafileCanvas.CreateWithComment(mf, 0, 'Ifiplot 2.0', ''); try hres:=GetDeviceCaps(mfc.Handle, HORZRES); vres:=GetDeviceCaps(mfc.Handle, VERTRES); hsize:=GetDeviceCaps(mfc.Handle, HORZSIZE); vsize:=GetDeviceCaps(mfc.Handle, VERTSIZE);
xsize:=MulDiv(mf.MMWidth, hres, hsize*100); ysize:=MulDiv(mf.MMHeight, vres, vsize*100);
with mfc do begin SetMapMode(Handle, MM_ANISOTROPIC); SetWindowExtEx(Handle, 2100, 2970, nil); SetViewportExtEx(Handle, xsize, -ysize, nil); SetViewportOrgEx(Handle, 0, ysize, nil); if FShape.Count > 2 then begin rc:=Rect(250,2820,1950,500);
xmin:=FParamsData.MinX*FParamsData.ScaleX; xmax:=FParamsData.MaxX*FParamsData.ScaleX; ymin:=FParamsData.MinY*FParamsData.ScaleY; ymax:=FParamsData.MaxY*FParamsData.ScaleY;
if FParamsData.Scale<>2 then SetMapMode(Handle, MM_ISOTROPIC); SetWindowExtEx(Handle, xmax-xmin+10, ymax-ymin+10, nil); SetViewportExtEx(Handle, xsize, -ysize, nil); SetViewportOrgEx(Handle, rc.Left + xsize div 2, rc.Top + ysize div 2, nil);
pt.x:=xmin + (xmax-xmin) div 2; pt.y:=ymin + (ymax-ymin) div 2; LPtoDP(Handle,pt,1); cx:=pt.x; cy:=pt.y; GetViewportOrgEx(Handle, pt); OffsetViewportOrgEx(Handle, pt.x-cx, pt.y-cy, nil);
rgn:=CreateRectRgnIndirect(rc); SelectClipRgn(Handle,rgn); DeleteObject(rgn);
end; end; finally mfc.Free; end; try mf.SaveToStream(fs); except FErrorCode:=cErrSaveEmfFile; end; mf.Free; fs.Free; end; |
Ich bin für jeden Tipp resp. jede Idee dankbar, um das Problem in den Griff zu bekommen.
Gruß Dirk
|
|
digi_c
      
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mo 05.12.05 09:34
Könntest du nicht .SVG benutzen? Dir kommt es doch auf ein Vektorformat an, oder?
|
|
petergensfeld 
      
Beiträge: 46
Windows Vista 32-Bit
Delphi XE Professional
|
Verfasst: Mi 07.12.05 10:50
Titel: Geeigntes Dateiformat?
Ja, ich suche schon nach einem anderen, geeigneten Format. (WMF/EMF scheint qualitativ leider wirklich nicht geeignet zu sein. Ich habe testweise ähnliche Dateien, die im HPGL-Format vorlagen, mittels SPlot in EMF konvertiert -> mit dem gleichen Effekt, unzureichende Auflösung!  )
Vielleicht könnt Ihr mir bei der Suche nach einem geeigneten Format weiterhelfen: Die Grafik soll frei skalierbar und qualitativ hochwertig auf DIN A4 ausgedruckt werden können. Darüber hinaus sollen die Dateien nachträglich mit einem CAD-Programm weiterbearbeitet werden können, ideal wäre dafür wohl DXF. Andererseits sollen die Grafiken auch in ein Word-Dokument eingebunden werden können, daher fiel unsere Wahl zunächst auf EMF.
Der Programmieraufwand sollte sich in Grenzen halten, die Spezifikation des Dateiformats möglichst offen liegen. Wie sieht es mit fertigen Komponenten aus, etwa zum Schreiben von DXF? Habe da noch nicht allzu viel gefunden.
Gruß Dirk
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 07.12.05 11:21
Hallo Dirk,
deiner Beschreibung nach sollte das emf-Format eigentlich ausreichend sein.
Mehrere Dinge fallen mir aber auf:
1. Du schreibst:
"Sehr kleine Elemente lassen sich nicht in hinreichender Auflösung darstellen, Kreise werden eckig, kleine Schriftarten unleserlich."
Meinst du damit den Ausdruck? Wenn ja, auf was für einem Drucker hast du die Graphik ausgegeben? Vektorgraphiken sehen auf Tintenstrahldruckern oft pixelig aus, wenn die Strichstärke <= 1 ist. Das gleiche gilt für eingebettete Texte, selbst dann, wenn es sich um Truetype fonts handelt. Handelt es sich also um ein Druckerproblem?
2. Die Maßeinheit für enhanced metafiles ist mmHeight und mmWidth (je 0,01 mm). Dies ist unabhängig von den Maßen des Reference Device. Eine weitere Manipulation der Metafilegröße durch SetMapMode ist daher nicht notwendig. Das wird erst wieder beim Mapping auf die endgültige Zeichenfläche (Drucker oder Bildschirm) interessant. Auch der Einsatz von GetDeviceCaps ist daher überflüssig.
3. In welcher Größenordnung bewegen sich die Integer-Werte, mit denen du die kleinen Kreise der Meßpunkte zeichnest?
Gruß, P_G
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Mi 07.12.05 11:40
Also an deiner Stelle würde ich Word und CAD Programm nicht versuchen wollen mit ein und dem selben Füttern zu wollen. Das eine kann eher etwas mit Bitmap anfangen und das andere ist rein Vektorbasiert. Also wäre für mich wohl das sinnvollste, wenn du dir ein Format aussuchst was sowohl einfach als auch zukunftsversiert ist. Ja ich spiele damit auch auf SVG an. Immer mehr Tool unterstützen das und bei Bedarf kannst du deine Daten auch als Bitmap oder PNG exportieren. Damit sollten dann alle Daten bedient werden.
Muss allerdings gestehen, dass ich nicht 100%tig weiß was du damit vor hast und somit kann ich auch nicht sagen was der Sinnvollste Weg ist und ob meine Lösung da überhaupt so sinnvoll ist. Das alleine wirst nur du entscheiden können.
[edit] Ach ja. SVG wird vom FireFox 1.5 nativ unterstützt und kannst du im übrigen mit Inkscape bearbeiten. Aber Vorsicht. SVG ist nicht nur ein Format um Grafiken anzuzeigen. Damit kann man wesentlich mehr machen. Das solltest du auch noch wissen. Habe vor 1-2 Jahren mal eine Seite gesehen in der Dynamische Grafiken mit SVG gemacht wurden. Also Per Skript waren die Grafiken veränderbar.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
petergensfeld 
      
Beiträge: 46
Windows Vista 32-Bit
Delphi XE Professional
|
Verfasst: Mi 07.12.05 12:00
@ P_G
Um ein Druckerproblem handelt es sich offenbar nicht. Habe auf verschiedenen Druckern getestet, die Schrift ist grundsätzlich unleserlich. Auch auf dem Bildschirm sieht man das (wenn man entsprechend zoomt).
In erster Linie geht es um einen guten Ausdruck auf DIN A4. Deshalb habe ich MMWidth und MMHeight auf 21000 bzw. 29700 gesetzt (multipliziert mit 0,01 mm ergibt sich so die Größe einen DIN A4-Blattes, wobei es bei theoretisch freier Skalierbarkeit ja eigentlich nur auf das richtige Verhältnis ankommen sollte). Seltsamerweise wird aber nur das Größenverhältnis, nicht die tatsächliche Größe durch MMWidth bzw. MMHeight beeinflusst? Wieso? Bei einer Angabe in mm sollte sich doch die absolute Größe ändern!?
SetMapMode benutze ich aus einem anderen Grund. Der Umriss, der gezeichnet werden soll, liegt in x-beliebigen, relativen Koordinaten vor. Deren Größe muss ich auf den mir zur Verfügung stehenden, tatsächlichen Zeichenbereich "mappen". Dazu bietet sich der Modus MM_ISOTROPIC an, um die Proportionen beizubehalten. Das dürfte mMn aber keinerlei Einfluss auf die tatsächliche Größe des entstehenden EMFs haben (habe das testweise auch mal rausgenommen, dadurch hat sich an der Größe erwartungsgemäß nichts geändert).
Die Kreise sollten auf dem Ausdruck hinterher etwa einen Durchmesser von einem 1 mm haben.
@ Lossy eX
Vielleicht habe ich mich da ein bisschen unglücklich ausgedrückt. Ich möchte für das CAD-Prgramm und Word nicht unbedingt ein- und dasselbe Format benutzen, nur eine brauchbare Konvertierung (im Batch-Modus, da sehr viele Dateien) sollte möglich sein. Bei SVG stellt sich das Problem, dass unsere CAD-Software (Malz+Kastner CAD 6) dieses nicht importieren kann.
Gruß Dirk
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 07.12.05 12:04
Lossy Ex,
nur ganz am Rande - Words Unterstützung von Vektorgraphiken wird häufig unterschätzt.
Es ist z.B. problemlos möglich noch in Word die einzelnen Linien des Metafiles zu selektieren, rotieren, verschieben oder ganz zu löschen.
Gruß, P_G
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Mi 07.12.05 12:12
P_G hat folgendes geschrieben: | nur ganz am Rande - Words Unterstützung von Vektorgraphiken wird häufig unterschätzt.
Es ist z.B. problemlos möglich noch in Word die einzelnen Linien des Metafiles zu selektieren, rotieren, verschieben oder ganz zu löschen. |
Asche auf mein Haupt. Muss gestehen, dass ich Word und Grafiken nach möglich komplett außen vor lasse. Seit neustem Word sowieso. Alleine die eingebetteten Bitmaps haben mich bisher immer schaudern lassen. Zu Vektorgrafiken bin ich noch gar nicht richtig gekommen. 
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 07.12.05 12:26
Hi Dirk,
Zitat: | Um ein Druckerproblem handelt es sich offenbar nicht. Habe auf verschiedenen Druckern getestet, die Schrift ist grundsätzlich unleserlich. Auch auf dem Bildschirm sieht man das (wenn man entsprechend zoomt). |
Laserdrucker auch? Gut, Punkt abgehakt.
Zitat: | Seltsamerweise wird aber nur das Größenverhältnis, nicht die tatsächliche Größe durch MMWidth bzw. MMHeight beeinflusst? Wieso? Bei einer Angabe in mm sollte sich doch die absolute Größe ändern!? |
Ist auch so. Du skalierst aber durch SetMapMode etc. das Metafile weiter runter. Diese ganze Sektion solltest du aus deinem Code entfernen. SetMapMode brauchst du erst wieder bei der eigentlichen Bildschirmdarstellung (z.B. einem TPaintBox.OnPaint event).
Zitat: | (habe das testweise auch mal rausgenommen, dadurch hat sich an der Größe erwartungsgemäß nichts geändert).
|
Wenn du wirklich alles rausgenommen hast kannst du mal folgendes testen:
Speichere das Metafile mit Savetofile ab. Öffne das Metafile jetzt von der Festplatte aus in der Windows Bild und Fax-Anzeige (die stellt Metafiles dar, ohne sie vorher zu Bitmaps konvertiert zu haben). Wenn du jetzt ranzoomst, sollte eigentlich alles richtig sein.
Gruß, P_G
|
|
petergensfeld 
      
Beiträge: 46
Windows Vista 32-Bit
Delphi XE Professional
|
Verfasst: Mi 07.12.05 13:10
P_G hat folgendes geschrieben: | Ist auch so. Du skalierst aber durch SetMapMode etc. das Metafile weiter runter. |
Hmm, verstehe ich zwar nicht, aber wenn's denn so ist...  Der Dokumentation bzw. Charles Petzolds Werk zur Windows-Programmierung kann ich das nicht entnehmen. Wird wahrscheinlich ein Verständnis-Problem meinerseits sein, habe noch nicht viel Erfahrung mit Grafik-Programmierung. Deshalb bin ich Dir auch dankbar, dass Du Dich meines Problems annimmst.
Zitat: | Diese ganze Sektion solltest du aus deinem Code entfernen. SetMapMode brauchst du erst wieder bei der eigentlichen Bildschirmdarstellung (z.B. einem TPaintBox.OnPaint event). |
Eine Bildschirmdarstellung gibt es nicht, ich brauche nur die EMF-Datei als Output. SetMapMode hätte mir eine ganze Menge Koordinatenumrechnungsarbeit erspart, zumal verschiedene Darstellungsformen (proportinal, max. Größe, beliebige Skalierung in x-/y-Richtung) erwünscht sind. Wie kann ich auf GetDeviceCaps verzichten? Muss ich nicht die mir tatsächlich zur Verfügung stehende Zeichenfläche ermitteln? Arbeiten die üblichen Canvas-Funktionen nicht mit logischen anstelle von Gerätekoordinaten? Oder kann ich wirklich 0,01mm-Koordinaten einsetzen?
Zitat: | Wenn du wirklich alles rausgenommen hast kannst du mal folgendes testen:
Speichere das Metafile mit Savetofile ab. Öffne das Metafile jetzt von der Festplatte aus in der Windows Bild und Fax-Anzeige (die stellt Metafiles dar, ohne sie vorher zu Bitmaps konvertiert zu haben). Wenn du jetzt ranzoomst, sollte eigentlich alles richtig sein. |
Ich habe bislang den weithin bekannten Grafikviewer IrfanView benutzt, um mir die Dateien anzuschauen. Ich wusste nicht, dass die Metafiles in Bitmaps konvertiert werden, bevor sie zur Anzeige kommen. Passiert das nicht am Ende grundsätzlich, wenn es auf einem pixelbasierten Gerät (Bildschirm, Drucker) zur Anzeige gebracht wird?
Ich werde zunächst mal testweise ein leeres EMF erstellen und einfach mal schauen, ob die Ausgabegröße dann tatsächlich der Vorgabe entspricht. Und dann "male" ich mal ein paar kleine Kreise...
Btw, gehört die "Windows Bild- und Faxanzeige" zur Standardinstallation von XP? Wo finde ich das Programm?
Gruß Dirk
|
|
digi_c
      
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mi 07.12.05 13:41
Explorer - Shift+Rechtsklick auf Datei - Öffnen Mit ... - Windows Bild und Fax Anzeige
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 07.12.05 13:44
Hi Dirk,
zu deinem Problem:
1. Zitat: | Arbeiten die üblichen Canvas-Funktionen nicht mit logischen anstelle von Gerätekoordinaten? Oder kann ich wirklich 0,01mm-Koordinaten einsetzen? |
Siehe Delphi-Hilfe (TMetafile.mmWidth): "Die Angabe der Eigenschaft mmWidth erfolgt immer in Pixeleinheiten für Bildschirmgeräte."
Mit anderen Worten: wenn du ein Metafile von 10*10 cm erstellst (mmwidth und mmHeight = 10000) und nun ein Rechteck (Rectangle(0, 0, 5000,5000)) hineinzeichnest bekommst du tatsächlich ein Rechteck geliefert, daß sich von der oberen linken Ecke bis zur Mitte der Graphik erstreckt.
2. Die Windows Bild und Fax-Anzeige öffnet sich, wenn du über deiner Graphikdatei das Kontextmenü öffnest und 'Öffnen mit' wählst. Dort wählst du die Faxanzeige aus
3. Zitat: | Ich wusste nicht, dass die Metafiles in Bitmaps konvertiert werden, bevor sie zur Anzeige kommen. Passiert das nicht am Ende grundsätzlich, wenn es auf einem pixelbasierten Gerät (Bildschirm, Drucker) zur Anzeige gebracht wird? |
Nein! Das Windows GDI liefert zwar letztlich eine Pixelgraphik an den Bildschirmtreiber, aber Windows-Intern bleibt es eine Vektorgraphik. Die meisten Viewer und selbst viele Zeichenprogramme konvertieren allerdings zu Bitmap, weil die Anzeige dann wesentlich schneller arbeitet. Ich kenne IrfanView nicht, vermute aber, daß genau das hier passiert ist ...
Gruß, P_G
Zuletzt bearbeitet von P_G am Mi 07.12.05 14:12, insgesamt 1-mal bearbeitet
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Mi 07.12.05 14:06
Nachtrag zum letzten Post,
Für das Beispiel mit dem 10*10 cm Rechteck kommst du tatsächlich nicht ums Mapping herum, wenn logische Koordinaten = mm-Koordinaten sein sollen - geht aber ganz einfach:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| procedure TForm1.Button1Click(Sender: TObject); Var Meta: TMetafile; v,w: TSize; begin Meta := TMetafile.Create; Meta.mmWidth := 10000; Meta.mmHeight := 10000; With TMetafileCanvas.Create(Meta, 0) do try SetMapMode(Handle, MM_hiMetric); GetWindowExtEx(Handle, w); GetViewPortExtEx(Handle, v); SetMapMode(Handle, MM_Anisotropic); SetWindowExtEx(Handle, w.cx, w.cy, nil); SetViewPortExtEx(Handle, v.cx, -v.cy, nil); Rectangle(0, 0, 10000,10000); Rectangle(0, 0, 5000,5000); Finally Free; end; Meta.SaveToFile('Test.emf'); Meta.Free; end; |
Mehr brauchst du nicht. Dennoch hängt dein Problem wahrscheinlich mit IrfanView zusammen.
Gruß, P_G
Moderiert von raziel: Code- durch Delphi-Tags ersetzt
|
|
petergensfeld 
      
Beiträge: 46
Windows Vista 32-Bit
Delphi XE Professional
|
Verfasst: Mi 07.12.05 15:28
Hallo P_G,
Du bist meine Rettung!
Zitat: | Die meisten Viewer und selbst viele Zeichenprogramme konvertieren allerdings zu Bitmap, weil die Anzeige dann wesentlich schneller arbeitet. Ich kenne IrfanView nicht, vermute aber, daß genau das hier passiert ist ... |
Das ist ja ein Ding, genau so ist es! Habe die Grafik jetzt mit der Windows Bild- und Faxanzeige ausgedruckt - und siehe da - perfekt, alles gestochen scharf! Insofern hat es wohl mit SetMapMode etc. nichts zu tun, zumal ich das im Grunde genau so gemacht habe wie in Deinem Beispiel (eben nur nicht auf mm, sondern auf ein beliebiges Koordinatensystem gemappt).
Scheinbar machen einige Grafikprogramme diesen Fehler auch beim Konvertieren in ein anderes Format. Wir haben mit SPlot HPGL-Dateien in EMF konvertiert - die sind nicht zu gebrauchen (auch nach Darstellung in der Windows Bild- und Faxanzeige). Scheinbar gab es da auch einen Zwischenschritt in ein Bitmap-Format?! Naja, das soll mich jetzt nicht mehr kratzen, Hauptsache die durch mein Programm erstellten EMFs sind ok.
Dann war meine bisherige Arbeit ja scheinbar doch nicht ganz vergebens!
Besten Dank und viele Grüße,
Dirk
|
|
|