DESSINER UN METAFILE

C'est un sujet qui m'a donné du fil à retordre. En effet, il existe des images de type METAFILE et d'autres de type ENHANCED METAFILE. Ces 2 types ne sont pas vraiment compatibles, et Microsoft SDK décommande l'utilisation des API spécifiques des METAFILES.
Ils recommandent de convertir d'abord le METAFILE en ENHANCED METAFILE, puis d'effectuer les traitements avec les API des enhanced metafiles.

La difficulté réside dans la position et la taille de l'image dessinée. Comme le mode METAFILE ne précise pas vraiment de dimension d'image, la taille de l'image dessinée ou imprimée est imprévisible.
De plus, les 2 OS W95-98 et WNT ne se comportent pas du tout de la même façon, et certains codes fonctionnent bien sous l'un et mal sous l'autre.

Néanmoins, je propose une méthode qui semble fonctionner dans tous les cas.

On suppose qu'on dispose déjà du Handle (descripteur) d'une image en mode metafile. Ce handle peut par exemple, être la propriété .Picture (en fait, .Picture.Handle par défaut) d'un PictureBox si elle contient un WMF.
Exemple : PicHandle = MyPictureBox.Picture

Ce Handle peut aussi être obtenu directement à partir d'un fichier image. Par exemple :
PicHandle = LoadPicture("ImageTest.wmf").Handle
Attention : dans ce cas, le Handle doit être détruit après usage au moyen de l'API DeleteObject

Dans l'exemple suivant, on demande ensuite de dessiner l'image résultante sur un périphérique d'affichage (Device Context) dont le Handle est HDCdest

Déclarations :

Private Const NULLPTR = 0&
Private Const MM_ANISOTROPIC = 8

Private Type RECT
         Left As Long
         Top As Long
         Right As Long
         Bottom As Long
End Type

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long

' GESTION DE LA MEMOIRE
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hmem As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hmem As Long) As Long

' METAFILES
Private Type METAFILEPICT
         mm As Long
         xExt As Long
         yExt As Long
         hMF As Long
End Type
Private Declare Function DeleteEnhMetaFile Lib "gdi32" (ByVal hemf As Long) As Long
Private Declare Function PlayEnhMetaFile Lib "gdi32" (ByVal hdc As Long, ByVal hemf As Long, lpRect As RECT) As Long
Private Declare Function GetMetaFileBitsEx Lib "gdi32" (ByVal hMF As Long, ByVal nSize As Long, lpvData As Long) As Long
Private Declare Function SetWinMetaFileBits Lib "gdi32" (ByVal cbBuffer As Long, lpbBuffer As Long, ByVal hdcRef As Long, lpmfp As METAFILEPICT) As Long

Dim hmem As Long, hMemPtr As Long, rc As Long
Dim RecDest As RECT
Dim hEnhMetaFile As Long
Dim nSize As Long
Dim HDesk As Long
Dim EMF As METAFILEPICT

Code :

' On suppose que PicHandle est le handle d'un metafile
' On va transformer le Metafile en Enhanced-Metafile
' On obtient la longueur du buffer nécessaire

nSize = GetMetaFileBitsEx(PicHandle, 0&, ByVal 0&)

' On réserve un espace mémoire pour y stocker l'image en mode METAFILE
hmem = GlobalAlloc(&H40, nSize)
hMemPtr = hmem

rc = GetMetaFileBitsEx(PicHandle, nSize, ByVal hMemPtr)

         EMF.mm = MM_ANISOTROPIC
         EMF.xExt = 0
         EMF.yExt = 0

' On récupère le handle du enhanced metafile
hEnhMetaFile = SetWinMetaFileBits(nSize, ByVal hMemPtr, HDCdest, EMF)

' On libère la mémoire
rc = GlobalFree(hmem)

         RecDest.Left = Xdest
         RecDest.Top = Ydest
         RecDest.Right = Xdest + Widthdest
         RecDest.Bottom = Ydest + Heightdest

' On dessine l'image sur le périphérique de destination
rc = PlayEnhMetaFile(HDCdest, hEnhMetaFile, RecDest)

' On nettoie
DeleteEnhMetaFile hEnhMetaFile

Retour à l'accueil