Page 1 sur 1

Fenetre d'un format spécial avec alphablending?

Publié : dim. 10/août/2008 15:50
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?

Publié : dim. 10/août/2008 17:20
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:

Publié : dim. 10/août/2008 17:57
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

Publié : dim. 10/août/2008 18:07
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?

Publié : dim. 10/août/2008 18:17
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:

Publié : dim. 10/août/2008 18:33
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

Publié : dim. 10/août/2008 19:05
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!)

Publié : dim. 10/août/2008 20:09
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 

Publié : dim. 10/août/2008 21:17
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é.)

Publié : lun. 11/août/2008 8:17
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

Publié : lun. 11/août/2008 13:36
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