PureBasic

Forums PureBasic
Nous sommes le Dim 26/Mai/2013 10:36

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 30 messages ]  Aller à la page 1, 2  Suivante
Auteur Message
 Sujet du message: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Jeu 10/Sep/2009 18:58 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Salut,

Je suis en train de refaire mon logiciel "PopupMenu Editeur" qui va s'appeler "Barre & Menu"

C'est une sorte de dock, un lanceur en gros.
Soit via une barre sur un bord de l'écran, soit via des menus qui s'ouvre un cliquant sur un raccourci.

Mon envie, c'est un skin qui supporte totalement le PNG.

Actuellement, je passe via un SetLayeredWindow_( pour rendre la couleur #FF00FF transparente.

Mais il n'y a pas de dégradé, cette méthode est basique, pixel affiché ou non, pas de gestion de la couche alpha.

Donc je penche sur ce code en C ici :
http://www.codeproject.com/KB/GDI-plus/ ... sharp.aspx
ou en VB ici : (c'est le même)
http://www.vbfrance.com/codes/FORM-GRAP ... 36788.aspx

C'est exactement ce que je recherche.

Visiblement, cela utilise la librairie GDI de crosoft

Si mon ami Denis peut me dire si ce genre de chose lui parle vu qu'il a beaucoup travailler sur GDI. Merci

Sinon, je vais essayer de traduire ce joli bazar mais le VB ou le C, pas trop ma tasse de thé.
Donc si des personnes sont intéressé par l'idée de fenêtre skinnable avec un PNG et support de la couche Alpha. Bienvenue.

Je compte essayer de faire une librairie pour PB en opensource.

Merci à tous ceux qui participeront :)

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Jeu 10/Sep/2009 19:17 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Donc, j'ai continué mes investigations.

J'ai trouvé la fonction qui m'intéresse, elle s'appelle UpdateLayeredWindow

et voici une code d'un code trouvé sur le forum anglais
vous ouvrez une image PNG puis vous déplacer l'image en cliquant dessus.
Code:
    Global SD_Window = -1
   
    Procedure StopDrag()
      ReleaseCapture_()
      If IsWindow(SD_Window)
        CloseWindow(SD_Window)
      EndIf
    EndProcedure
   
    Procedure DragCallback(WindowID, message, wParam, lParam)
      Protected Result = #PB_ProcessPureBasicEvents
      Select message
        Case #WM_MOUSEMOVE
          SetWindowPos_(WindowID, #HWND_TOPMOST, DesktopMouseX(), DesktopMouseY(), 0, 0, #SWP_NOSIZE)
        Case #WM_LBUTTONUP
          StopDrag()
        Case #WM_CHAR
          If wParam = #ESC
            StopDrag()
          EndIf
      EndSelect
      ProcedureReturn Result
    EndProcedure
   
    Procedure StartDrag(Image)
      Protected BitmapInfo.BITMAP
      Protected ContextOffset.POINT
      Protected BlendMode.BLENDFUNCTION
      Protected hdc
      If IsWindow(SD_Window)
        CloseWindow(SD_Window)
      EndIf
      SD_Window = OpenWindow(#PB_Any, DesktopMouseX(), DesktopMouseY(), 20, 20, "", #PB_Window_BorderLess, WindowID(GetActiveWindow()))
      SetWindowLong_(WindowID(SD_Window), #GWL_EXSTYLE, GetWindowLong_(WindowID(SD_Window), #GWL_EXSTYLE) | #WS_EX_LAYERED)
      hdc = StartDrawing(ImageOutput(Image))
        GetObject_(ImageID(Image), SizeOf(BITMAP), @BitmapInfo)
        BlendMode\SourceConstantAlpha = 255
        BlendMode\AlphaFormat = 1
        UpdateLayeredWindow_(WindowID(SD_Window), 0, 0, @BitmapInfo+4, hdc, @ContextOffset, 0, @BlendMode, 2)
      StopDrawing()
      SetCapture_(WindowID(SD_Window))
      SetWindowCallback(@DragCallback(), SD_Window)
    EndProcedure
   
    UsePNGImageDecoder()
    fichier.s = OpenFileRequester("", "", "PNG|*.png", 1)
    If fichier
    OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    CreateGadgetList(WindowID(0))
    LoadImage(0, fichier.s)
    ImageGadget(0, 10, 10, 0, 0, ImageID(0))
   
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Select EventType()
                Case 14002
                  StartDrag(0)
              EndSelect
          EndSelect
        Case #PB_Event_CloseWindow
          Break
      EndSelect
    ForEver
   
  EndIf


Donc ça avance :) je suis content, c'est bien plus simple que ce que je pensais

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Jeu 10/Sep/2009 21:21 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
La première version de la fonction qui va bien :)

Il faut que je fignole. Je veux passer l'image ID et pas l'identifiant PB à la procedure.

Donc petit travail sur CreateDC pour obtenir le HDC de l'image.

Code:
ProcedureDLL AlphaImageWindow(WindowID, Image, Alpha = 255)
  Protected Image_HDC, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
  SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED)
 
  Image_HDC = StartDrawing(ImageOutput(Image))
    GetObject_(ImageID(Image), SizeOf(BITMAP), @Image_BitmapInfo)
    Blend\SourceConstantAlpha = Alpha ; niveau de transparence
    Blend\AlphaFormat = 1 ; Support de la couche alpha
    UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
  StopDrawing()
 
EndProcedure



UsePNGImageDecoder()

Fichier.s = OpenFileRequester("Image", "", "PNG|*.png", 1)
If Fichier
  If LoadImage(0, Fichier)
   
    If OpenWindow(0, 0, 0, ImageWidth(0), ImageHeight(0), "Test", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
     
      AlphaImageWindow(WindowID(0), 0)
     
      StickyWindow(0, 1)
     
      Repeat
        Event = WaitWindowEvent()
       
      Until Event = #PB_Event_CloseWindow
     
    EndIf
   
  EndIf
EndIf

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Jeu 10/Sep/2009 21:57 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
et voilà, c'est bon ;)


le code de ma librairie

Code:
ProcedureDLL SetLayeredWindow(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
   SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure

ProcedureDLL SetLayeredWindowAttributes(WindowID.l, Alpha.l, Color.l) ; Transparence et forme de la fenêtre
  Protected Parametre.l
  If Alpha > 0
    Parametre | #LWA_ALPHA
  Else
    Alpha = 0
  EndIf
  If Color > 0
    Parametre | #LWA_COLORKEY
  Else
    Color = 0
  EndIf
  SetLayeredWindowAttributes_(WindowID, Color, Alpha, Parametre)
EndProcedure

ProcedureDLL SkinWindow(WindowID, ImageID) ; Mettre une forme sur une fenêtre a partir d'une image
  Protected bmi.BITMAPINFO, Region_Temp, Region_Totale, Largeur, Hauteur
 
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
 
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
 
  Region_Totale = CreateRectRgn_(0, 0, bm\bmWidth, bm\bmHeight)
 
  mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If mem
   
    hdc = CreateCompatibleDC_(GetDC_(ImageID))
    If hdc
      GetDIBits_(hdc, ImageID, 0, bm\bmHeight, mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
      DeleteDC_(hdc)
    EndIf
   
    ; On convertit la liste dans le bon format
    Largeur = bm\bmWidth - 1
    Hauteur = bm\bmHeight - 1
    Point = mem
    For y1 = 0 To Hauteur
      For x1 = 0 To Largeur
        If PeekL(Point) = $FF00FF
          x2 = x1
          While x2 < Largeur And PeekL(Point + 4) = $FF00FF
            x2 + 1
            Point + 4
          Wend
          Region_Temp = CreateRectRgn_(x1, Hauteur - y1, x2 + 1, Hauteur - y1 + 1) ; On retire le point de la region
          CombineRgn_(Region_Totale, Region_Totale, Region_Temp, #RGN_DIFF)
          DeleteObject_(Region_Temp)
          x1 = x2
        EndIf
        Point + 4
      Next
    Next
   
    FreeMemory(mem)
  EndIf
 
  SetWindowRgn_(WindowID, Region_Totale, 1) ; On applique la region
  DeleteObject_(Region_Totale) ; On efface la region
 
EndProcedure

ProcedureDLL SkinWindow2(WindowID, ImageID, Couleur) ; Mettre une forme sur une fenêtre a partir d'une image
  Protected bmi.BITMAPINFO, Region_Temp, Region_Totale, Largeur, Hauteur
 
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
 
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
 
  Region_Totale = CreateRectRgn_(0, 0, bm\bmWidth, bm\bmHeight)
 
  ; On inverse la couleur
  Couleur = ((Couleur & $0000FF) << 16) | (Couleur & $00FF00) | ((Couleur & $FF0000) >> 16)
 
  mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If mem
   
    hdc = CreateCompatibleDC_(GetDC_(ImageID))
    If hdc
      GetDIBits_(hdc, ImageID, 0, bm\bmHeight, mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
      DeleteDC_(hdc)
    EndIf
   
    ; On convertit la liste dans le bon format
    Largeur = bm\bmWidth - 1
    Hauteur = bm\bmHeight - 1
    Point = mem
    For y1 = 0 To Hauteur
      For x1 = 0 To Largeur
        If PeekL(Point) = Couleur
          x2 = x1
          While x2 < Largeur And PeekL(Point + 4) = Couleur
            x2 + 1
            Point + 4
          Wend
          Region_Temp = CreateRectRgn_(x1, Hauteur - y1, x2 + 1, Hauteur - y1 + 1) ; On retire le point de la region
          CombineRgn_(Region_Totale, Region_Totale, Region_Temp, #RGN_DIFF)
          DeleteObject_(Region_Temp)
          x1 = x2
        EndIf
        Point + 4
      Next
    Next
   
    FreeMemory(mem)
  EndIf
 
  SetWindowRgn_(WindowID, Region_Totale, 1) ; On applique la region
  DeleteObject_(Region_Totale) ; On efface la region
 
EndProcedure

ProcedureDLL AlphaImageWindow(WindowID, ImageID) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC, Image_Bitmap.BITMAP, ContextOffset.POINT, Blend.BLENDFUNCTION, Image
   
   ; Dimension de l'image
   GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
   
   Image = CreateImage(#PB_Any, Image_Bitmap\bmWidth, Image_Bitmap\bmHeight, 32)
   StartDrawing(ImageOutput(Image))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawAlphaImage(ImageID, 0, 0)
      DrawingMode(#PB_2DDrawing_AlphaChannel)
      DrawAlphaImage(ImageID, 0, 0)
   StopDrawing()
   
   ; Chargement du HDC
   Image_HDC = CreateCompatibleDC_(#NULL)
   Image_Ancienne = SelectObject_(Image_HDC, ImageID(Image))
   
   ; L'image est mise en skin de la fenêtre
   Blend\SourceConstantAlpha = 255 ; niveau de transparence
   Blend\AlphaFormat = 1 ; Support de la couche alpha
   Blend\BlendOp = 0
   Blend\BlendFlags = 0
   UpdateLayeredWindow_(WindowID, 0, 0, @Image_Bitmap + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
   
   ; Fermeture du HDC
   SelectObject_(Image_HDC, Image_Ancienne)
   DeleteDC_(Image_HDC)
   
   ; Supression de l'image
   FreeImage(Image)
   
EndProcedure

ProcedureDLL AlphaImageWindow2(WindowID, ImageID, Alpha) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC, Image_Bitmap.BITMAP, ContextOffset.POINT, Blend.BLENDFUNCTION, Image
   
   ; Dimension de l'image
   GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
   
   Image = CreateImage(#PB_Any, Image_Bitmap\bmWidth, Image_Bitmap\bmHeight, 32)
   StartDrawing(ImageOutput(Image))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawAlphaImage(ImageID, 0, 0)
      DrawingMode(#PB_2DDrawing_AlphaChannel)
      DrawAlphaImage(ImageID, 0, 0)
   StopDrawing()
   
   ; Chargement du HDC
   Image_HDC = CreateCompatibleDC_(#NULL)
   Image_Ancienne = SelectObject_(Image_HDC, ImageID(Image))
   
   ; L'image est mise en skin de la fenêtre
   Blend\SourceConstantAlpha = Alpha ; niveau de transparence
   Blend\AlphaFormat = 1 ; Support de la couche alpha
   Blend\BlendOp = 0
   Blend\BlendFlags = 0
   UpdateLayeredWindow_(WindowID, 0, 0, @Image_Bitmap + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
   
   ; Fermeture du HDC
   SelectObject_(Image_HDC, Image_Ancienne)
   DeleteDC_(Image_HDC)
   
   ; Supression de l'image
   FreeImage(Image)
   
EndProcedure


le code de l'exemple :
Code:
; PureBasic 4.40

UsePNGImageDecoder()

Fichier.s = OpenFileRequester("Image", "", "PNG|*.png", 1)
If Fichier
  If LoadImage(0, Fichier)

    If OpenWindow(0, 0, 0, ImageWidth(0), ImageHeight(0), "Test", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
     
         SetLayeredWindow(WindowID(0))
      AlphaImageWindow(WindowID(0), ImageID(0))
     
      StickyWindow(0, 1)
     
      Repeat
        Event = WaitWindowEvent()
       
      Until Event = #PB_Event_CloseWindow
     
    EndIf
   
  EndIf
EndIf


voici d'autres exemple pour cette lib
Code:
; Auteur : Le Soldat Inconnu
; Version de PB : 4
;
; Explication du programme :
; Pour doner une forme spéciale à une fenêtre



; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 300, 300, "Skin", #PB_Window_BorderLess | #PB_Window_ScreenCentered) = 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()

SkinWindow(WindowID(0), ImageID(0))

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 = #WM_LBUTTONDOWN
    SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 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


Code:
; Auteur : Le Soldat Inconnu
; Version de PB : 4
;
; Explication du programme :

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 300, 300, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget) = 0
  End
EndIf

; La couleur $FF00FF devient totalement transparente
; Donc si on dessine de la couleur $FF00FF sur la fenêtre, on fait des trous
; La valeur 200 est l'effet de transparence globale de la fenêtre, 0 donne invisible, et 255 complètement opaque
SetLayeredWindow(WindowID(0))
SetLayeredWindowAttributes(WindowID(0), 200, $FF00FF)

Repeat
  Event = WaitWindowEvent()
 
  Select Event
    Case #PB_Event_Menu
      Select EventMenu() ; Menus
         
      EndSelect
     
    Case #PB_Event_Gadget
      Select EventGadget() ; Gadgets
         
      EndSelect
     
    Case #WM_MOUSEMOVE
      StartDrawing(WindowOutput(0))
        Circle(WindowMouseX(0), WindowMouseY(0), 8, $FF00FF)
      StopDrawing()
  EndSelect
 
Until Event = #PB_Event_CloseWindow

End

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Ven 11/Sep/2009 7:19 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Edition : cette erreur est plus compliqué voir plus bas.

je corrige mon exemple des fenêtres avec support couche alpha.

Il y a une obligation pour les zones de l'image qui sont transparente à 100%
la couleur doit être noire sur ces zones.

Et photoshop n'a pas trop l'air motivé sur ce points, donc cette exemple corrige ce problème

il faut toujours les fonctions de la lib du message plus haut

Code:
Retiré

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Ven 11/Sep/2009 19:11 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 22/Jan/2004 14:31
Messages: 3311
Le Soldat Inconnu a écrit:
Visiblement, cela utilise la librairie GDI de crosoft

Si mon ami Denis peut me dire si ce genre de chose lui parle vu qu'il a beaucoup travailler sur GDI. Merci



Heu, j'ai pas regardé (c'est GDI+ car GDI existe mais est limité d'ou GDI+)

_________________
Documentation GDI + 1.0 PB 4.30 beta 4 et supérieur
PureIconManager


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Sam 12/Sep/2009 11:41 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
C'est pas grave, mon bon Denis, en fait, dans l'exemple en C, la lib GDI sert juste à ouvrir le format PNG
Merci :)


Sinon, j'ai fait des corrections dans mes exemples

Et je conseile PB4.40 pour le support de la couche Alpha, sinon, c'est le gros bazar

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Lun 14/Sep/2009 16:15 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Bon, je n'avais un bon rendu sur mes images, et j'ai trouvé le problème. Problème Microsoft bien entendu, qui ne sait pas faire de mélange entre 2 couleurs

A savoir microsoft travaille de cette manière pour mélangé 2 couleurs :
Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red
Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green
Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue

Ce qui est totalement faux, il faut faire comme cela
Dst.Red = Src.Red * Src.Alpha + (1 - Src.Alpha) * Dst.Red
Dst.Green = Src.Green * Src.Alpha + (1 - Src.Alpha) * Dst.Green
Dst.Blue = Src.Blue * Src.Alpha + (1 - Src.Alpha) * Dst.Blue

En gros, quand j'ajoute à une couleur une autre avec de la transparence à 70%, je me retrouve avec 30% de la couleur de base et 70% de la nouvelle couleur, et pas comme microsoft le fait en prenant 100% de la couleur de base + 70% de l'autre couleur (ce qui fait au passage 170% bravo)

Donc j'ai déjà trouvé la méthode, il faut que je fasse le calcul (Src.Red * Src.Alpha ; ...) directement sur mon image avant de l'envoyer comme skin.
Maintenant, je cherche à optimiser.

Donc tous mes exemples plus haut sont faux, attendez la mise à jour.

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Mar 15/Sep/2009 19:06 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Alors voilà, c'est au point.

J'ai remis à jour les codes plus haut.
Chez moi, le traitement de l'image pour palier les bizarrerie microsoft donne 32ms pour une image de 1024*1024. Donc très très rapide. Tant mieux

Donc il faut de préférence la version 4.40, pas essayé avec 4.30 mais je pense que cela doit fonctionner (mais c'est pas le top)

et pour finir, voici un aperçu de ce que cela peut donner
Image
La fenêtre, c'est le bouton vert. Donc grace au PNG et la couche alpha, contour net, ombre, etc ...

Si d'autres peuvent tester chez eux le bon fonctionnement, 2000, XP, Vista (si vous avez opté pour cet ... hum ...chose), 7

Merci

voici un code tout près
Code:
UsePNGImageDecoder()

Procedure SetLayeredWindow2(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
   SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure
Procedure AlphaImageWindow2(WindowID, ImageID, Alpha) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
   Protected xx, yy, x, y, Rouge, Vert, Bleu, AlphaChannel
   
   ; Précalcul
   Protected Dim Echelle.f($FF)
   For x = 0 To $FF
      Echelle(x) = x / $FF
   Next
   
   ; Chargement du HDC
   Image_HDC = CreateCompatibleDC_(#NULL)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
   
   ; Dimension de l'image
   GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
   Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
   Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
   Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
   Image_BitmapInfo\bmiHeader\biPlanes = 1
   Image_BitmapInfo\bmiHeader\biBitCount = 32
   
   ; Zone mémoire pour copier l'image
   xx = Image_Bitmap\bmWidth - 1
   yy = Image_Bitmap\bmHeight - 1
   Protected Dim Image.l(xx, yy)
   
   ; Copie de l'image en mémoire
   GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
   ; Modification de l'image en mémoire
   For x = 0 To xx
      For y = 0 To yy
         Couleur = Image(x, y)
         AlphaChannel = Couleur >> 24 & $FF
         If AlphaChannel < $FF
            Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
            Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
            Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
            Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
         EndIf
      Next
   Next
   
   ; Transfert de la mémoire dans la l'image de base
   SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   
   ; L'image est mise en skin de la fenêtre
   Blend\SourceConstantAlpha = Alpha ; niveau de transparence
   Blend\AlphaFormat = 1 ; Support de la couche alpha
   Blend\BlendOp = 0
   Blend\BlendFlags = 0
   UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
   
   ; Fermeture du HDC
   SelectObject_(Image_HDC, Image_Ancienne)
   DeleteDC_(Image_HDC)
 
EndProcedure

Fichier.s = OpenFileRequester("Image", "", "PNG|*.png", 1)
If Fichier
  If LoadImage(0, Fichier)
      
      If OpenWindow(0, 0, 0, ImageWidth(0), ImageHeight(0), "Test", #PB_Window_BorderLess | #PB_Window_ScreenCentered | #PB_Window_Invisible)
         
         SetLayeredWindow2(WindowID(0))
         AlphaImageWindow2(WindowID(0), ImageID(0), 200)
         
         StickyWindow(0, 1)
         HideWindow(0, 0)
         
         Repeat
            Event = WaitWindowEvent()
            
            If Event = #WM_LBUTTONDOWN
               SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
            EndIf
            
         Until Event = #PB_Event_CloseWindow
         
      EndIf
      
   EndIf
EndIf

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Mar 15/Sep/2009 19:36 
Hors ligne
Avatar de l’utilisateur

Inscription: Mar 06/Avr/2004 10:35
Messages: 1493
Voici deux screens sous ce que tu appelles hum... chose là... Vista je crois
Exemple utilisé le n°1 with PB 4.40
Image
Le second de la même fenêtre, avec fond différent.
Image
Le 2 et le 3 fonctionnent bien aussi, mais le 4 craint. Je ne vois rien et on ne peut fermer qu'en stoppant dans PB
je teste le dernier...
voilà
Image
Ca fonctionne. Manque le bouton pour quitter car le systèm menu n'apparaît sur aucune.

_________________
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.


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Jeu 01/Oct/2009 18:39 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 29/Juil/2004 16:33
Messages: 2120
Localisation: . <------ ici
c'est mega bon sa :P
je vais regarder de plus pres merci du code





@++

_________________
Windows 8 x64, processeur core i7 2.93ghz, mémoire ram 10Go, 2x ati radeon hd 5750 1Go chacune
PureBasic 5.11 x86 & x64 DirectX 11


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Sam 03/Oct/2009 19:32 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Voici un code qui mets en évidence le problème que j'ai rencontré sur la gestion de la couche Alpha avec UpdateLayeredWindow_(

Fenêtre à gauche sans la correction, et celle de droite avec la correction.

voici l'image originale
Image

Code:
; PureBasic 4.40

UsePNGImageDecoder()

Procedure SetLayeredWindow2(WindowID) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
   SetWindowLong_(WindowID, #GWL_EXSTYLE, GetWindowLong_(WindowID, #GWL_EXSTYLE) | #WS_EX_LAYERED) ; Mettre l'attribut WS_EX_LAYERED à la fenêtre
EndProcedure
Procedure AlphaImageWindow2(WindowID, ImageID, Calcul.l) ; Mettre une image PNG comme fond d'une fenêtre
  Protected Image_HDC, Image_Bitmap.BITMAP, Image_BitmapInfo.BITMAPINFO, ContextOffset.POINT, Blend.BLENDFUNCTION
   Protected xx, yy, x, y, Rouge, Vert, Bleu, AlphaChannel
   
   ; Précalcul
   Protected Dim Echelle.f($FF)
   For x = 0 To $FF
      Echelle(x) = x / $FF
   Next
   
   ; Chargement du HDC
   Image_HDC = CreateCompatibleDC_(#NULL)
  Image_Ancienne = SelectObject_(Image_HDC, ImageID)
   
   
   ; Dimension de l'image
   GetObject_(ImageID, SizeOf(BITMAP), @Image_Bitmap)
   Image_BitmapInfo\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
   Image_BitmapInfo\bmiHeader\biWidth = Image_Bitmap\bmWidth
   Image_BitmapInfo\bmiHeader\biHeight = Image_Bitmap\bmHeight
   Image_BitmapInfo\bmiHeader\biPlanes = 1
   Image_BitmapInfo\bmiHeader\biBitCount = 32
   
   If Calcul
      ; Zone mémoire pour copier l'image
      xx = Image_Bitmap\bmWidth - 1
      yy = Image_Bitmap\bmHeight - 1
      Protected Dim Image.l(xx, yy)
      
      ; Copie de l'image en mémoire
      GetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
      
      ; Modification de l'image en mémoire
      For x = 0 To xx
         For y = 0 To yy
            Couleur = Image(x, y)
            AlphaChannel = Couleur >> 24 & $FF
            If AlphaChannel < $FF
               Rouge = (Couleur & $FF) * Echelle(AlphaChannel)
               Vert = (Couleur >> 8 & $FF) * Echelle(AlphaChannel)
               Bleu = (Couleur >> 16 & $FF) * Echelle(AlphaChannel)
               Image(x, y) = Rouge | Vert << 8 | Bleu << 16 | AlphaChannel << 24
            EndIf
         Next
      Next
      
      ; Transfert de la mémoire dans la l'image de base
      SetDIBits_(Image_HDC, ImageID, 0, Image_Bitmap\bmHeight, @Image(), @Image_BitmapInfo, #DIB_RGB_COLORS)
   EndIf
   
   ; L'image est mise en skin de la fenêtre
   Blend\SourceConstantAlpha = 255 ; niveau de transparence
   Blend\AlphaFormat = 1 ; Support de la couche alpha
   Blend\BlendOp = 0
   Blend\BlendFlags = 0
   UpdateLayeredWindow_(WindowID, 0, 0, @Image_BitmapInfo + 4, Image_HDC, @ContextOffset, 0, @Blend, 2)
   
   ; Fermeture du HDC
   SelectObject_(Image_HDC, Image_Ancienne)
   DeleteDC_(Image_HDC)
 
EndProcedure

If CatchImage(0, ?Image)
   
   If OpenWindow(0, 100, 100, ImageWidth(0), ImageHeight(0), "Test 1", #PB_Window_BorderLess)
      
      SetLayeredWindow2(WindowID(0))
      AlphaImageWindow2(WindowID(0), ImageID(0), 0)
      
      StickyWindow(0, 1)
      
   EndIf
   If OpenWindow(1, 300, 100, ImageWidth(0), ImageHeight(0), "Test 2", #PB_Window_BorderLess)
      
      SetLayeredWindow2(WindowID(1))
      AlphaImageWindow2(WindowID(1), ImageID(0), 1)
      
      StickyWindow(1, 1)
      
   EndIf
   
   Repeat
      Event = WaitWindowEvent()
      
      If Event = #WM_LBUTTONDOWN
         SendMessage_(WindowID(EventWindow()), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
      EndIf
      
   Until Event = #PB_Event_CloseWindow
   
EndIf
   
DataSection
   image:
   Data.l $474E5089,$0A1A0A0D,$0D000000,$52444849,$80000000,$80000000,$00000608,$613EC300,$000000CB,$4D416704,$AF000041,$8A0537C8
   Data.l $000000E9,$58457419,$666F5374,$72617774,$64410065,$2065626F,$67616D49,$61655265,$C9717964,$00003C65,$4449EA02,$DA785441
   Data.l $72599BEC,$451440DA,$98035A9F,$F34BD198,$EC8AB22E,$180A3B2C,$4D6EAC1B,$313B02B9,$2A299258,$A9CE543F,$5BBB75BA,$80E24943
   Data.l $611A88BE,$7BA9E766,$F75D43E6,$3549AFCC,$0F1AEF30,$D7D57DAD,$35E9731C,$D72F757C,$0F99EFA6,$EB67E775,$106BFE0C,$01000100
   Data.l $01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100,$01000100
   Data.l $01000100,$56E00100,$77E7EC48,$459C7455,$DB71DFD1,$E3EFE71F,$E7D16B3F,$45B64BB5,$C9FAF3EE,$C63B3B9A,$B9D3EFF5,$D79C75DD
   Data.l $E3BB9D9D,$7BEED79C,$FB57CC72,$C763DD75,$0CF4F8F3,$35DEE82E,$276EDB3B,$E005F8DB,$00080015,$00080008,$00080008,$00080008
   Data.l $00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$47FB4137
   Data.l $14511FF1,$E738C7D9,$FD43E73A,$35F9F39E,$77B8E389,$5A1E35DE,$D5FFB4BB,$AEE34331,$7BE935F9,$FBDD43E6,$E01DF2D9,$00080015
   Data.l $00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008
   Data.l $00080008,$00080008,$3CD440B7,$6B95363E,$FBD7197C,$EA766E32,$9FA922E7,$21D6A98E,$10EA95AD,$E87676DF,$ADCACF8D,$2F36AACF
   Data.l $B5EE5679,$0AACF3E6,$A6D4AF5A,$699D44F5,$A89EAC7D,$67AD3EA7,$E97AB9EA,$62426393,$5621566D,$CE08B6C7,$59B385E6,$197DD911
   Data.l $1B34A4D9,$B9A33A29,$D58D71A6,$AB04A971,$D2AB5792,$B3E9959D,$DB22B5B2,$A30B6B28,$997F8CB7,$F2DAF43F,$DDFCC6F1,$AB78FCD6
   Data.l $BBF2CEF1,$4BABDABD,$29D8D6A5,$F563C6A9,$3E5A9944,$3A17AB9A,$6CF2D2C7,$4DD07EA5,$3548583D,$B4BA4256,$885B9922,$DFC45667
   Data.l $2B1374AC,$74494CA3,$535B1695,$8914D625,$4FB2B9D5,$56A5DAAD,$CCDB2B3E,$6CB7A78A,$656B0B32,$CC8F5233,$B293FDAB,$96465E55
   Data.l $725579B7,$5750585D,$AB1C698A,$4CAC6553,$AA657B94,$6DF333CC,$D97E3A96,$B0E87A76,$522C2D4A,$1589162B,$589A6533,$F84CAF79
   Data.l $0015E005,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008,$00080008
   Data.l $00080008,$00080008,$00080008,$C1370008,$0006016F,$7D698A9A,$EDA484F5,$00000000,$444E4549,$826042AE
EndDataSection ;}


_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Lun 05/Oct/2009 17:55 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
Mise à jour du code de la LIB pour une simplification du code.

Merci à Olivier pour l'astuce

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Mar 06/Oct/2009 18:14 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 09/Oct/2005 16:51
Messages: 5229
Merci pour ce travail sur le skinage. J'aimerai tester ta lib pour me faire une fenêtre "A Propos" personnalisée avec l'image suivante mais je ne pige pas vraiment comment m'y prendre. Ai-je bon en ayant créer l'image de la sorte ?

image about.png
Image

image alpha about_a.png
Image

Ou suis je à coté de la plaque ?

_________________
.: Ar-S :. - Windows 8 x64 - Radeon HD 7870 - PB 5.11
LDV MULTIMEDIA : Assistance informatique Isère (38) Oyeu
PURE BASIC forum non officiel : Forum PB


Haut
 Profil  
 
 Sujet du message: Re: Fenêtre avec skin au format PNG (support alpha)
MessagePosté: Mar 06/Oct/2009 20:09 
Hors ligne
Avatar de l’utilisateur

Inscription: Mer 28/Jan/2004 20:58
Messages: 4311
Localisation: Clermont ferrand OU Olsztyn
totalement à coté de la plaque :), du moins pour skinner une fenêtre avec un PNG

Fais une seule image avec couche alpha (donc fond transparent au lieu de mauve)

Et après, tu dois dessiner ton texte sur l'image (malheureusement, pas de gadget possible dans cet astuce)
Et gérer les clics en fonction de la position des éléments.

L'autre solution est de rajouter une autre fenêtre contenant la zone de texte par dessus la fenêtre skinner.

Je vais te faire un exemple :) (mais la je vais faire la soupe, patiente un poil)

_________________
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]


Haut
 Profil  
 
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 30 messages ]  Aller à la page 1, 2  Suivante

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye