Transformation de metafile Windows (rotation, miroir, inversion)
Date de publication : 26/02/2005
Par
Pierre Castelain (Contributions)
Routine Delphi de transformation d'un metafile Windows (image au format vectoriel)
Voici une unité contenant une procédure de transformation d'un metafichier Windows.
Les metafichiers (wmf ou emf) sont des fichiers images contenant la description
vectorielle d'un dessin. Ils ont l'avantage de pouvoir être redimensionnés sans
perte de qualité. Par contre, leur modification en mémoire est assez fastidieuse.
Le source suivant vous permet d'appliquer plusieurs transformations à un de ces
fichiers en mémoire : rotation (dans le sens inverse des aiguilles d'une montre,
inversion (haut-bas) et miroir (droite-gauche).
Pour l'utiliser, passez le handle d'un TMetafile à la procédure en indiquant les
transformations désirées.
Ce code source n'est pas parfait car la transformation de certains ordres GDI n'est pas
supportée. Par exemple, si le metafile contient du texte, celui-ci ne subira pas les
transformations.
GDI+ vous permet d'appliquer des transformations beaucoup plus évoluées lors du tracé. Vous êtes
encouragés à l'utiliser, mais si pour une raison quelconque cela n'est pas possible, vous pouvez
utiliser cette unité.
unit EMFTransform;
interface
uses
Classes, Windows;
procedure TransformEMF(emf: HENHMETAFILE; DoRotate, DoFlip, DoMirror: boolean);
implementation
uses
SysUtils, Dialogs;
var
centerl: TPoint;
Rotate, Flip, Mirror: boolean;
function SmallPoint(x, y: SHORT): TSmallPoint;
begin
Result.x:= x;
Result.y:= y;
end;
function RectCenter(rec: TRect): TPoint;
begin
result:= Point((rec.Left + rec.Right) div 2, (rec.Top + rec.Bottom) div 2);
end;
procedure InvertHVRect(var rec: TRect);
var
tmp: LongInt;
begin
tmp:= rec.Left;
rec.Left:= rec.Top;
rec.Top:= tmp;
tmp:= rec.Right;
rec.Right:= rec.Bottom;
rec.Bottom:= tmp;
end;
procedure InvertHVPoint(var pt: TPoint);
var
tmp: LongInt;
begin
tmp:= pt.X;
pt.X:= pt.Y;
pt.Y:= tmp;
end;
procedure RotatePoint(var pt: TPoint; center: TPoint);
begin
pt:= Point(pt.Y, 2*center.X - pt.X);
end;
procedure FlipPoint(var pt: TPoint; center: TPoint);
begin
pt:= Point(pt.X, 2*center.Y - pt.Y);
end;
procedure MirrorPoint(var pt: TPoint; center: TPoint);
begin
pt:= Point(2*center.X - pt.X, pt.Y);
end;
procedure RotateSmallPoint(var pt: TSmallPoint; center: TPoint);
begin
pt:= SmallPoint(pt.Y, 2*center.X - pt.X);
end;
procedure FlipSmallPoint(var pt: TSmallPoint; center: TPoint);
begin
pt:= SmallPoint(pt.X, 2*center.Y - pt.Y);
end;
procedure MirrorSmallPoint(var pt: TSmallPoint; center: TPoint);
begin
pt:= SmallPoint(2*center.X - pt.X, pt.Y);
end;
procedure RotateRect(var r: TRect; center: TPoint);
var
p2, p4: TPoint;
begin
p2:= Point(r.Right, r.Top);
p4:= Point(r.Left, r.Bottom);
RotatePoint(p2, Center);
RotatePoint(p4, Center);
r:= Rect(p2.X, p2.Y, p4.X, p4.Y);
end;
procedure FlipRect(var r: TRect; center: TPoint);
var
p1, p2: TPoint;
begin
p1:= r.TopLeft;
p2:= r.BottomRight;
FlipPoint(p1, center);
FlipPoint(p2, center);
r.Top:= p2.Y;
r.Bottom:= p1.Y;
end;
procedure MirrorRect(var r: TRect; center: TPoint);
var
p1, p2: TPoint;
begin
p1:= r.TopLeft;
p2:= r.BottomRight;
MirrorPoint(p1, center);
MirrorPoint(p2, center);
r.Left:= p2.X;
r.Right:= p1.X;
end;
procedure RotateSize(var sz: TSize);
var
tmpl: LongInt;
begin
tmpl:= sz.cx;
sz.cx:= sz.cy;
sz.cy:= tmpl;
end;
function EnhMetaFileProc_Manipulate(DC: HDC; lpHTable: PHandleTable; lpEMFR: PENHMetaRecord; nObj: integer; lpData: LPARAM): integer; stdcall;
var
i: integer;
begin
Result:= 1;
case lpEMFR^.iType of
EMR_HEADER:
with PEnhMetaHeader(lpEMFR)^ do
begin
if Rotate then
begin
InvertHVRect(PEnhMetaHeader(lpEMFR)^.rclBounds);
InvertHVRect(PEnhMetaHeader(lpEMFR)^.rclFrame);
RotateSize(PEnhMetaHeader(lpEMFR)^.szlDevice);
RotateSize(PEnhMetaHeader(lpEMFR)^.szlMillimeters);
end;
end;
EMR_LINETO, EMR_MOVETOEX:
begin
if Rotate then
RotatePoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
if Flip then
FlipPoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
if Mirror then
MirrorPoint(PEMRLineTo(lpEMFR)^.ptl, centerl);
end;
EMR_OFFSETCLIPRGN:
begin
if Rotate then
RotatePoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
if Flip then
FlipPoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
if Mirror then
MirrorPoint(PEMROffsetClipRgn(lpEMFR)^.ptlOffset, centerl);
end;
EMR_FILLPATH, EMR_STROKEANDFILLPATH, EMR_STROKEPATH:
begin
if Rotate then
RotateRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRFillPath(lpEMFR)^.rclBounds, centerl);
end;
EMR_EXCLUDECLIPRECT, EMR_INTERSECTCLIPRECT:
begin
if Rotate then
RotateRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
if Flip then
FlipRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
if Mirror then
MirrorRect(PEMRExcludeClipRect(lpEMFR)^.rclClip, centerl);
end;
EMR_SETWINDOWORGEX:
with PEMRSetViewportOrgEx(lpEMFR)^ do
begin
end;
EMR_SETVIEWPORTORGEX, EMR_SETBRUSHORGEX:
with PEMRSetViewportOrgEx(lpEMFR)^ do
begin
end;
EMR_SETVIEWPORTEXTEX, EMR_SETWINDOWEXTEX:
begin
end;
EMR_SETPIXELV:
begin
if Rotate then
RotatePoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
if Flip then
FlipPoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
if Mirror then
MirrorPoint(PEMRSetPixelV(lpEMFR)^.ptlPixel, centerl);
end;
EMR_EXTFLOODFILL:
begin
if Rotate then
RotatePoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
if Flip then
FlipPoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
if Mirror then
MirrorPoint(PEMRExtFloodFill(lpEMFR)^.ptlStart, centerl);
end;
EMR_ELLIPSE, EMR_RECTANGLE:
begin
if Rotate then
RotateRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
if Flip then
FlipRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
if Mirror then
MirrorRect(PEMREllipse(lpEMFR)^.rclBox, centerl);
end;
EMR_ROUNDRECT:
begin
if Rotate then
begin
RotateRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
RotateSize(PEMRRoundRect(lpEMFR)^.szlCorner);
end;
if Flip then
FlipRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
if Mirror then
MirrorRect(PEMRRoundRect(lpEMFR)^.rclBox, centerl);
end;
EMR_ARC, EMR_ARCTO, EMR_CHORD, EMR_PIE:
begin
if Rotate then
begin
RotateRect(PEMRArc(lpEMFR)^.rclBox, centerl);
RotatePoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
RotatePoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
end;
if Flip then
begin
FlipRect(PEMRArc(lpEMFR)^.rclBox, centerl);
FlipPoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
FlipPoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
end;
if Mirror then
begin
MirrorRect(PEMRArc(lpEMFR)^.rclBox, centerl);
MirrorPoint(PEMRArc(lpEMFR)^.ptlStart, centerl);
MirrorPoint(PEMRArc(lpEMFR)^.ptlEnd, centerl);
end;
end;
EMR_ANGLEARC:
begin
if Rotate then
RotatePoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
if Flip then
FlipPoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
if Mirror then
MirrorPoint(PEMRAngleArc(lpEMFR)^.ptlcenter, centerl);
end;
EMR_POLYLINE, EMR_POLYBEZIER, EMR_POLYGON, EMR_POLYBEZIERTO, EMR_POLYLINETO:
begin
if Rotate then
RotateRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyline(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyline(lpEMFR)^.cptl-1 do
begin
if Rotate then
RotatePoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
if Flip then
FlipPoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
if Mirror then
MirrorPoint(PEMRPolyline(lpEMFR)^.aptl[i], Centerl);
end;
end;
EMR_POLYLINE16, EMR_POLYBEZIER16, EMR_POLYGON16, EMR_POLYBEZIERTO16, EMR_POLYLINETO16:
begin
if Rotate then
RotateRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyline16(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyline16(lpEMFR)^.cpts-1 do
begin
if Rotate then
RotateSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
if Flip then
FlipSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
if Mirror then
MirrorSmallPoint(PEMRPolyline16(lpEMFR)^.apts[i], Centerl);
end;
end;
EMR_POLYDRAW:
begin
if Rotate then
RotateRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyDraw(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyDraw(lpEMFR)^.cptl-1 do
begin
if Rotate then
RotatePoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
if Flip then
FlipPoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
if Mirror then
MirrorPoint(PEMRPolyDraw(lpEMFR)^.aptl[i], Centerl);
end;
end;
EMR_POLYDRAW16:
begin
if Rotate then
RotateRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyDraw16(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyDraw16(lpEMFR)^.cpts-1 do
begin
if Rotate then
RotateSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
if Flip then
FlipSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
if Mirror then
MirrorSmallPoint(PEMRPolyDraw16(lpEMFR)^.apts[i], Centerl);
end;
end;
EMR_POLYPOLYLINE, EMR_POLYPOLYGON:
begin
if Rotate then
RotateRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyPolyLine(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyPolyLine(lpEMFR)^.cptl-1 do
begin
if Rotate then
RotatePoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
if Flip then
FlipPoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
if Mirror then
MirrorPoint(PEMRPolyPolyLine(lpEMFR)^.aptl[i], Centerl);
end;
end;
EMR_POLYPOLYLINE16, EMR_POLYPOLYGON16:
begin
if Rotate then
RotateRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
if Flip then
FlipRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
if Mirror then
MirrorRect(PEMRPolyPolyLine16(lpEMFR)^.rclBounds, centerl);
for i:=0 to PEMRPolyPolyLine16(lpEMFR)^.cpts-1 do
begin
if Rotate then
RotateSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
if Flip then
FlipSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
if Mirror then
MirrorSmallPoint(PEMRPolyPolyLine16(lpEMFR)^.apts[i], Centerl);
end;
end;
EMR_EXTSELECTCLIPRGN:
begin
end;
EMR_SCALEVIEWPORTEXTEX, EMR_SCALEWINDOWEXTEX, EMR_SETWORLDTRANSFORM,
EMR_MODIFYWORLDTRANSFORM, EMR_INVERTRGN, EMR_PAINTRGN, EMR_FILLRGN,
EMR_FRAMERGN, EMR_EXTTEXTOUTA, EMR_EXTTEXTOUTW,
EMR_POLYTEXTOUTA, EMR_POLYTEXTOUTW :
begin
end;
end;
end;
procedure TransformEMF(emf: HENHMETAFILE; DoRotate, DoFlip, DoMirror: boolean);
var
metaHeader: TEnhMetaHeader;
begin
Rotate:= DoRotate;
Flip:= DoFlip;
Mirror:= DoMirror;
GetEnhMetaFileHeader(emf, SizeOf(TEnhMetaHeader), @metaHeader);
with metaHeader do
centerl:= Point((rclBounds.Left + rclBounds.Right) div 2,
(rclBounds.Top + rclBounds.Bottom) div 2);
EnumEnhMetaFile(0, emf, @EnhMetaFileProc_Manipulate, nil, Rect(0, 0, 0, 0));
end;
end.
| Articles | |
Delphi 2005 : Découvrez le futur Delphi 2005
| |
DirectX : Introduction à DirectX 9 en Delphi
| |
Variables d'environnement : Présentation, description et utilisation des variables d'environnement sous Windows
| |
Mailslots : Présentation des mailslots et de leur utilisation en Delphi pour la communication inter-processus
| | Projets complets avec sources | |
NumericalParser : Parser numérique en Delphi afin de transformer une chaîne de caractères en
valeur flottante ou entière.
| |
RegSearch : Composant de recherche dans la base de registre
| |
CDAReader : Lecture des informations contenues dans les fichier CDA de Windows
| |
ScreenSaverPreview : Composant d'affichage de l'aperçu des économiseurs d'écran de Windows
| |
ScanResources : Programme d'exploration des ressources des programmes ou des dll d'un répertoire
| |
ClipboardViewer : Démonstration de la détection des modifications et de l'affichage du contenu du presse-papier
| |
Matrix : Tentative de reproduction en Delphi de l'animation bien connue du film Matrix
| | Sources et exemples | |
EMFTransform : Transformation (rotation, inversion, miroir) d'un metafile Windows en mémoire
| |
DeleteKeyTree : Suppression récursive d'un clé de la base de registre
| |
MultiStrings : Routines de gestion de tableaux de chaînes C
| |
GetDllFilename : Pour récupérer le chemin d'une dll par son handle
| |
Extension du shell : Exemple d'extension du menu contextuel du shell de Windows
| |
TriStringGrid : Exemple de tri par colonne d'un composant TStringGrid à l'aide d'un algorithme
de tri rapide (quick sort)
| |
XPManifestCPL : Utilisation des contrôles XP dans une application du panneau de configuration (cpl)
| |
Bouboules : Modélisation à l'aide du design pattern Observer
| | Divers | |
Diagramme ternaire : Un logiciel gratuit de tracé de diagramme ternaire
|
|
|