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

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

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

Message 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 :)
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)]
wolfjeremy
Messages : 1202
Inscription : sam. 31/déc./2005 23:52

Message par wolfjeremy »

Super interressant :D merci !
AWEAR
Messages : 264
Inscription : ven. 28/oct./2005 8:20
Localisation : Mayotte ( 976 ), Océan Indien, France

Message 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 
La vie est une rose dont il faut accepter les épines, mais la mienne est fannée, arrosée par le goût de mes larmes. (Soprano)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Le code de Danilo crée un skin à partir d'une image, donc forcément il est mieux adapté!
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message 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
AWEAR
Messages : 264
Inscription : ven. 28/oct./2005 8:20
Localisation : Mayotte ( 976 ), Océan Indien, France

Message 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...
La vie est une rose dont il faut accepter les épines, mais la mienne est fannée, arrosée par le goût de mes larmes. (Soprano)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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.
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)]
bernard13
Messages : 1221
Inscription : mer. 05/janv./2005 21:30

Message par bernard13 »

pourrais pas faire un tuto

svp
AWEAR
Messages : 264
Inscription : ven. 28/oct./2005 8:20
Localisation : Mayotte ( 976 ), Océan Indien, France

Message 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 ?
La vie est une rose dont il faut accepter les épines, mais la mienne est fannée, arrosée par le goût de mes larmes. (Soprano)
wolfjeremy
Messages : 1202
Inscription : sam. 31/déc./2005 23:52

Message 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
bernard13
Messages : 1221
Inscription : mer. 05/janv./2005 21:30

Message par bernard13 »

je cherche un tuto pour savoir
comment faire une fenetre qui utilise les apis + un skin
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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
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)]
AWEAR
Messages : 264
Inscription : ven. 28/oct./2005 8:20
Localisation : Mayotte ( 976 ), Océan Indien, France

Message 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..
La vie est une rose dont il faut accepter les épines, mais la mienne est fannée, arrosée par le goût de mes larmes. (Soprano)
wolfjeremy
Messages : 1202
Inscription : sam. 31/déc./2005 23:52

Message par wolfjeremy »

+1... :?

Je comprend pas trop bernard13...
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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.
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)]
Répondre