Delphi XE2 und spätere Versionen haben einen großen Teil der Windows-API-Deklarationen in die bereichsbezogene Unit Winapi.Windows verschoben und mehrere Record-Deklarationen strenger gemacht. Code, der in älteren Delphi-Versionen kompiliert wurde, kann deshalb fehlschlagen, wenn ein Enhanced-Metafile-Record einen tagLOGBRUSH32-Wert liefert, die GDI-API aber tagLOGBRUSH oder TLogBrush erwartet.
Das Symptom erscheint meist beim Wiedergeben von EMF-Records oder beim Neuaufbau von GDI-Brush-Objekten aus PEMRCreateBrushIndirect. Ein direkter Aufruf wie der folgende wirkt plausibel, aber die beiden Record-Typen sind in neueren Delphi-Compilern nicht zuweisungskompatibel.
|
1 2 3 4 5 |
procedure VEMRCREATEBRUSHINDIRECT(Data: PEMRCreateBrushIndirect); begin GDIObjects[Data^.ihBrush] := CreateBrushIndirect(Data^.lb); //GDIObjects and CreateBrushIndirect are defined in the winapi.windows unit. end; |
Der Compiler meldet E2010 Incompatible types: 'tagLOGBRUSH' and 'tagLOGBRUSH32'. Erzwingen Sie den Record nicht mit einem unsicheren Cast. Sicherer ist es, einen lokalen TLogBrush zu erstellen, die kompatiblen Felder ausdrücklich zu kopieren und diese Struktur an CreateBrushIndirect zu übergeben.
|
1 2 3 4 5 6 7 8 9 |
procedure VEMRCREATEBRUSHINDIRECT(Data: PEMRCreateBrushIndirect); var LogBrush: TLogBrush; begin LogBrush.lbStyle := Data^.lb.lbStyle; LogBrush.lbColor := Data^.lb.lbColor; LogBrush.lbHatch := Data^.lb.lbHatch; GDIObjects[Data^.ihBrush] := CreateBrushIndirect(LogBrush); end; |
Warum die explizite Kopie sicherer ist
tagLOGBRUSH32 wird im EMF-Recordformat verwendet, damit die serialisierten Metafile-Daten ein stabiles 32-Bit-Feldlayout haben. CreateBrushIndirect akzeptiert dagegen die normale Windows-Brush-Struktur der aktuellen API-Deklaration. Das Kopieren von lbStyle, lbColor und lbHatch dokumentiert die Umwandlung und vermeidet Abhängigkeit von compilerspezifischer Record-Kompatibilität.
Dieses Muster lässt sich auch leichter prüfen, wenn alter Grafikcode nach Unicode Delphi oder auf 64-Bit-Ziele portiert wird. Falls eine spätere Windows-SDK-Deklaration Typaliasse erneut ändert, macht die feldweise Konvertierung die beabsichtigte Datengrenze klar.
Portierungscheckliste
- Behalten Sie
Winapi.Windowsin deruses-Liste moderner Delphi-Projekte. - Kopieren Sie EMF-Recordfelder in die API-Struktur, die der GDI-Aufruf erwartet.
- Ersetzen Sie dies nicht durch einen blinden Pointer-Cast, solange binäres Layout und Lebensdauer nicht geprüft sind.
- Nachdem der Brush erstellt wurde, behalten Sie die bestehenden Ownership-Regeln für Ihre
GDIObjects-Tabelle bei.
Warum dies bei Delphi-Upgrades auftaucht
Alter EMF-Wiedergabecode behandelt Windows-Records oft so, als wären API-Strukturen und serialisierte Metafile-Strukturen austauschbar. Ältere Units und lockerere Aliasnamen ließen diese Annahme manchmal kompilieren. Moderne Delphi-Deklarationen sind strenger, sodass der Compiler die Grenze sichtbar macht, die in der Windows-API bereits vorhanden war.
Der Fehler ist daher nicht nur ein Syntaxproblem. Er ist ein nützlicher Hinweis, dass der Code von einer Dateiformatstruktur in einen aktiven GDI-Aufruf wechselt. Eine explizite Konvertierung macht den Code sicherer, wenn er später für 64-Bit-Builds, Unicode-Migration oder aktualisierte Windows-SDK-Deklarationen geprüft wird.
Was Sie vermeiden sollten
Ein Pointer-Cast kann den Compilerfehler scheinbar beseitigen, verbirgt aber die eigentliche Konvertierung und erschwert spätere Wartung. Außerdem sehen Prüfer nicht, welche Felder absichtlich verwendet werden. Die Feldkopie ist kurz, deterministisch und selbstdokumentierend, daher ist sie die bessere Vorgabe für Anwendungscode und Komponentenbeispiele.
Wenn Ihr EMF-Parser viele ähnliche Records verarbeitet, kapseln Sie diese Konvertierung in einer kleinen Hilfsfunktion und testen Sie sie mit mehreren Brush-Stilen. So bleibt die Wiedergabeschleife lesbar, während die Windows-API-Grenze explizit bleibt.