Page 1 sur 2

Fenêtre avec une forme bizarre basée sur une image

Publié : ven. 02/juin/2006 17:58
par Le Soldat Inconnu
Salut,

Un petit code pour donner n'importe quel forme à une fenêtre

On dessine une image de la taille de la fenêtre avec en mauve les zones qui seront transparentes.
cette image sera appliqué a la fenêtre.

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 3.9
;
; Explication du programme :
; Pour dessiner une fenêtre avec une forme dépendant d'une image


Procedure SkinWin(Window, Image)
  Protected x, y, Region_Temp, Region_Totale, Largeur, Hauteur
  ; On applique le skin à la fenêtre
  Largeur = ImageWidth(Image) - 1
  Hauteur = ImageHeight(Image) - 1
  Region_Totale = CreateRectRgn_(0, 0, Largeur + 1, Hauteur + 1) ; on crée une region de la taille de la fenêtre
  StartDrawing(ImageOutput(Image))
    For X1 = 0 To Largeur
      For Y1 = 0 To Hauteur
        If Point(X1, Y1) = $FF00FF
          Y2 = Y1
          While X2 < Largeur And Point(X1, Y2 + 1) = $FF00FF
            Y2 + 1
          Wend
          Region_Temp = CreateRectRgn_(X1, Y1, X1 + 1, Y2 + 1) ; On retire le point de la region
          CombineRgn_(Region_Totale, Region_Totale, Region_Temp, #RGN_DIFF)
          DeleteObject_(Region_Temp)
          Y1 = Y2
        EndIf
      Next
    Next
  StopDrawing()
  
  SetWindowRgn_(WindowID(Window), Region_Totale, 1) ; On applique la region
  DeleteObject_(Region_Totale) ; On efface la region
EndProcedure


; 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 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

SkinWin(0, 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
J'ai une version plus rapide mais elle utilise mes libs, et j'ai pas encore eu le temps de les remettre sur mon site depuis la V4
Donc patience :)

Publié : ven. 02/juin/2006 19:19
par wolfjeremy
Super interressant :D merci !

Publié : ven. 02/juin/2006 19:27
par AWEAR
Je viens juste de faire la même chose, en reprenant un code de Danilo fait en C pour PBOSL.

Le tien est quand même mieux, il n'y a pas à dire (plus court et un poil plus rapide).

Code : Tout sélectionner

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 

Publié : ven. 02/juin/2006 20:25
par nico
Le code de Danilo crée un skin à partir d'une image, donc forcément il est mieux adapté!

Publié : ven. 02/juin/2006 21:47
par Backup
nico a écrit :Le code de Danilo crée un skin à partir d'une image, donc forcément il est mieux adapté!
le code du Soldat aussi ! :D

Merci , excellent ces codes ! :D

Publié : ven. 02/juin/2006 23:36
par AWEAR
nico a écrit :Le code de Danilo crée un skin à partir d'une image, donc forcément il est mieux adapté!
J'avoue que je ne comprends pas bien ce que tu as voulu dire, car les deux codes utilisent une image.
C'est peut-être parce que le code entier de Danilo mettait l'image en background en plus, mais ca j'ai eu une grosse flemme de le faire, car il avait fait quelque chose d'assez complexe, alors qu'à mon avis un imagegadget suffit emplement...

Publié : sam. 03/juin/2006 9:25
par Le Soldat Inconnu
Dès que j'aurais remis mes libs en ligne, en l'utilisant, le temps pour créer le skin est divisé par 4 (sur mon exemple), et la, ca devient super intéressant. J'espère la semaine prochaine, je serais en vacance.

Publié : sam. 03/juin/2006 9:33
par bernard13
pourrais pas faire un tuto

svp

Publié : sam. 03/juin/2006 13:11
par AWEAR
Le Soldat Inconnu a écrit :Dès que j'aurais remis mes libs en ligne, en l'utilisant, le temps pour créer le skin est divisé par 4 (sur mon exemple), et la, ca devient super intéressant. J'espère la semaine prochaine, je serais en vacance.
Alors là je suis impatient de voir ça, ca promet d'être interessant !

Sinon Bernard13, tu demandes un tuto, mais tu ne précise sur quoi.. Le code du Soldat Inconnu est très simple et en plus il est commenté. Je ne vois où peut-être ton problème avec ce code, mais as-tu au moins fait l'effort de le regarder et de le comprendre, ou as-tu préféré la simplicité de demander un "tuto", en espérant que quelqu'un te mâcherais encore plus le travail ?

Publié : sam. 03/juin/2006 13:44
par wolfjeremy
bernard13 ne doit pas etre français car il ne sais pas bien s'exprimer, peut etre sait il tout simplement mal exprimé :wink: Si c'est pas sa ben c'est de la fénéantise lol

Publié : sam. 03/juin/2006 15:55
par bernard13
je cherche un tuto pour savoir
comment faire une fenetre qui utilise les apis + un skin

Publié : dim. 04/juin/2006 11:38
par Le Soldat Inconnu
j'ai fais une librairie avec la fonction ci dessus optimisée

voir ici :
http://lsi.celeonet.fr/index.php?mod=ar ... ires&id=81

Publié : dim. 04/juin/2006 13:30
par AWEAR
Woaw ! Ca c'est de l'efficacité !!!! Vraiment génial, bon boulot.

Les sources seront-elles disponnibles, car je serais très interessé de les voir..
comment faire une fenetre qui utilise les apis
Alors là je ne comprend même pas la question..
+ un skin
Vraiment t'abuses, il y a deux postes juste au dessus, commentés, avec deux méthodes assez semblables, le mien (pas génial certes, surtout niveau commentaire), et celui de LSI (clair et simple à comprendre).

Je te repose donc la question :
As-tu cherché à comprendre ces codes, et les as-tu même lu ?

Quel est l'intêret de faire de la programation si c'est uniquement pour que l'on te fasse tout à ta place, pour que l'on te mache le travail, et que toi au final tu fasse juste un copié/collé et que tu dises "hé ! regardez ce que j'ai réussi à faire".
Essaye de faire les chose par toi-même un peu..

Publié : dim. 04/juin/2006 14:07
par wolfjeremy
+1... :?

Je comprend pas trop bernard13...

Publié : lun. 05/juin/2006 8:36
par Le Soldat Inconnu
Les sources seront-elles disponnibles, car je serais très interessé de les voir..
La je suis en vacance jusqu'a jeudi, donc pas avant vendredi je pense.
Je mettrais la source en ligne.