AutoIt : Gérer la transparence des images

L’AutoIt est un langage compilé très pratique pour la conception de petits scripts d’automatisation de tâche. Cependant, la surcouche GUI étant dépendante de la bibliothèque Windows WinAPI, il peut s’avérer laborieux de gérer les fenêtres et leur contenu. Il s’avère en effet très compliqué au premier abord d’afficher une image PNG transparente, AutoIt ne prenant en charge que les formats BMP, JPG et GIF non-animés. Nous allons donc voir comment effectuer ceci de manière simplifiée.

Les extraits de code contenus dans cet article vont vous montrer comment afficher une fenêtre dont le background est une image transparente, qui contient elle même une image transparente.

Bibliothèques, variables globales et fonctions outils

Avant de commencer, il est nécessaire d’importer les bibliothèques dont nous nous servirons et de définir quelques variables telles que la largeur et la hauteur (respectivement $width et $height) de la fenêtre principale. Il peut également être intéressant de définir en variable la position de l’image à afficher dans la fenêtre ($left et $top).

#Include <GUIConstantsEx.au3>
#Include <Icons.au3>
#Include <WinAPIEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <ButtonConstants.au3>
#include <StaticConstants.au3>
#Include <WinAPI.au3>

Ces positions sont définies en pixels :

Global $width = 800
Global $height = 600
Global $left = 50
Global $top = 10

Nous allons également utiliser une fonction outil servant à gérer les images PNG comme des Bitmaps grâce à la bibliothèque WinAPI :

Func _SetBitmap($hWnd, $hBitmap, $iOpacity)
 Local $hDC, $hMemDC, $tBlend, $tSize, $tSource

 $hDC = _WinAPI_GetDC($hWnd)
 $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
 _WinAPI_SelectObject($hMemDC, $hBitmap)
 $tSize = _WinAPI_GetBitmapDimension($hBitmap)
 $tSource = DllStructCreate($tagPOINT)
 $tBlend = DllStructCreate($tagBLENDFUNCTION)
 DllStructSetData($tBlend, 'Alpha', $iOpacity)
 DllStructSetData($tBlend, 'Format', 1)
 _WinAPI_UpdateLayeredWindow($hWnd, $hDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
 _WinAPI_ReleaseDC($hWnd, $hDC)
 _WinAPI_DeleteDC($hMemDC)
EndFunc

Les fenêtres

Maintenant que cette fonction est implémentée, nous allons créer deux variables dans lesquelles seront stockées les images que nous voulons afficher (background.png et image.png) :

$hBackground = _Icons_Bitmap_Load(@ScriptDir & '\background.png')
$hImage = _Icons_Bitmap_Load(@ScriptDir & '\image.png')

L’étape suivante est de créer les fenêtres qui vont contenir les images. Ainsi, pour gérer les images transparentes, il va être nécessaire de créer une fenêtre par image, avec des attributs bien particuliers. Pour la fenêtre de background, il faudra utiliser : « BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST) » et pour toutes les autres fenêtre, ce sera : BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD, $WS_EX_TOPMOST), couplé avec la déclaration de la première fenêtre comme parent (dernier argument de la fonction GUICreate).

$hGUI = GUICreate('', $width, $height, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
$hGUI_A = GUICreate('', $width, $height, $left, $top, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD, $WS_EX_TOPMOST), $hGUI)

Une fois ces fenêtres crées, nous leur attribuons leur image respective et demandons au programme des les afficher.

_SetBitmap($hGUI, $hBackground, 255)
_SetBitmap($hGUI_A, $hImage, 255)

GUISetState(@SW_SHOW, $hGUI)
GUISetState(@SW_SHOW, $hGUI_A)

Pour finir, la boucle principale va permettre aux fenêtres de rester affichées jusqu’à ce que l’utilisateur quitte le programme.

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

La gestion du curseur

Nous avons donc réussi à afficher une image transparente sur un background lui-même transparent. Toutefois, l’architecture de fenêtres superposées engendre le problème de la gestion du curseur. En effet, comment intercepter les clics sur le background alors que des fenêtre viennent par dessus ? La réponse : les évènements customs.

Nous allons déclarer le « drag » sur le clic gauche de la fenêtre du fond (ou la fenêtre de votre choix) et préparer le clic droit pour n’importe quelle action, à l’aide de ces fonctions :

Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
 _SendMessage($hGUI, $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
EndFunc ;
Func _WM_RBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Il faut ensuite rattacher ces évènements au programme :

GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")
GUIRegisterMsg($WM_RBUTTONDOWN, "_WM_RBUTTONDOWN")

Ainsi, la fenêtre devient déplaçable d’un simple cliquer-glisser.

La gestion du texte

Il reste la question du texte à afficher par-dessus nos images, car les labels ne sont pas transparents par défaut. Et bien là-encore, il s’agit de créer une fenêtre à rattacher au background.

$hGUI_text = GUICreate('', $width, $height, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD, $WS_EX_TOPMOST), $hGUI)

Il faut ensuite définir une couleur de fond du texte qui sera la couleur de transparence et une couleur de texte par défaut :

GUISwitch($hGUI_text)
GUISetBkColor(0x000000)
GUISetFont(14, 800, 0, "Candara")
GUICtrlSetDefColor(0xFFFFFF)
GUICtrlCreateLabel("Du texte", 10, 10)

Et définir la couleur de transparence de la fenêtre :

_WinAPI_SetLayeredWindowAttributes($hGUI_text, 0x000000, 0xFF)

Les labels seront alors transparents !

Conclusion

Grâce à la création de fenêtre parent/enfant superposées, il est possible de gérer de manière assez simple la transparence des images ainsi que des labels de texte. N’hésitez pas à apporter vos propres améliorations à ces scripts.

Article rédigé par Julien TAUBENHAUS

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Êtes-vous humain ? *