Metafiles
WINDOWS Metafiles sind eine weitere Möglichkeit zur Abspeicherung von Grafiken.
Im Gegensatz zu Bitmaps, in den die Bildinformation als einzelne Punkten enthalten
ist, enthalten WMF-Dateien (WindowsMetaFile)
die Bildinformation als kodierte GDI-Befehle. Dadurch kann eine WMF-Grafik ohne
Qualitätsverlust beliebig skaliert werden da beim Ändern der Grafikgröße nur die
Koordinaten für die Grafikbefehle neu berechnet werden.
Um eine WMF-Datei zu erstellen (nicht um sie einzulesen) müssen Sie sich zuerst
einen Metafile-DC holen. Die MFC stellt dazu die Klasse CMetaFileDC zur
Verfügung. Dieser DC-Objekt ist aber noch an keine Datei gebunden. Um das DC-Objekt
mit einer Datei zu verbinden, rufen Sie die CMetaFileDC-Methode CreateEnhanced(...)
auf. Diese Methode erhält zuerst einen Zeiger auf ein CDC-Objekt, das als
Referenz für das WMF dienen soll. Wenn Sie hier den Wert NULL angeben wird der aktuelle
Bildschirm als Referenz für die Auflösung (Größe) verwendet. Danach ist der Namen
der zu erstellenden WMF-Datei anzugeben. Diese Datei sollte die Extension EMF (für
Extented MetaFile) besitzen. Der nächste Parameter zeigt auf eine RECT-Struktur,
die die Ausdehnung der abzuspeichernden Grafik in HIMETRIC Einheiten (0,01 mm) definiert.
Wird hierfür der Wert NULL angegeben, dann wird die Ausdehnung automatisch so berechnet,
dass die gesamte Grafik darin Platz findet. Mit Hilfe des letzten Parameters kann
die Grafik noch mit einem Kommentar versehen. Diese Kommentar besteht aus zwei Teilen:
dem Namen der Applikation, die die Grafik erzeugt hat, und einem Titel. Die Kommentarteile
sind durch eine '0' zu trennen und der Kommentar selbst ist mit zwei Null-Bytes
abzuschließen. Wenn Sie keinen Kommentar benötigen, so können Sie auch hier den
Wert NULL angeben.
Um nun in eine WMF-Datei 'zu zeichnen' verwenden Sie gleichen Anweisungen wie
beim Zeichnen innerhalb eines Fensters nur mit dem Unterschied, dass Sie hier jetzt
nicht mit dem Fenster-DC Objekt zeichnen sondern mit dem vorher erstellten CMetaFileDC
Objekt.
 |
Einige CDC-Methoden werten beim Zeichen die Membervariable
m_hAttribDC des DCs aus. Diese wird aber von CreateEnhanced(...)
nicht gesetzt. Sie sollten daher diese Membervariable vor dem ersten Zeichen
mit der CDC-Membervariable m_hDC initialisieren. |
Wurde die Grafik komplett gezeichnet, muss die WMF-Datei geschlossen werden.
Um die WMF-Datei zu schließen rufen Sie die CMetaFileDC-Methode CloseEnhanced(...)
auf. Sie liefert als Returnwert ein Handle auf die erstellte WMF-Datei. Mit Hilfe
dieses Handles könnten Sie dann die WMF-Datei wiedergeben (was wir nachher in einem
zweiten Schritt tun werden) oder auch einzelne Einträge der WMF-Datei (GDI-Anweisungen)
editieren. Wird das erhaltene Metafile-Handle nicht mehr benötigt, so muss es durch
den Aufruf der API-Funktion DeleteEnhMetaFile(...) freigegeben werden.
 |
Wenn Sie in Metafiles zeichnen achten Sie immer darauf, dass Sie alle beim
Zeichnen belegten Ressourcen auch wieder freigeben, d.h. zu jedem SelectObject(...)
sollte auch ein DeleteObject(...) vorhanden sein. Tun Sie dies nicht,
so kann es Ihnen unter Umständen bei wiederholter Wiedergabe (Anzeige) der WMF-Datei
passieren dass der GDI-Heap überläuft! |
Sehen wir uns nun an, wie ein und die selbe OnDraw(...) Methode des
Ansichtsobjektes dazu verwendet werden kann um einmal in eine WMF-Datei zu zeichnen
und das andere mal innerhalb des Fensters.
/////////////////////////////////////////////////////////////////////////
// CGdiDrawView Zeichnen
void CGdiDrawView::OnDraw(CDC* pDC)
{
CGdiDrawDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten
hinzufügen
CPen CBluePen(PS_DASH,0,RGB(0,0,255));
// Stift erstellen
// Das ist der DC, mit dem gezeichnet
wird
CDC *pPaintDC;
if (m_bWMF)
{
// Falls
in WMF-Datei zeichnen
pPaintDC
= new CMetaFileDC;
((CMetaFileDC*)pPaintDC)->CreateEnhanced(pDC,"curve.emf",NULL,NULL);
pPaintDC->m_hAttribDC = pPaintDC->m_hDC;
}
else
// Es
wird ins Fenster gezeichnet
pPaintDC
= pDC;
// Hier wird nun gezeichnet
pPaintDC->SetBkColor(RGB(0,255,0));
pPaintDC->SetBkMode(OPAQUE);
pPaintDC->SelectObject(&CBluePen);
pPaintDC->MoveTo(0,m_CMin.y);
pPaintDC->LineTo(0,m_CMax.y);
....
if (m_bWMF)
{
// Falls
WMF-Datei erstellt wurde, WMF schliessen
HENHMETAFILE
hWMF = ((CMetaFileDC*)pPaintDC)->CloseEnhanced();
::DeleteEnhMetaFile(hWMF);
m_bWMF = FALSE;
// und
Fenster auch neu darstellen lassen
Invalidate();
}
} |
Kommen wir nun zum Einlesen einer WMF-Datei. Auch hier muss zuerst die gewünschte
WMF-Datei geöffnet werden. Leider bietet die MFC keine direkte Unterstützung hierfür
an sondern es muss die API-Funktion GetEnhMetaFile(...) eingesetzt werden.
Als Parameter erhält die Funktion den Namen der zu ladenden WMF-Datei und
als Returnwert wird das Metafile-Handle geliefert. Um den Inhalt der Datei (das
sind die kodierten GDI-Befehle) wiederzugeben, wird die CDC-Methode
PlayMetaFile(...) verwendet. Sie erhält als ersten Parameter das von GetEnhMetaFile(...)
zurückgelieferte Handle und im zweiten Parameter wird der Bereich spezifiziert,
innerhalb dessen die WMF-Datei dargestellt wird. Die Ausgabe der WMF-Datei wird
hierbei entsprechend skaliert. Wird das Handle der Metafile-Datei nicht mehr benötigt,
so muss es mit der bereits bekannten API-Funktion DeleteEnhMetaFile(...)
freigegeben werden.
Damit würde sich für die Wiedergabe einer WMF-Datei folgende OnDraw(...)
Methode ergeben:
void CWMFReadView::OnDraw(CDC*
pDC)
{
CWMFReadDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten
hinzufügen
// WMF-Datei im gesamten Fenster darstellen
RECT ClientRect;
GetClientRect(&ClientRect);
HENHMETAFILE hWMF = ::GetEnhMetaFile("curve.emf");
if (hWMF != NULL)
{
pDC->PlayMetaFile(hWMF,&ClientRect);
::DeleteEnhMetaFile(hWMF);
}
} |
 |
Es gibt noch ein weiteres Format der WMF-Dateien das aber aus
Zeiten von WINDOWS 3.x stammt. Dateien mit diesem 'alten' Format haben in der
Regel die Extension WMF. Das 'alte' WMF-Format unterstützt wesentlich weniger
GDI-Funktionen. Dies sind insbesondere die Funktionen, die sich mit den Koordinatentransformationen
befassen. Um 'alte' WMF-Dateien zu bearbeiten sind andere Funktionen/Methoden
notwendig. So verbinden Sie z.B. eine solche Datei mit dem CMetaFileDC
über die Methode Create(...) anstelle der aufgeführten CreateEnhanced(...)
Methode. |
Damit verlassen wir nun endgültig die Darstellung von Grafikdateien und wenden
uns in der nächsten Lektion noch einigen weiteren GDI-Funktionen zu.
|