Fenetre d'un format spécial avec alphablending?

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Fenetre d'un format spécial avec alphablending?

Message par poshu »

Alors que je mettais à jour iBar, je me suis retrouvé face à un petit problème:
iBar utilise un système de skin qui permet d'utiliser des fenêtres d'une forme "spéciale".
Image
Jusque là, tout va bien, je me suis codé une petite fonction toute bête et très simple qui rempli son office (la voilà, si elle peut servir à quelqu'un, tant mieux ^^):

Code : Tout sélectionner

Procedure SkinWindow(Window,Skin,Transparent_Color = #Magenta)
  Region = CreateRectRgn_(0, 0, WindowWidth(Window) + 1, WindowHeight(Window) + 1)
  StartDrawing( ImageOutput (Skin))
    For x1 = 0 To WindowWidth(Window)-1
      For y1 = 0 To WindowHeight(Window)-1
        If Point(x1, y1) = Transparent_Color
          y2 = y1
          While x2 < WindowWidth(Window) And Point(x1, y2 + 1) = Transparent_Color
            y2 + 1
          Wend
          Region_Temp = CreateRectRgn_(x1, y1, x1 + 1, y2 + 1)
          CombineRgn_ (Region, Region, Region_Temp, #RGN_DIFF )
          y1 = y2
        EndIf
      Next
    Next
  StopDrawing()
  SetWindowRgn_(WindowID(Window), Region, #True )
  brush=CreatePatternBrush_(ImageID(Skin))
  SetClassLong_(WindowID(Window),#GCL_HBRBACKGROUND,brush)
  InvalidateRect_(WindowID(Window),0,1)
  CreateGadgetList(WindowID(Window))
EndProcedure

; Exemple (lancer avec le débuger: on ne peut pas fermer la fenêtre, je suis un flemmard)
If LoadImage(0,OpenFileRequester("Selection du skin","","Bitmap|*.bmp",0))
  OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"Fenêtre skinée",#PB_Window_ScreenCentered|#PB_Window_BorderLess)
  SkinWindow(0,0)
Repeat

Until WaitWindowEvent() = #PB_Event_CloseWindow
FreeImage(0)
EndIf
Comme vous pouvez le voir, c'est vraiment simpliste jusque là, mais pour pousser le principe un peu plus loin, j'aimerais utiliser l'alphablending, et là je panne:
Comment faire pour afficher une window skinnée prenant compte de l'alpha blending? Est-ce au moins possible?
Dernière modification par poshu le ven. 22/août/2008 8:24, modifié 1 fois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

C'est cool ! maintenant ça prouve que tu es plus doué que moi ! Vu que tu sais utilisé les API et que moi non a part Beep_() :lol:
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Tu peux utiliser Gdi+ pour la transparence mais fonctionnera pas sur les OS ou GDI+ n'est pas installé.

Tu peux utiliser l'API alphablend, j'ai donné un exemple ici

http://www.purebasic.fr/french/viewtopic.php?t=5512

Il y a aussi la commande PB DrawAlphaImage()

A+
Denis
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Denis > J'avais très peur de devoir en venir à GDI+. J'ai installé ton pack (très beau boulot d'ailleurs) hier, et j'ai beaucoup de mal à assimiler autant d'information d'un coup.
Au moins, ça confirme que c'est possible, merci beaucoup

Typhoon > Et tu sais faire des choses qui m'échappent on a tous nos points faibles. Mais globalement, c'est moi qui pose le plus souvent des questions stupides sur le forum... Et si on arrêtait la gueguerre "c'est toi le meilleur" maintenant?
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

poshu a écrit : Typhoon > Et tu sais faire des choses qui m'échappent on a tous nos points faibles. Mais globalement, c'est moi qui pose le plus souvent des questions stupides sur le forum... Et si on arrêtait la gueguerre "c'est toi le meilleur" maintenant?
lollll tu as tout a fait raison, c'était juste un petit clein d'oeil a note dernière conversation. :P il est vrai que ce forum possède de véritable talent. ça pourrait être amusant de tous les réunirs pour un petit projet un jour (chaqu'un ayant des occupation diverse ça ne marcherait pas pour un grand projet...). On pourait sans doute faire quelques choses de terrible !! :roll:
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

poshu a écrit :Denis > J'avais très peur de devoir en venir à GDI+. J'ai installé ton pack (très beau boulot d'ailleurs) hier, et j'ai beaucoup de mal à assimiler autant d'information d'un coup.
Au moins, ça confirme que c'est possible, merci beaucoup
J'ai mis plus de 8 mois d'un travail de fou avec des hauts et des bas, alors je sais bien que l'on assimile pas ça d'un coup. Ce qui est intéressant c'est de savoir ce que l'on peut faire, pas de connaître les 600 fonctions; de mémoire il y a des fonctions de mélange de couleurs.

Je pense que l'API Alphablend correspond à ton besoin. Cherche sur le forum, tu trouveras une formule sans API pour créer une image avec transparence (à l'affichage) à partir d'une image.

A+
Denis
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Je suis en train de bidouiller sec dans le code là (et j'ai les mains pleines de cambouis), mais j'ai pas l'impression de pouvoir faire ce que je veux avec l'api >.<

J'vais commencer à regarder du coté de GDI (noooooon!)
Avatar de l’utilisateur
Jacobus
Messages : 1559
Inscription : mar. 06/avr./2004 10:35
Contact :

Message par Jacobus »

Avec un peu de transparence... (j'ai ajouté le bouton "Fermer") flemmard! :lol:

Code : Tout sélectionner

Procedure SkinWindow(Window,Skin,Transparent_Color = #Magenta) 
  Region = CreateRectRgn_(0, 0, WindowWidth(Window) + 1, WindowHeight(Window) + 1) 
  StartDrawing( ImageOutput (Skin)) 
    For x1 = 0 To WindowWidth(Window) 
      For y1 = 0 To WindowHeight(Window) 
        If Point(x1, y1) = Transparent_Color 
          y2 = y1 
          While x2 < WindowWidth(Window) And Point(x1, y2 + 1) = Transparent_Color 
            y2 + 1 
          Wend 
          Region_Temp = CreateRectRgn_(x1, y1, x1 + 1, y2 + 1) 
          CombineRgn_ (Region, Region, Region_Temp, #RGN_DIFF ) 
          y1 = y2 
        EndIf 
      Next 
    Next 
  StopDrawing() 
  SetWindowRgn_(WindowID(Window), Region, #True ) 
  brush=CreatePatternBrush_(ImageID(Skin)) 
  SetClassLong_(WindowID(Window),#GCL_HBRBACKGROUND,brush) 
  InvalidateRect_(WindowID(Window),0,1) 
  CreateGadgetList(WindowID(Window)) 
EndProcedure 
; Le niveau de transparence doit être compris entre 1 (transparence totale) et 255 (opaque) 
Procedure SetWinTransparency(WinHandle.l, Transparency_Level.l) 
     SetWindowLong_ (WinHandle, #GWL_EXSTYLE , GetWindowLong_ (WinHandle, #GWL_EXSTYLE ) | $00080000) ; #WS_EX_LAYERED = $00080000 
     If OpenLibrary (0, "user32.dll" ) 
         CallFunction (0, "SetLayeredWindowAttributes" , WinHandle, 0, Transparency_Level, 2) 
         CloseLibrary (0) 
     EndIf 
EndProcedure 
Global Hwnd
; Exemple (lancer avec le débuger: on ne peut pas fermer la fenêtre, je suis un flemmard) 
If LoadImage(0,OpenFileRequester("Selection du skin","","Bitmap|*.bmp",0)) 
  Hwnd = OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"Fenêtre skinée",#PB_Window_ScreenCentered|#PB_Window_BorderLess) 
  SkinWindow(0,0) 
  ButtonGadget(1,WindowWidth(0)-100,WindowHeight(0)-30,80,20,"Fermer")
  SetWinTransparency(Hwnd, 100)
Repeat 
  Select WaitWindowEvent() 
    Case #PB_Event_Gadget  
      Select EventGadget()
        Case 1 
         quitter = 1 
      EndSelect
   EndSelect   
Until quitter = 1
FreeImage(0) 
EndIf 
End 
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Ca, je savais le faire (c'est déjà dans la V0.4 d'iBar), mon problème est d'utiliser une transparence différente pour chaque pixel de la fenêtre, et c'est vachement plus dur (ou j'ai juste rien compris, et dans ce cas, j'en suis désolé.)
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Voici les explications de Microsoft (en anglais) sur la couche alpha avec les formules.

http://msdn2.microsoft.com/en-us/librar ... S.85).aspx

Essaye cette procedure qui retourne la couleur mélangée, il te suffit de l'appeler pour chaque point de ton image.

Alpha doit être compris en 0 et 255, 0 c'est complètement transparent, donc c'est le fond qui s'affiche et 255 c'est totalement opaque donc c'est la couleur source qui s'affiche.

Code : Tout sélectionner

Procedure.l GetAlphaBlendedColor(CouleurSource.l, CouleurFond.l, Alpha.l)
     ProcedureReturn RGB((((Red(CouleurSource) * Alpha / 255) + ((Red(CouleurFond) * (255 - Alpha))) / 255)), (((Green(CouleurSource) * Alpha / 255) + ((Green(CouleurFond) * (255 - Alpha))) / 255)), (((Blue(CouleurSource) * Alpha / 255) + ((Blue(CouleurFond) * (255 - Alpha))) / 255)))
EndProcedure
A+
Denis
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Nico avait pondu ça :)

Code : Tout sélectionner

Procedure AlphaBlend(Image1,Image2); transparence d'image
; Nico      
      Structure _LTI_BITMAPINFO
            bmiHeader.BITMAPINFOHEADER
            bmiColors.RGBQUAD[1]
      EndStructure
      
      Structure BGRA
            Blue.b
            Green.b
            Red.b
            Alpha.b
      EndStructure
      
      Structure BGRAL
            Blue.l
            Green.l
            Red.l
            Alpha.l
      EndStructure
      
      hDC1  = StartDrawing(ImageOutput(Image1))
            hDC2=CreateCompatibleDC_(hDC1)
            SelectObject_(hDC2,ImageID(Image2))
            
            If hDC1 And hDC2
                  ImageWidth  = ImageWidth(Image1) : ImageHeight = ImageHeight(Image1)
                  mem1 = GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,ImageWidth*ImageHeight*4)
                  mem2 = GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,ImageWidth*ImageHeight*4)
                  If mem1>0 And mem2>0
                        bmi._LTI_BITMAPINFO
                        bmi\bmiHeader\biSize   = SizeOf(BITMAPINFOHEADER)
                        bmi\bmiHeader\biWidth  = ImageWidth
                        bmi\bmiHeader\biHeight = ImageHeight
                        bmi\bmiHeader\biPlanes = 1
                        bmi\bmiHeader\biBitCount = 32
                        bmi\bmiHeader\biCompression = #BI_RGB
                        
                        GetDIBits_(hDC1,ImageID(Image1),0,ImageHeight,mem1,bmi,#DIB_RGB_COLORS)
                        GetDIBits_(hDC2, ImageID(Image2), 0, ImageHeight, mem2, bmi, #DIB_RGB_COLORS)
                        
                        *color1.BGRA = mem1
                        *color2.BGRA = mem2
                        
                        color1Long.BGRAL
                        color2Long.BGRAL
                        
                        color1Long\Blue =  *color1\Blue & $FF
                        color1Long\Green = *color1\Green & $FF
                        color1Long\Red =   *color1\Red & $FF
                        color1Long\Alpha =   *color1\Alpha & $FF
                        
                        color2Long\Blue =  *color2\Blue & $FF
                        color2Long\Green = *color2\Green & $FF
                        color2Long\Red =   *color2\Red & $FF
                        color2Long\Alpha = *color2\Alpha & $FF
                        
                        For a = 0 To (ImageWidth*ImageHeight)-1
                              ColorBlue.b =  color1Long\Blue * color1Long\Alpha / 255 + color2Long\Blue * (255 - color1Long\Alpha) / 255
                              ColorGreen.b = color1Long\Green * color1Long\Alpha / 255 + color2Long\Green * (255 - color1Long\Alpha) / 255   
                              ColorRed.b =   color1Long\Red * color1Long\Alpha / 255 + color2Long\Red * (255 - color1Long\Alpha) / 255
                              
                              *color1\Blue  = ColorBlue
                              *color1\Green = ColorGreen
                              *color1\Red  = ColorRed
                              
                              *color1 + 4
                              *color2 + 4
                              
                              color1Long\Blue =  *color1\Blue & $FF
                              color1Long\Green = *color1\Green & $FF
                              color1Long\Red =   *color1\Red & $FF
                              color1Long\Alpha =   *color1\Alpha & $FF
                              
                              color2Long\Blue =  *color2\Blue & $FF
                              color2Long\Green = *color2\Green & $FF
                              color2Long\Red =   *color2\Red & $FF
                              color2Long\Alpha = *color2\Alpha & $FF
                        Next a
                        
                        If SetDIBits_(hdcdest, ImageID(1),0,ImageHeight,mem,bmi,#DIB_RGB_COLORS) <> 0
                              Result = ImageID(1)
                        EndIf
                        
                  EndIf
                  
                  If mem1         
                        GlobalFree_(mem1)         
                  EndIf
                  If mem1
                        GlobalFree_(mem2)         
                  EndIf
            EndIf
            
      StopDrawing()
      DeleteDC_(hDC2)
      
      ProcedureReturn Result
EndProcedure
Répondre