Zoomer, Tourner, Translater, c'est possible avec n'importe quoi avec les API Windows. La procedure qui nous intéresse s'appelle SetWorldTransform, voici son prototype :
function SetWorldTransform(DC: HDC; const p2: TXForm): BOOL;
Le paramètre DC attend un "Device Context", c'est une sorte de Handle (un identifiant), un nombre entier unique que windows attribue à tout ce qui peut représenter une surface de dessin. D'habitude, c'est une valeur que l'on demande à windows comme ceci :
1 2 3 4 5 6 7 8
| uses windows;
...
var DC:HDC;
UnHandleDeFenetre:HWnd;
begin
UnHandleDeFenetre:=0;
DC:=GetDC(UnHandleDeFenetre);
end; |
Ici, HWND, est un l'identifiant d'une fenètre (un entier en fait) que Windows attribue à chaque fenètre existante dans Windows (Pour le bureau, cette valeur vaut zéro). Quand tu crées une fiche, c'est une fenètre (TForm possède une propriété Handle que tu peux utiliser, les controles fenétrés dérivés de TWinControl aussi).
Certains composants Delphi, possèdent un Handle de type HDC (tous les TGraphicControl en fait et les "surfaces de dessin" comme TCanvas et TMetaFileCanvas. C'est pratique : Delphi à déjà demandé à Windows de leur attribuer un identifiant unique afin de pouvoir dessiner dessus.
Le paramètre TXForm, c'est un enregistrement déclaré comme ceci :
1 2 3 4 5 6 7 8
| TXFORM = packed record
eM11: Single;
eM12: Single;
eM21: Single;
eM22: Single;
eDx: Single;
eDy: Single;
end; |
Le but du jeu avec ce paramètre, c'est de transformer x en x' et y en y', tel que :
1 2
| x' := x * eM11 + y * eM21 + eDx;
y' := x * eM12 + y * eM22 + eDy; |
Voici, selon la transformation que tu souhaites effectuer, voici quelques exemples de comment tu dois initialiser ces paramètres :
Rotation
eM11:=Cos(angle);
eM12:=Sin(angle);
eM21:=-Sin(angle);
eM22:=Cos(angle);
eDX:=0;
eDY:=0;
Zoom/Etirement
eM11:=Facteur_de_Zoom_Horizontal;
eM12:=0;
eM21:=0;
eM22:=Facteur_de_Zoom_Vertical;
eDX:=0;
eDY:=0;
Translation
eM11:=1;
eM12:=0;
eM21:=0;
eM22:=1;
eDX:=Translation_en_x;
eDY:=Translation_en_y;
Voici donc une procédure dont je me suis fendu qui va te permettre de transformer en Picasso du Delphi, celà fait appel a nos API Windows :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| procedure Transforme(ABitmap1,ABitmap2:TBitMap;Parametres:TXFORM);
var UnDeviceContext:HDC;
MatriceXForm:TXFORM;
ARect:TRect;
begin
//obtenir un contexte de périphérique sur le Bitmap à transformer
UnDeviceContext:=ABitMap2.Canvas.Handle;
//On met le mode graphique de notre Canvas en mode "Avancé"
//Sinon, ça ne marche pas :/
SetGraphicsMode(UnDeviceContext,GM_ADVANCED);
//On efface le bitmap en le remettant en mode "Normal"
with MatriceXForm do
begin
eM11:=1;
eM12:=0;
eM21:=0;
eM22:=1;
eDx:=0;
eDy:=0;
end;
SetWorldTransform(UnDeviceContext, MatriceXForm);
ARect:=Rect(0,0,ABitMap2.Width,ABitMap2.Height);
ABitMap2.Canvas.Brush.Color:=clBlack; //ou clWhite si tu préfères
ABitMap2.Canvas.FillRect(ARect);
//Transformation des coordonnées du Canvas
SetWorldTransform(UnDeviceContext, Parametres);
//Le Canvas possède maintenant un nouveau sytème de coordonnées
//On peut dessiner dessus :
ABitMap2.Canvas.Draw(0,0,ABitMap1);
end; |
En entrée, tu as donc ABitmap1 et en Sortie ABitMap2.
Bien sur, on peu adapter la procedure pour qu'elle fonctionne avec des TMetafile (ce qui sous-entend l'utilisation de TMetaFileCanvas), ou directement des Canvas. Mais là, c'est un bon début.
Bon dev
Partager