Delphi XE2 y versiones posteriores trasladaron gran parte de las declaraciones de la API de Windows a la unidad con ámbito Winapi.Windows y endurecieron varias declaraciones de registros. Por eso, el código que compilaba en versiones antiguas de Delphi puede fallar cuando un registro Enhanced Metafile expone un valor tagLOGBRUSH32 pero la API GDI espera tagLOGBRUSH o TLogBrush.
El síntoma suele aparecer al reproducir registros EMF o al reconstruir objetos de pincel GDI desde PEMRCreateBrushIndirect. Una llamada directa como la siguiente parece razonable, pero los dos tipos de registro no son compatibles por asignación en compiladores Delphi recientes.
|
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; |
El compilador informa E2010 Incompatible types: 'tagLOGBRUSH' and 'tagLOGBRUSH32'. Evita forzar el registro mediante una conversión insegura. La corrección más segura es crear un TLogBrush local, copiar explícitamente los campos compatibles y pasar esa estructura a CreateBrushIndirect.
|
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; |
Por qué la copia explícita es más segura
tagLOGBRUSH32 se usa en el formato de registro EMF para que los datos serializados del metaarchivo tengan un diseño estable de campos de 32 bits. CreateBrushIndirect, en cambio, acepta la estructura normal de pincel de Windows usada por la declaración actual de la API. Copiar lbStyle, lbColor y lbHatch documenta la conversión y evita depender de compatibilidad de registros específica del compilador.
Este patrón también es más fácil de revisar al portar código gráfico heredado a Delphi Unicode o a destinos de 64 bits. Si una declaración posterior del Windows SDK vuelve a cambiar alias de tipos, la conversión campo por campo deja claro el límite de datos previsto.
Lista de comprobación de migración
- Mantén
Winapi.Windowsen la listausesde proyectos Delphi modernos. - Copia los campos del registro EMF en la estructura de API esperada por la llamada GDI.
- No sustituyas esto por una conversión ciega de puntero salvo que hayas verificado el diseño binario y la vida útil.
- Después de crear el pincel, conserva las reglas existentes de propiedad de objetos de tu tabla
GDIObjects.
Por qué aparece durante las actualizaciones de Delphi
El código heredado de reproducción EMF suele tratar los registros de Windows como si las estructuras de la API y las estructuras serializadas del metaarchivo fueran intercambiables. Unidades antiguas y alias más flexibles a veces permitían compilar esa suposición. Las declaraciones modernas de Delphi son más estrictas, por lo que el compilador expone el límite que ya existía en la API de Windows.
Por tanto, el error no es solo un problema de sintaxis. Es una advertencia útil de que el código cruza desde una estructura de formato de archivo hacia una llamada GDI activa. Mantener la conversión explícita hace el código más seguro cuando se revise después para compilaciones de 64 bits, migración Unicode o declaraciones actualizadas del Windows SDK.
Qué no hacer
Una conversión de puntero puede parecer que elimina el error del compilador, pero oculta la conversión real y puede dificultar el mantenimiento posterior. Tampoco da a los revisores ninguna pista sobre qué campos se usan intencionadamente. La copia de campos es corta, determinista y autoexplicativa, así que es la opción predeterminada más adecuada para código de aplicación y ejemplos de componentes.
Si tu analizador EMF maneja muchos registros similares, envuelve esta conversión en una pequeña función auxiliar y pruébala con varios estilos de pincel. Así el bucle de reproducción sigue siendo legible sin dejar de mantener explícito el límite de la API de Windows.