Repaint gadgets au dessus de canvas

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
ChrisR
Messages : 222
Inscription : sam. 14/févr./2015 16:20

Repaint gadgets au dessus de canvas

Message par ChrisR »

Dans l'exemple suivant, j'utilise des canvas derrières des gadgets, pour avoir la main dessus avec la sélection, le déplacement (flèches) ou le redimensionnement (Shift+flèches).
Quand je prends le focus avec LeftButtonDown ou quand je le perd LostFocus, pour ne pas avoir un cadre blanc (=canvas) je dois repeindre le gadget avec:
ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ou avec:
HideGadget(\Gadget,#True)
HideGadget(\Gadget,#False)
Y a t'il une solution préférable entre les 2, ou autres ?

Code : Tout sélectionner

Enumeration
  #Window_0
  #Canvas_0
  #Editor_0
  #Canvas_1
  #Text_0
  #Button_0
EndEnumeration

Structure GadgetHandle
  Gadget.i
  Handle.i
EndStructure

Procedure GadgetHandle_Callback()
  Protected GadgetHandle.GadgetHandle, ResizeDone.b = #False
  
  With GadgetHandle
    \Handle = EventGadget()
    \Gadget = GetGadgetData(\Handle) 
    
    Select EventType()
        
      Case #PB_EventType_Focus
        If StartDrawing(CanvasOutput(\Handle))   ;Dessiner une bordure autour du gadget
          Box(0, 0, OutputWidth(), OutputHeight(), $000000) 
          Box(1, 1, OutputWidth()-2, OutputHeight()-2, $FFFFFF)
          StopDrawing()
        EndIf
        
      Case #PB_EventType_LostFocus
        If StartDrawing(CanvasOutput(\Handle))   ;Supprimer la bordure autour du gadget
          Box(0, 0, OutputWidth(), OutputHeight(), $FFFFFF) 
          StopDrawing()
        EndIf
        ;DisableGadget(\Gadget,#True) : DisableGadget(\Gadget,#False)   ;ne redessine pas le Gadget
        ;SetActiveGadget(\Gadget)   ;ne redessine pas le Gadget
        ;HideGadget(\Gadget,#True) : HideGadget(\Gadget,#False)   ;OK mais quel est le mieux entre hide/unhide ou Resize  
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)   ;OK mais quel est le mieux entre hide/unhide ou Resize  
        
      Case #PB_EventType_KeyDown
        Select GetGadgetAttribute(EventGadget(),#PB_Canvas_Key)
          Case #PB_Shortcut_Right
            If GetGadgetAttribute(\Handle, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
              ResizeGadget(\Handle, #PB_Ignore, #PB_Ignore, GadgetWidth(\Handle)+1, #PB_Ignore)
            Else
              ResizeGadget(\Handle, GadgetX(\Handle)+1, #PB_Ignore, #PB_Ignore, #PB_Ignore)
            EndIf
          Case #PB_Shortcut_Left
            If GetGadgetAttribute(\Handle, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
              ResizeGadget(\Handle, #PB_Ignore, #PB_Ignore, GadgetWidth(\Handle)-1, #PB_Ignore)
            Else            
              ResizeGadget(\Handle, GadgetX(\Handle)-1, #PB_Ignore, #PB_Ignore, #PB_Ignore)
            EndIf
          Case #PB_Shortcut_Up
            If GetGadgetAttribute(\Handle, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
              ResizeGadget(\Handle, #PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(\Handle)-1)
            Else
              ResizeGadget(\Handle, #PB_Ignore, GadgetY(\Handle)-1, #PB_Ignore, #PB_Ignore)
            EndIf
          Case #PB_Shortcut_Down
            If GetGadgetAttribute(\Handle, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
              ResizeGadget(\Handle, #PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(\Handle)+1)
            Else
              ResizeGadget(\Handle, #PB_Ignore, GadgetY(\Handle)+1, #PB_Ignore, #PB_Ignore)
            EndIf 
        EndSelect
        If StartDrawing(CanvasOutput(\Handle))   ;Redessiner la bordure en cas de redimensionnement 
          Box(0, 0, OutputWidth(), OutputHeight(), $480000)
          Box(1, 1, OutputWidth()-2, OutputHeight()-2, $FFFFFF)
          StopDrawing()
        EndIf
        ResizeGadget(\Gadget, GadgetX(\Handle)+1, GadgetY(\Handle)+1, GadgetWidth(\Handle)-2, GadgetHeight(\Handle)-2)        
        
      Case #PB_EventType_LeftButtonDown
        ;DisableGadget(\Gadget,#True) : DisableGadget(\Gadget,#False)   ;ne redessine pas le Gadget
        ;SetActiveGadget(\Gadget)   ;ne redessine pas le Gadget
        ;HideGadget(\Gadget,#True) : HideGadget(\Gadget,#False)   ;OK mais quel est le mieux entre hide/unhide ou Resize  
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)   ;OK mais quel est le mieux entre hide/unhide ou Resize  
        
    EndSelect
  EndWith
EndProcedure

OpenWindow(#Window_0, 0, 0, 300, 145, "", #PB_Window_SystemMenu)

CanvasGadget(#Canvas_0, 0, 0, 0, 0, #PB_Canvas_Keyboard)
EditorGadget(#Editor_0, 50, 20, 200, 50, #PB_Editor_WordWrap) : SetGadgetText(#Editor_0, "Text Editor Gadget")
ResizeGadget(#Canvas_0, GadgetX(#Editor_0)-1, GadgetY(#Editor_0)-1, GadgetWidth(#Editor_0)+2, GadgetHeight(#Editor_0)+2)
SetGadgetData(#Canvas_0, #Editor_0)

CanvasGadget(#Canvas_1, 0, 0, 0, 0, #PB_Canvas_Keyboard)
TextGadget(#Text_0, 50, 80, 100, 20, "Texte")
ResizeGadget(#Canvas_1, GadgetX(#Text_0)-1, GadgetY(#Text_0)-1, GadgetWidth(#Text_0)+2, GadgetHeight(#Text_0)+2)
SetGadgetData(#Canvas_1, #Text_0)

ButtonGadget(#Button_0, 50, 110, 100, 25, "Take Focus")

SetGadgetAttribute(#Canvas_0, #PB_Canvas_Cursor, #PB_Cursor_Arrows)
BindGadgetEvent(#Canvas_0, @GadgetHandle_Callback())
SetGadgetAttribute(#Canvas_1, #PB_Canvas_Cursor, #PB_Cursor_Arrows)
BindGadgetEvent(#Canvas_1, @GadgetHandle_Callback())

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver
#2
En remplaçant Case #PB_EventType_KeyDown avec le code ci dessous, je dois également repeindre le gadget avec hide/unhide ou ResizeGadget à la fin.
Ici, contrairement au code ci dessus le redimensionnement est fait sur le Gadget en 1er et sur le canva (ou poignée) ensuite. Il est fait de même dans "SweetyVD" pour calculer les positions mini, maxi pour les déplacements/redimensionnements.
Pour éviter le "Flickerring" avec ResizeGadget(\Gadget, #PB_Ignore...) à chaque #PB_EventType_KeyDown, je passe par une variable, ResizeDone alimenté à #True en cas de déplacements/redimensionnements réellement effectués.
Est-ce que je loupe quelque chose ? Y a t'il mieux à faire ?

Code : Tout sélectionner

Case #PB_EventType_KeyDown
  Select GetGadgetAttribute(EventGadget(),#PB_Canvas_Key)
    Case #PB_Shortcut_Right
      If GetGadgetAttribute(\Handle, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, GadgetWidth(\Gadget)+1, #PB_Ignore)
      Else
        ResizeGadget(\Gadget, GadgetX(\Gadget)+1, #PB_Ignore, #PB_Ignore, #PB_Ignore)
      EndIf
      ResizeDone = #True
    Case #PB_Shortcut_Left
      If GetGadgetAttribute(\Gadget, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, GadgetWidth(\Gadget)-1, #PB_Ignore)
      Else            
        ResizeGadget(\Gadget, GadgetX(\Gadget)-1, #PB_Ignore, #PB_Ignore, #PB_Ignore)
      EndIf
      ResizeDone = #True
    Case #PB_Shortcut_Up
      If GetGadgetAttribute(\Gadget, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(\Gadget)-1)
      Else
        ResizeGadget(\Gadget, #PB_Ignore, GadgetY(\Gadget)-1, #PB_Ignore, #PB_Ignore)
      EndIf
      ResizeDone = #True
    Case #PB_Shortcut_Down
      If GetGadgetAttribute(\Gadget, #PB_Canvas_Modifiers) = #PB_Canvas_Shift 
        ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(\Gadget)+1)
      Else
        ResizeGadget(\Gadget, #PB_Ignore, GadgetY(\Gadget)+1, #PB_Ignore, #PB_Ignore)
      EndIf
      ResizeDone = #True
  EndSelect
  If ResizeDone   ;Solution de contournement pour effectuer ResizeGadget(\Gadget) sans le clignotement
     If StartDrawing(CanvasOutput(\Handle))   ;Redessiner la bordure en cas de redimensionnement 
       Box(0, 0, OutputWidth(), OutputHeight(), $480000)
       Box(1, 1, OutputWidth()-2, OutputHeight()-2, $FFFFFF)
       StopDrawing()
     EndIf
     ResizeGadget(\Handle, GadgetX(\Gadget)-1, GadgetY(\Gadget)-1, GadgetWidth(\Gadget)+2, GadgetHeight(\Gadget)+2)
     ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)
  EndIf
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Repaint gadgets au dessus de canvas

Message par falsam »

Je pense que tu vas devoir passer par le dessin de tes gadgets sur le canvas. J'avais commencé un projet en 2015. Je vais le ressortir de mes archives et le mettre à jour avec les dernieres version de pb.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
ChrisR
Messages : 222
Inscription : sam. 14/févr./2015 16:20

Re: Repaint gadgets au dessus de canvas

Message par ChrisR »

Merci, j'avais fait un essai du dessin sur le Gadget avec:

Code : Tout sélectionner

If StartDrawing(WindowOutput(ParentGadget))
  TmpImage = GrabDrawingImage(#PB_Any, GadgetX(Gadget), GadgetY(Gadget), GadgetWidth(Gadget), GadgetHeight(Gadget))
  StopDrawing()
EndIf
If StartDrawing(CanvasOutput(Handle))
  Box(0, 0, OutputWidth(), OutputHeight(), $000000)
  DrawImage(ImageID(TmpImage), 1, 1, GadgetWidth(Handle)-2,GadgetHeight(Handle)-2)
  StopDrawing()
EndIf
Ensuite, pour ne pas avoir une image trop déformée, il faut la redessiner à chaque redimensionnement et avec un souci à régler en cas de chevauchement de plusieurs Gadgets.
J'avais abandonné sans persévérer.

Bon, je crois que je vais continuer sur le principe des canvas actuels, blancs avec juste le cadre. Et pour éviter les soucis, toujours redimensionner les canvas (poignées) avant le Gadget. Il semble pas trop mal comme cela.
Il faut que je reprenne le calcul des positions (X,Y,Width,Height) + position mini, maxi. Grrr, La flemme :wink:
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Repaint gadgets au dessus de canvas

Message par Ar-S »

La 5.60 et l'option #PB_Canvas_Container ne résout pas ce soucis ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
ChrisR
Messages : 222
Inscription : sam. 14/févr./2015 16:20

Re: Repaint gadgets au dessus de canvas

Message par ChrisR »

Oui, #PB_Canvas_Container avec PB5.60 doit pouvoir résoudre ce genre de souci.
Et pour avoir la main sur le canva, il faut désactiver les gadgets + ResizeGadget pour voir les TextGadget désactivés.

Mais, dans mon utilisation, il sont créer à la volée et il faut alors jouer avec SetParent + ResizeGadget(blabla, X, Y
Activer:

Code : Tout sélectionner

Handle = CanvasGadget(#PB_Any, GadgetX(Gadget)-1, GadgetY(Gadget)-1, GadgetWidth(Gadget)+2,  GadgetHeight(Gadget)+2, #PB_Canvas_Container|#PB_Canvas_Keyboard)
ResizeGadget(Gadget, 1, 1, #PB_Ignore, #PB_Ignore)
SetParentProc(Gadget, Handle)
SetGadgetZOrder(Handle)
Désactiver:

Code : Tout sélectionner

ResizeGadget(Gadget, GadgetX(Handle)+1, GadgetY(Handle)+1, GadgetWidth(Handle)-2, GadgetHeight(Handle)-2)
SetParentProc(Gadget, ParentGadget)
FreeGadget(Handle)
Avec des soucis d'affichage après désactivation
Dernière modification par ChrisR le jeu. 09/mars/2017 20:21, modifié 2 fois.
Avatar de l’utilisateur
ChrisR
Messages : 222
Inscription : sam. 14/févr./2015 16:20

Re: Repaint gadgets au dessus de canvas

Message par ChrisR »

ChrisR a écrit :...... repeindre le gadget avec:
ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)
ou avec:
HideGadget(\Gadget,#True) : HideGadget(\Gadget,#False)
Je viens de tester avec:

Code : Tout sélectionner

        t0 = ElapsedMilliseconds()
        For i = 1 To 10000
          ResizeGadget(\Gadget, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)   ;OK mais quel est le mieux entre hide/unhide ou Resize  
        Next
        t1 = ElapsedMilliseconds()
        
        For i = 1 To 10000
          HideGadget(\Gadget,#True) : HideGadget(\Gadget,#False)
        Next
        t2 = ElapsedMilliseconds()
        Debug "ResizeGadget: " + Str(t1 - t0) + #LF$ + "(Un)HideGadget : " + Str(t2 - t1)
Il y a pas photo, ResizeGadget est nettement plus rapide
ResizeGadget: 157
(Un)HideGadget : 2775
Avatar de l’utilisateur
Ar-S
Messages : 9478
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Repaint gadgets au dessus de canvas

Message par Ar-S »

Sacré différence en effet !
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Répondre