Laden...

Exakte Platzierung einer Metafile-Grafik?

Erstellt von Minsky vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.657 Views
M
Minsky Themenstarter:in
3 Beiträge seit 2008
vor 16 Jahren
Exakte Platzierung einer Metafile-Grafik?

Hallo,

kann mir jemand helfen bei der exakten Platzierung eines „Image“ aus einer Metafile-Datei in das Graphics einer Form?

Verkürzte Version meines Vorhabens und mein Problem:

  1. Ich erstelle eine Metafile-Datei und zwei Stifte („Pens“) zum Zeichnen in das Metafile (evt. direkt in der Hauptform „WinForm()“):

public WinForm()
  {
    InitializeComponent();

    orangePen = new Pen(Color.Orange);
    redPen = new Pen(Color.Red);


    Graphics neuGraphics = this.CreateGraphics();
    IntPtr hdc = neuGraphics.GetHdc();

    metafile1 = new Metafile(@"Unbenannt.emf", hdc, EmfType.EmfPlusDual);

    neuGraphics.ReleaseHdc(hdc);
    neuGraphics.Dispose();

  }

  1. Ich lasse durch das Betätigen eines Buttons ein Rechteck in die Metafile-Datei schreiben (die Koordinaten liegen bei x = 0 und y = 0, die Breite und Höhe des Rechtecks bei 150 und 150 Millimetern):

private void button1_Click(object sender, System.EventArgs e)
 {

   Graphics g = Graphics.FromImage(metafile1);
   g.PageUnit = GraphicsUnit.Millimeter;
   redPen.Width = 1/g.DpiX*25.4F;
   g.DrawRectangle(redPen, 0.0F, 0.0F, 150.0F, 150.0F);

   g.Dispose();
   Invalidate();
  }

  1. Der Button in Punkt 2 löst zuletzt durch das „Invalidate()“ ein Paint-Event aus, das somit die Metadatei auf den Bildschirm in die Form an den angegebenen Punkt x = 0 und y = 0 zeichnen sollte:

private void WinForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
 {
   Graphics g = e.Graphics;
 
   g.PageUnit = GraphicsUnit.Millimeter;
   g.DrawImage(metafile1, 0.0F, 0.0F);
   orangePen.Width = 1/g.DpiX*25.4F;
   g.DrawRectangle(orangePen, 0.0F, 0.0F, 150.0F, 150.0F);

   g.Dispose();
   metafile1.Dispose();
  }

Das Ergebnis obiger Prozedur sieht aber anders aus als ich erwartet hatte! Das rote Rechteck aus dem Metafile in die Form gezeichnet, liegt nicht etwa in der oberen linken Ecke, sondern ist etwas nach rechts und nach unten verschoben. Zur Kontrolle zeichne ich noch ein Rechteck (in orange) mit den gleichen Maßen direkt in die Form, aber dieses weicht erheblich von dem roten Rechteck aus dem Metafile ab! Noch abweichender sieht es aus, wenn ich die PageUnit (sowohl beim Schreiben in die Datei als auch zum Zeichnen in die Form) von Millimetern auf Inch setze (statt einer Größe von 150 Millimetern habe ich 5 Inch gewählt), dann findet nicht nur eine Translation meines Rechtecks, sondern auch noch eine Skalierung statt (das Rechteck wird verkleinert in die Form gezeichnet).

Meine Frage und mein Problem: Weiß jemand wie es zu dieser Translation bzw. Skalierung in der Metadatei kommt? Kann mir jemand sagen, wie man diese Eingriffe verhindern oder rückgängig machen kann? Ich möchte genau angeben können, an welchem Punkt die Zeichnung (und nicht der virtuelle Rahmen) aus der Metadatei zu liegen kommt. D.h. in dem obigen Beispiel würde ich mir wünschen, dass wenn ich angebe, dass die „metadatei1“ an Punkt x = 0, y = 0 gezeichnet werden soll, und sich darin ein Rechteck mit den Koordinaten x = 0, y = 0, befindet, dieses auch in der oberen linken Ecke der Form, bei x = 0, y = 0, zu liegen kommt!

Ich bin für jede Anregung dankbar, habe auch schon viel herumprobiert, z.B. mit Metafile.PhysicalDimension oder Metafile.GetBounds sowie versucht, etwas aus dem MetafileHeader herauszulesen etc., habe aber noch keine richtige Lösung gefunden.

Vielen Dank im Voraus für jegliche Mühe mit meinem Problem!

139 Beiträge seit 2006
vor 16 Jahren

Probiers mal mit Graphics.Pixeloffset (oder es hies PixeloffsetMode) = PixelOffset.HighQuality

Gruss Ari
Wer lesen kann ist klar im vorteil!
MSDN
Dein Feund in allen fragen

M
Minsky Themenstarter:in
3 Beiträge seit 2008
vor 16 Jahren
Metafile-Grafik

Danke TNDAri für Deinen Tipp mit:


Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

Ich habe es ausprobiert, aber leider wird meine Grafik in dem Metafile trotzdem noch verschoben und skaliert. Es handelt sich auch nicht einfach um ein oder zwei Pixel, die PixelOffset ausgleichen könnte, sondern um mehrere Zentimeter.

Beste Grüße
M.M.

I
1.739 Beiträge seit 2005
vor 16 Jahren
hmm
  1. Du erstellst kein Metafile sondern nur Pixelgrafik, gekapselt in ein Metafile(es sei denn du hast wesentlichen Code ausgelassen.
  2. mm sind daher Pixelabstände
  3. Welches Metafile? 😉
    a) wird keins erstellt, bzw. erstellt, gespeichert und vernichtet(Ctor der Form)
    b) in Pixeln darin rumgemacht(buttonclick). Geladen, gespielt verworfen.
    c) Darstellung(Onpaint) ist unabhängig von Grafik und selbstgemalten.

Wo ist der Fehler?
Anregungen gegeben.
(Falls es nicht ausreicht, nochmals posten)

M
Minsky Themenstarter:in
3 Beiträge seit 2008
vor 16 Jahren

Hallo ikaros,

ein Dank für Deine Anregungen, die mir aber leider noch nicht weitergeholfen haben.

Zu 1:

  1. Du erstellst kein Metafile sondern nur Pixelgrafik, gekapselt in ein Metafile(es sei denn du hast wesentlichen Code ausgelassen.

Ja, ich habe viel - aber hoffentlich nicht wesentlichen - Code ausgelassen, weil ich auf mein Problem so kurz als möglich verweisen wollte. Deswegen scheint mein Programmfetzen auch keinen Sinn zu machen, aber laut meiner Bauanleitung (in dem Buch: "Graphics Programming with GDI+" von Mahesh Chand) erstelle ich schon ein richtiges Metafile! Ausser ich habe da was nicht richtig verstanden?

Zu 3:

  1. Welches Metafile? 😉
    a) wird keins erstellt, bzw. erstellt, gespeichert und vernichtet(Ctor der Form)
    b) in Pixeln darin rumgemacht(buttonclick). Geladen, gespielt verworfen.
    c) Darstellung(Onpaint) ist unabhängig von Grafik und selbstgemalten.

Ich erstelle ein Metafile mit dem namen "metafile1" das auf das File "Unbenannt. emf" verweist. Und schreibe mit dem „Buttonclick“ durch die Anweisung "Graphics.FromImage(metafile1)" in dieses File (Unbenannt.emf) ein Rechteck hinein! Speichern und dann "vernichten", wie Du schreibst, werde ich das Metafile "metafile1" erst, nachdem ich das Metafile in die Form (auf den Bildschirm) gezeichnet habe. Also mit "metafile1.Dispose();" am Ende des gesamten Vorganges. Das File "vernichte" ich nicht.

Da ich das File "Unbenannt.emf" auch mit anderen Programmen öffnen und bearbeiten kann, und da sich darin das von mir hineingezeichnete (Buttonclick)-Rechteck befindet, so gehe ich davon aus, dass ich das File auch richtig angelegt und beschrieben habe?

Zu 2:

  1. mm sind daher Pixelabstände

Ja, ich glaube auch, dass mein Problem irgendwie in den Umrechnungen der Maßeinheiten versteckt liegt, aber ich kann noch nicht genau verstehen warum?

a) ich schreibe mein Rechteck in das "metafile1", nachdem ich durch "g.PageUnit = GraphicsUnit.Millimeter;" die Maßeinheit des Graphics-Objekt auf Millimeter gesetzt habe. Ich vermute, dass während des Speichervorgangs dieses Rechteck in das Pixel-Format umgerechnet wird, denn
b) wenn ich dieses "metafile1" im Pixel-Format (also PageUnit = Pixel) in die Form zeichne, so ist es richtig dimensioniert, aber
c) wenn ich vorher wie in meinem Beispiel (PageUnit = Millimeter) ein anderes Format als Pixel wähle, bekomme ich immer verfälschte Größen angezeigt!

Ich versuche nochmals meine Frage zu verdeutlichen:
Ist es möglich (und wie?) eine „emf“-Datei, in die vorher mit einer bestimmten Masseinheit gezeichnet wurde, auch wieder in einer bestimmten Masseinheit (z.B. Millimeter oder Inch) zu öffnen und auf den Bildschirm (d.h. in eine Form) zu zeichnen?? In meinem Beispiel von oben kommen immer irgendwelche Verzerrungen (Translationen und Skalierungen) vor, die ich nicht verorten kann!?

P.S.: Ich halte es aber auch nicht für völlig ausgeschlossen, dass ich irgendwas bei dem Thema "Metafile" grundsätzlich missverstanden habe? Hast Du, "ikaros", oder hat jemand anderes eine bessere Einführung in die Metafile-Programmierung? Oder evt. Code-Beispiele?

Sorry für die umständliche Beschreibung meines Problems, aber ich bekomme es nicht besser formuliert.

Grüße,
M.M.