; Permet de créer une fenêtre skinnée avec une image. Un effet de transparence pourra être appliqué à certaines zones de l'images (couleur définie)
; Structure BITMAP
; bmType.l
; bmWidth.l
; bmHeight.l
; bmWidthBytes.l
; bmPlanes.w
; bmBitsPixel.w
; bmBits.l
; EndStructure
#Gdi = 0
#User = 1
OpenLibrary(#Gdi, "gdi32.dll")
OpenLibrary(#User, "user32.dll")
Procedure RegionColor(hBmp, color)
If hBmp ; si le handle n'est pas nul
;{ déclaration de variables
hDC_bmp.l
bmpstruct.bitmap ;
transparent.l
LineRegion = 0
FullRegion = 0
In_Line = 0
In_First_Region = 1
StartLine_X = 0
;}
If CallFunction(#Gdi, "GetObjectA", hBmp, SizeOf(BITMAP), @bmpstruct) = 0 ; on récupère des informations sur l'image et on vérifie le handle
ProcedureReturn 0 ;
EndIf
hDC_bmp = CallFunction(#Gdi, "CreateCompatibleDC", 0) ; on crée un device contexte
If hdc_bmp = 0 ; on vérifie qu'il aie été créé
ProcedureReturn 0 ;
EndIf
hBmp_old = CallFunction(#Gdi, "SelectObject", hDC_bmp, hBmp) ; on met l'image dans le dc
transparent = color ; on récupère la couleur transparente
For y = 0 To bmpstruct\bmHeight - 1 ; on "scanne"
For x = 0 To bmpstruct\bmWidth ; l'image
If CallFunction(#Gdi, "GetPixel", hDC_bmp, x, y) = transparent Or x = bmpstruct\bmWidth ; si la couleur du point est celle de transparence ou que l'on est à la droite de l'image, cela veux dire que l'on doit stopper la selection
If In_Line ; si avant il y avait un pixel coloré
In_Line = 0 ; on remet à zéro
LineRegion = CallFunction(#Gdi, "CreateRectRgn", StartLine_X, y, x, y + 1) ; on sélectionne une région rectangulaire d'une hauteur de 1 et d'une largeur correspondant au nombre de pixels non-transparent précédants le pixel transparent
If In_First_Region ; si c'est la première région que l'on sélectionne
In_First_Region = 0 ; on remet à zéro
FullRegion = LineRegion ; la région globale pour le moment sera cette région
Else
CallFunction(#Gdi, "CombineRgn", FullRegion, FullRegion, LineRegion, 2) ; sinon la région globale est l'union de la région globale actuelle plus celle que l'on viens de séléctionner
CallFunction(#Gdi, "DeleteObject", LineRegion) ; on n'a plus besoin de cette région maintenant
EndIf
EndIf
ElseIf In_Line = 0 ; sinon si avant le pixel est tranparent
In_Line = 1 ; on précise que le pixel est maitenant coloré
StartLine_X = x ; on garde la position de ce pixel afin de plus tard selectionner une région coloré
EndIf
Next
Next
CallFunction(#Gdi, "DeleteDC", hDC_bmp) ; et on supprime le dc
ProcedureReturn FullRegion ; on renvoie le région finale
EndIf
ProcedureReturn 0
EndProcedure
Procedure SkinColor(WindowID, ImageID, color = 0)
CallFunction(#User, "SetWindowRgn", WindowID, RegionColor(ImageId, color), #True)
EndProcedure
If OpenWindow(0, 0, 0, 300, 300, "Skin", #PB_Window_BorderLess | #PB_Window_ScreenCentered) = 0 Or CreateGadgetList(WindowID(0)) = 0
End
EndIf
; La fenêtre doit obligatoirement être avec le style #PB_Window_BorderLess
SetWindowColor(0, RGB(255, 0, 0))
; On crée une image qui va servir de skin (elle doit avoir la taille de la fenêtre)
CreateImage(0, 300, 300)
StartDrawing(ImageOutput(0))
; La couleur mauve $FF00FF ou RGB(255, 0, 255) représente la partie transparente de la fenêtre
Box(250, 0, 50, 30, $FF00FF)
Circle(200, 200, 50, $FF00FF)
Circle(250, 230, 50, $FF00FF)
Ellipse(50, 120, 40, 20, $FF00FF)
LineXY(50, 50, 250, 100, $FF00FF)
StopDrawing()
Temps = ElapsedMilliseconds()
; ExtCreateRegion : a voir
SkinColor(WindowID(0), ImageID(0), $FF00FF)
Temps = ElapsedMilliseconds() - Temps
; On place un bouton pour quitter
ButtonGadget(0, 0, 0, 100, 25, "Quitter")
; On affichage le temps nécesssaire pour créer le masque
TextGadget(#PB_Any, 0, 25, 100, 15, Str(Temps) + " ms")
Repeat
Event = WaitWindowEvent()
If Event = 513
OpenLibrary(0, "user32.dll")
CallFunction(0, "SendMessage", WindowID(0), 161, 2, 0)
EndIf
If Event = #PB_Event_Gadget
Select EventGadget() ; boutons, zone de texte, ...
Case 0 ; On quitte le programme
Event = #PB_Event_CloseWindow
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
End