scrollareagadget et imagegadget

Sujets variés concernant le développement en PureBasic
ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

scrollareagadget et imagegadget

Message par ymerdy »

Bonjour,
je suis en PB 5.73LTS et j'essaie de faire un simple ScrollAreaGadget contenant un ImageGadget.
Avec le VisualDesigner, je pose mes gadgets qui donnent ce code:

scrollareatest.pbf

Code : Tout sélectionner

;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;

Global Window_0

Global ScrollArea_0, Image_0


Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu)
  ScrollArea_0 = ScrollAreaGadget(#PB_Any, 80, 40, 460, 280, 300, 225, 1)
  Image_0 = ImageGadget(#PB_Any, 10, 35, 400, 190, 0)
  CloseGadgetList()
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure

Si je clique en dehors de l'imageGadget, et que je reclique dedans, le visualdesigner me le deplace à gauche!
Il se retrouve avec une position négative par rapport au scrollAreaGadget parent.
Le comportement dépend de la taille de l'imageGadget.
En deça d'une certaine taille, pas de probleme.

Avec le code, ça semble faire la meme chose.
5si je fais un resizeGadget de mon imageGadget, à l'execution il se retrouve décalé à gauche).
C'est un bug de PB, du visualDesigner?
ou c'est ma conf?
(windows7 x64)
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: scrollareagadget et imagegadget

Message par microdevweb »

Bonjour ymerdy,

Personnellement je n'utilise jamais le créateur de fenêtre. EN me basant sur ton code voici un petit exemple. J'ai utiliser un canvas en lieu et place de l'image. Le canvas est diviser en 4 portions (de la taille de la fenêtre) et avec le ScrollArea tu peux naviguer à travers l'image.

Voila j'espère que cela pourra t'aider

Code : Tout sélectionner

;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;

Global Window_0

Global ScrollArea_0, canvas_0

Procedure exit()
  End
EndProcedure

Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu)
  ScrollArea_0 = ScrollAreaGadget(#PB_Any, 0, 0, width, height, width * 2, height * 2, 10)
  canvas_0 = CanvasGadget(#PB_Any, 0, 0, width * 2, height * 2)
  CloseGadgetList()
  ; draw something
  StartVectorDrawing(CanvasVectorOutput(canvas_0))
  AddPathBox(0,0,width,height)
  VectorSourceColor($FF2626CD)
  FillPath()
  AddPathBox(width,0,width,height)
  VectorSourceColor($FF00FF00)
  FillPath()
  AddPathBox(0,height,width,height)
  VectorSourceColor($FFCD0000)
  FillPath()
  AddPathBox(width,height,width,height)
  VectorSourceColor($FFCDCD00)
  FillPath()
  StopVectorDrawing()
  ; push event listener for close application
  BindEvent(#PB_Event_CloseWindow,@exit(),Window_0)
EndProcedure

OpenWindow_0()

Repeat
  WaitWindowEvent()
ForEver 


Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Marc56
Messages : 2147
Inscription : sam. 08/févr./2014 15:19

Re: scrollareagadget et imagegadget

Message par Marc56 »

Bonjour,

Pour contrer cela, il faut modifier les valeurs largeur interne et externes du scrollareagadget.
Ainsi l'image se bloquera en haut/gauche du scroll et se déplacera en dehors dans l'autre sens.

Léger bug, le FD n'est pas parfait (mais personne n'a fait mieux). Il faut parfois ruser un peut pour lui faire faire ce qu'on veut.

:wink:
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: scrollareagadget et imagegadget

Message par falsam »

Marc56 a écrit :Pour contrer cela, il faut modifier les valeurs largeur interne et externes du scrollareagadget.
C'est la meilleur réponse.

Code : Tout sélectionner

;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;

Global Window_0

Global ScrollArea_0, Image_0


Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu)
  ;ScrollArea_0 = ScrollAreaGadget(#PB_Any, 80, 40, 460, 280, 300, 225, 1)
  ScrollArea_0 = ScrollAreaGadget(#PB_Any, 80, 40, 460, 280, 1000, 1000, 1)
  Image_0 = ImageGadget(#PB_Any, 10, 35, 400, 190, 0)
  CloseGadgetList()
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure


EnableExplicit
Define Event

OpenWindow_0()

Repeat
  Event = WaitWindowEvent()
  Window_0_Events(Event)
Until Event = #PB_Event_CloseWindow
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
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: scrollareagadget et imagegadget

Message par falsam »

Je n'aime pas Form Designer. J'ai eu des soucis de code non identiques d'un pc à un autre si les préférences de Form Designer n'est pas configurer de la même manière. Mais comme le rappelle Marc, il y a pas mieux pour PureBasic :wink:

@ymerdy : Une autre façon d'écrire ton code.

Code : Tout sélectionner

EnableExplicit

Global Window_0, ScrollArea_0, Image_0

; Sommaire 
Declare Start()
Declare Exit()

Start()

Procedure Start()
  Window_0 = OpenWindow(#PB_Any, 0, 0, 600, 400, "", #PB_Window_SystemMenu)
  ScrollArea_0 = ScrollAreaGadget(#PB_Any, 80, 40, 460, 280, 1000, 1000, 1)
  Image_0 = ImageGadget(#PB_Any, 10, 35, 400, 190, 0)
  CloseGadgetList()
  
  ; Déclencheur
  BindEvent(#PB_Event_CloseWindow, @Exit())
  
  Repeat : WaitWindowEvent() : ForEver
EndProcedure

Procedure Exit()
  End  
EndProcedure
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%
ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

Re: scrollareagadget et imagegadget

Message par ymerdy »

Merci beaucoup à tous pour toutes ces réponses, ces explications et ces exemples.

Je pensais que les parametres ScrollAreaWidth et ScrollAreaHeight s'adaptaient à la taille du contenu.
Mais en effet, quand j'agrandissais la taille de mon imageGadget, il était repositionné pour que ses bords bas et droite ne dépassent pas de la scrollArea.
C'est plus clair maintenant.

Mon but est d'afficher une gallerie de vignettes des images d'un dossier (style FaststoneViewer...).
  • La grille de vignettes fera la largeur de la fenetre et la hauteur nécessaire à l'affichage de toutes les vignettes (ascenceur vertical uniquement)
    La fenetre devra être redimensionnable et le nombre de vignettes par ligne s'adaptera à la largeur de la fenetre
    il faudra détecter le clic souris (voire le survol) sur les vignettes et déclencher une action associée
Je ne sais pas quelle est la meilleure approche:

1) un scrollAreaGadget dans lequel je met un imageGadget qui affiche une image construite en collant toutes les vignettes,
il faudra determiner quelle vignette est cliquée d'aprés les coordonnées du clic
Y a-t-il un avantage à passer par un canvasGadget plutot qu'un imageGadget?

2) un scrollAreaGadget dans lequel chaque vignette est une buttonImageGadget

3) autre solution?

Merci pour vos conseils!
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: scrollareagadget et imagegadget

Message par venom »

Tu as un exemple de microdevweb qui utilise le canvas avec le clic de souris. Ça peut te donner un exemple. :wink:






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Marc56
Messages : 2147
Inscription : sam. 08/févr./2014 15:19

Re: scrollareagadget et imagegadget

Message par Marc56 »

Bonjour,

Le CanvasGadget est principalement un objet de dessin. Pour ton utilisation, il y a plus simple, sauf si tu veux déplacer les images avec la souris.

Si tu souhaites juste afficher et sélectionner de vignettes sans avoir besoin de les déplacer, un ScrollAreaGadget et des ImagesGadgets suffisent, ainsi pas besoin de définir l'image cliquée par ses coordonnées puisque chaque image est un objet.

Exemple rapide.

Code : Tout sélectionner

EnableExplicit

Enumeration 
    #Win
    #ID_Img_1
    #ID_Img_2
    #ID_Img_3
    #Gad_Img_1
    #Gad_Img_2
    #Gad_Img_3
EndEnumeration

OpenWindow(#Win, 0, 0, 405, 240, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 

; Zone d'images 
ScrollAreaGadget(0, 10, 10, 390,220, 575, 575, 30)

LoadImage(#ID_Img_1, #PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp") 
ImageGadget(#Gad_Img_1, 10, 10, 50, 50, ImageID(#ID_Img_1))

LoadImage(#ID_Img_2, #PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp") 
ImageGadget(#Gad_Img_2, 150, 10, 50, 50, ImageID(#ID_Img_2))

LoadImage(#ID_Img_3, #PB_Compiler_Home + "Examples\Sources\Data\GeeBee2.bmp") 
ImageGadget(#Gad_Img_3, 290, 10, 50, 50, ImageID(#ID_Img_3))

; Fin zone d'images
CloseGadgetList() 


Repeat 
    Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow 
            End 
            
        Case #PB_Event_Gadget 
            Select EventGadget()
                    
                Case #Gad_Img_1
                    Debug "Image 1"              
                Case #Gad_Img_2
                    Debug "Image 2"               
                Case #Gad_Img_3
                    Debug "Image 3" 
                    
            EndSelect
    EndSelect 
ForEver 

End
Pour ton système, tu mets bien-sur les ID des images dans un tableau ou une liste (avec For/Next ou ForEach/Next) et tu les positionne en changeant les valeurs x, y en faisant un offset de la valeur de l'image à côté et au dessus.

À noter que tu peux faire le fond de l'interface avec le Form Designer et ensuite positionner les images dynamiquement. Il suffite que l'XInclude du .pbf soit avant la création des images.

:wink:
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: scrollareagadget et imagegadget

Message par kernadec »

bjr à tous
très sympa tous ces exemples
merci à vous pour le partage :D
cordialement

Mais on peut aussi utiliser le mode souris Drag sans ScrollAreaGadget()
dont voici le code réalisé par Danilo code ci-dessous

Sinon pour la complète par mestnyi "drag plus ascenseurs"
voir ce lien https://www.purebasic.fr/english/viewto ... 12&t=70628

Code : Tout sélectionner

;https://www.purebasic.fr/english/viewtopic.php?f=13&t=54098&start=6
;auteur Danilo  mars 2013

Structure canvasitem
  img.i : x.i : y.i : width.i : height.i
EndStructure

Global isCurrentItem = #False
Global currentItemXOffset.i, currentItemYOffset.i

Global NewList Images.canvasitem()

Procedure AddImage(x,y,img)
  If AddElement(Images())
    Images()\img    = img
    Images()\x      = x
    Images()\y      = y
    Images()\width  = ImageWidth(img)
    Images()\height = ImageHeight(img)
  EndIf
EndProcedure

Procedure DrawCanvas()
  If StartDrawing(CanvasOutput(0))
    Box(0,0,GadgetWidth(0),GadgetHeight(0),RGB(255,255,255))
    ForEach Images()
      DrawImage(ImageID(Images()\img),Images()\x,Images()\y) ; draw all images with z-order
    Next
    StopDrawing()
  EndIf
EndProcedure

Procedure HitTest(x,y)
  If LastElement(Images()) ; search for hit, starting from end (z-order)
    Repeat
      If x >= Images()\x And x <  Images()\x + Images()\width
        If y >= Images()\y And y < Images()\y + Images()\height
          match = #True
          Break
        EndIf
      EndIf
    Until PreviousElement(Images())=0
  EndIf
  If match
    isCurrentItem = #True
    currentItemXOffset = x - Images()\x
    currentItemYOffset = y - Images()\y
    temp.canvasitem = Images()
    DeleteElement(Images())
    LastElement(Images()) ; move match to last position (z-order)
    AddElement(Images())
    Images() = temp
  Else
    isCurrentItem = #False
  EndIf
  ProcedureReturn isCurrentItem
EndProcedure

AddImage(10,10,LoadImage(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/PureBasic.bmp"))
AddImage(100,100,LoadImage(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/GeeBee2.bmp"))
AddImage(50,200,LoadImage(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/AlphaChannel.bmp"))

If OpenWindow(0, 0, 0, 420, 420, "Move/Drag Canvas Image", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(0, 10, 10, 400, 400)
  
  DrawCanvas()
  
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Gadget And EventGadget() = 0
      Select EventType()
        Case #PB_EventType_LeftButtonDown
          x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
          y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
          If HitTest(x,y)
            DrawCanvas()
          EndIf
          Drag = #True
        Case #PB_EventType_LeftButtonUp
          Drag = #False
        Case #PB_EventType_MouseMove
          If Drag = #True
            If isCurrentItem
              x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
              y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
              If LastElement(Images())
                Images()\x = x - currentItemXOffset
                Images()\y = y - currentItemYOffset
                DrawCanvas()
              EndIf
            EndIf
          EndIf
      EndSelect
    EndIf   
    
  Until Event = #PB_Event_CloseWindow
EndIf
ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

Re: scrollareagadget et imagegadget

Message par ymerdy »

Hello,

j'ai avancé dans mon projet de viewer d'images genre FastStone Viewer.
J'utilise finalement un scrollAreaGadget avec un canvasGadget pour chaque vignette, afin de pouvoir gérer différents types d'évènements.
J'ai maintenant un soucis de rafraichissement lors du redimensionnement de la fenetre.
Je sais que ce sujet a été abordé maintes fois sur le forum, mais je ne trouve pas de solution satisfaisante.

Je ne vois aucune amélioration à l'utilisation du SmartWindowRefresh(),
ni à l'utilisation des LockWindowUpdate_() et UpdateWindow_(),
à moins que je les utilise mal.

Voici un extrait simplifié de mon code:
lors du redimensionnement, on voit que tout le ré-affichage clignote.
Il n'y a vraiment pas un systeme simple de double-buffer qui permet de mettre à jour l'affichage des gadgets une fois que tout le tracé est terminé?

Code : Tout sélectionner

;###############################################################################################################################
;- ------Variables
;###############################################################################################################################
Structure Thumb
	x.i
	y.i
	gadget_id.i
EndStructure

; --- les gadgets
Global MainWindow
Global ScrollArea

; --- dimension de la fenetre
Global Wind_w = 800
Global Wind_h = 600

; --- dimensions des vignettes
Global thumbSize = 40
Global thumbSep=5
Global nbThumb = 150
Global nbThumbByLine

; liste des vignettes
Global NewList list_thumbs.Thumb()

;###############################################################################################################################
;- ------Procedures
;###############################################################################################################################
Declare Window_Resize()
Declare calcThumbPositions()
Declare createGalleryGadgets()
;###############################################################################################################################

;+++++++++++++++++++++++++++++++++++++
; Gestion de l'evenement resizewindow
;+++++++++++++++++++++++++++++++++++++
Procedure Window_Resize()
	
	Protected size_window_w = WindowWidth(MainWindow)
	Protected size_window_h = WindowHeight(MainWindow)
	
	; aucun effet?
	LockWindowUpdate_(WindowID(MainWindow))
	
	; On ajuste la scrollarea a la taille de la fenetre
	ResizeGadget(ScrollArea ,#PB_Ignore, #PB_Ignore,  size_window_w-15, size_window_h-15)
	SetGadgetAttribute(ScrollArea,#PB_ScrollArea_InnerWidth,size_window_w-15)
	SetGadgetAttribute(ScrollArea,#PB_ScrollArea_InnerHeight,size_window_h-15)	
	
	; si le nombre de vignettes par ligne change, on met a jour les positions
	Protected new_nbThumbByLine = (GadgetWidth(ScrollArea)-15) /(thumbSize+thumbSep)
	
	If new_nbThumbByLine<>nbThumbByLine
		calcThumbPositions()
		ForEach list_thumbs()
			ResizeGadget(list_thumbs()\gadget_id,list_thumbs()\x,list_thumbs()\y,#PB_Ignore, #PB_Ignore)
		Next
		nbThumbByLine = new_nbThumbByLine
		
	EndIf
	LockWindowUpdate_(0)
	UpdateWindow_(WindowID(MainWindow))
	
	
EndProcedure

;+++++++++++++++++++++++++++++++++++++
; Calcul de la position de chaque canvasgadgets
;+++++++++++++++++++++++++++++++++++++
Procedure calcThumbPositions()
	
	nbThumbByLine = (GadgetWidth(ScrollArea)-15) /(thumbSize+thumbSep);(largeur ascenceur vertical=15?)
  
	thumb_num.i = 0
	ForEach list_thumbs()
		
		list_thumbs()\x=thumbSep+(thumb_num % nbThumbByLine)*(thumbSize+thumbSep)
		list_thumbs()\y=thumbSep+(thumb_num/nbThumbByLine)*(thumbSize+thumbSep)
		thumb_num+1
		
	Next
	
EndProcedure

;+++++++++++++++++++++++++++++++++++++
; Construction de la liste de canvasgadgets
; dans la scrollArea
;+++++++++++++++++++++++++++++++++++++
Procedure createGalleryGadgets()
	nb_thumb.i = ListSize(list_thumbs())
	
	; On va ajouter tous les canvasGadget dans la scrollArea
	OpenGadgetList(ScrollArea)
	
	ForEach list_thumbs()
		
		; On ajoute la vignette dans la scrollArea
		; on memorise le numero du gadget dans la liste
		list_thumbs()\gadget_id=CanvasGadget(#PB_Any, list_thumbs()\x,list_thumbs()\y,thumbSize,thumbSize)
		StartDrawing(CanvasOutput(list_thumbs()\gadget_id))
		; couleur ou image
		Box(0,0,thumbSize-1,thumbSize-1,RGB(Random(255,0),Random(255,0),Random(255,0)))
		DrawText(20,20,Str(thumb_num),RGB(255,255,255))
		StopDrawing()
		thumb_num+1
		
	Next
	
	CloseGadgetList()
	
EndProcedure

;###############################################################################################################################
;- ------Initialisation
;###############################################################################################################################
MainWindow = OpenWindow(#PB_Any,0,0,Wind_w,600,"test resize",#PB_Window_SystemMenu | #PB_Window_SizeGadget)
ScrollArea = ScrollAreaGadget(#PB_Any, 0, 0, Wind_w-15, Wind_h-15, Wind_w-30, Wind_h-30, #PB_ScrollArea_Raised)
SetGadgetColor(ScrollArea,#PB_Gadget_BackColor ,RGB(50,50,50))

; Aucun effet?
SmartWindowRefresh(MainWindow, #True)

; Gestion du redimensionnement de la fenetre en temps reel
BindEvent(#PB_Event_SizeWindow,@Window_Resize(),MainWindow)

; on cree une liste de canvasGadgets
For i=0 To nbThumb -1
	AddElement(list_thumbs())
Next

nbThumbByLine = (GadgetWidth(ScrollArea)-15) /(thumbSize+thumbSep);(largeur ascenceur vertical=15?)

calcThumbPositions()
createGalleryGadgets()

;###############################################################################################################################
;- ------Boucle principale
;###############################################################################################################################
Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

Re: scrollareagadget et imagegadget

Message par ymerdy »

Bon, je viens de tester mon exemple sur Windows10, il n'y a aucun clignotement.
Par contre sur Windows7, même en changeant juste la hauteur de la fenêtre (donc sans changement de position des canvasGadgets), on voit le contenu clignoter lorsque la scrollArea est agrandie.

J'ai testé également le module DeFlicker de PureLust => sans effet.
ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

Re: scrollareagadget et imagegadget

Message par ymerdy »

Well,
J'ai épluché les 3000 threads des forums PB et autre pour comprendre que je ne suis pas le 1er à pleurer devant une IHM qui clignote sous Windows :?

aprés pas mal de test, il semble que le redraw d'un canvasGadget en lieu et place d'un scrollAreaGadget ne provoque aucun clignotement, même sans aucune bidouille d'appel de SendMessage_() ou autre...

Il ne me reste plus qu'à gérer l'apparition des ascenseurs pour faire une custom scrollarea à base de canvas, et ça devrait le faire.

Code : Tout sélectionner

;XIncludeFile "Modul_DeFlicker.pbi"

Macro DisableRedraw(hWnd)
    ; http://msdn.microsoft.com/en-US/library/dd145219(v=vs.85).aspx
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SendMessage_(hWnd,#WM_SETREDRAW,0,0)
    CompilerEndIf
EndMacro

Macro EnableRedraw(hWnd)
    ; http://msdn.microsoft.com/en-US/library/dd145219(v=vs.85).aspx
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SendMessage_(hWnd,#WM_SETREDRAW,1,0)
        RedrawWindow_(hWnd, 0, 0, #RDW_ERASE | #RDW_FRAME | #RDW_INVALIDATE | #RDW_ALLCHILDREN)
    CompilerEndIf
EndMacro


Macro StopWindowUpdate(_winID_)
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SendMessage_(_winID_,#WM_SETREDRAW,0,0)
    CompilerEndIf
EndMacro

Macro ContinueWindowUpdate(_winID_, _redrawBackground_ = 0)
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SendMessage_(_winID_,#WM_SETREDRAW,1,0)
        InvalidateRect_(_winID_,0,_redrawBackground_)
        UpdateWindow_(_winID_)
    CompilerEndIf
EndMacro

;###############################################################################################################################
;- ------Variables
;###############################################################################################################################
Structure Thumb
	x.i
	y.i
	gadget_id.i
EndStructure

; --- les gadgets
Global MainWindow
Global container

; --- dimension de la fenetre
Global Wind_w = 800
Global Wind_h = 600

; --- dimensions des vignettes
Global thumbSize = 40
Global thumbSep=5
Global nbThumb = 150
Global nbThumbByLine

; liste des vignettes
Global NewList list_thumbs.Thumb()

Global useScrollArea.b = #False

;###############################################################################################################################
;- ------Procedures
;###############################################################################################################################
Declare Window_Resize()
Declare calcThumbPositions()
Declare createGalleryGadgets()
;###############################################################################################################################

;+++++++++++++++++++++++++++++++++++++
; Gestion de l'evenement resizewindow
;+++++++++++++++++++++++++++++++++++++
Procedure Window_Resize()
	;SendMessage_(WindowID(MainWindow),#WM_SETREDRAW,#False,0)          ; <======================
	
	; aucun effet
	;winID = WindowID(MainWindow)
	;StopWindowUpdate(winID)
	
	; aucun effet
	;DeFlicker_StartResize(MainWindow)
	
	;HideGadget(container,#True)
	
	Protected size_window_w = WindowWidth(MainWindow)
	Protected size_window_h = WindowHeight(MainWindow)
	
	; aucun effet?
	;LockWindowUpdate_(WindowID(MainWindow))
	
	; On ajuste la container a la taille de la fenetre
	;SendMessage_(GadgetID(container),#WM_SETREDRAW,#False,0)
	
	ResizeGadget(container ,#PB_Ignore, #PB_Ignore,  size_window_w-15, size_window_h-15)
	;SetGadgetAttribute(container,#PB_ScrollArea_InnerWidth,size_window_w-15)
	;SetGadgetAttribute(container,#PB_ScrollArea_InnerHeight,size_window_h-15)	
	
	; si le nombre de vignettes par ligne change, on met a jour les positions
	Protected new_nbThumbByLine = (GadgetWidth(container)-15) /(thumbSize+thumbSep)
	
	If new_nbThumbByLine<>nbThumbByLine
		calcThumbPositions()
		ForEach list_thumbs()
			;SendMessage_(list_thumbs()\gadget_id,#WM_SETREDRAW,#False,0)
			
			ResizeGadget(list_thumbs()\gadget_id,list_thumbs()\x,list_thumbs()\y,#PB_Ignore, #PB_Ignore)
		Next
		nbThumbByLine = new_nbThumbByLine
		
	EndIf
	;LockWindowUpdate_(0)
	;UpdateWindow_(WindowID(MainWindow))
	
	; aucun effet
	;DeFlicker_EndResize()
	;DeFlicker_RefreshWindow(MainWindow)
	
	;HideGadget(container,#False)
	
	;ContinueWindowUpdate(winID)
	;ForEach list_thumbs()
	;	SendMessage_(list_thumbs()\gadget_id,#WM_SETREDRAW,#True,0)           ; <##########################
	;Next
	
	;SendMessage_(GadgetID(container),#WM_SETREDRAW,#True,0)           ; <##########################
	
	;SendMessage_(WindowID(MainWindow),#WM_SETREDRAW,#True,0)                   ; <======================
	;RedrawWindow_(WindowID(MainWindow),#Null,#Null,#RDW_INVALIDATE)						 ; <======================
	
	
EndProcedure

;+++++++++++++++++++++++++++++++++++++
; Calcul de la position de chaque canvasgadgets
;+++++++++++++++++++++++++++++++++++++
Procedure calcThumbPositions()
	
	nbThumbByLine = (GadgetWidth(container)-15) /(thumbSize+thumbSep);(largeur ascenceur vertical=15?)
  
	thumb_num.i = 0
	ForEach list_thumbs()
		
		list_thumbs()\x=thumbSep+(thumb_num % nbThumbByLine)*(thumbSize+thumbSep)
		list_thumbs()\y=thumbSep+(thumb_num/nbThumbByLine)*(thumbSize+thumbSep)
		thumb_num+1
		
	Next
	
EndProcedure

;+++++++++++++++++++++++++++++++++++++
; Construction de la liste de canvasgadgets
; dans le container
;+++++++++++++++++++++++++++++++++++++
Procedure createGalleryGadgets()
	nb_thumb.i = ListSize(list_thumbs())
	
	; On va ajouter tous les canvasGadget dans le container
	OpenGadgetList(container)
	
	ForEach list_thumbs()
		
		; On ajoute la vignette dans le container
		; on memorise le numero du gadget dans la liste
		list_thumbs()\gadget_id=CanvasGadget(#PB_Any, list_thumbs()\x,list_thumbs()\y,thumbSize,thumbSize)
		StartDrawing(CanvasOutput(list_thumbs()\gadget_id))
		; couleur ou image
		Box(0,0,thumbSize-1,thumbSize-1,RGB(Random(255,0),Random(255,0),Random(255,0)))
		DrawText(20,20,Str(thumb_num),RGB(255,255,255))
		StopDrawing()
		thumb_num+1
		
	Next
	
	CloseGadgetList()
	
EndProcedure

;###############################################################################################################################
;- ------Initialisation
;###############################################################################################################################
MainWindow = OpenWindow(#PB_Any,0,0,Wind_w,600,"test resize",#PB_Window_SystemMenu | #PB_Window_SizeGadget)
If useScrollArea
	container = ScrollAreaGadget(#PB_Any, 0, 0, Wind_w-15, Wind_h-15, Wind_w-30, Wind_h-30, #PB_ScrollArea_Raised)
Else
	container = CanvasGadget(#PB_Any,0,0, Wind_w-15, Wind_h-15,#PB_Canvas_Border|#PB_Canvas_Container)
EndIf

SetGadgetColor(container,#PB_Gadget_BackColor ,RGB(50,50,50))

; aucun effet
;SmartWindowRefresh bascially create a clip region out of all sibling control, and apply it to the WM_ERASEBACKGROUND message, so the erase doesn't overwrite the controls with a solid color. So the more control you have in your root window, the worste it will perfom.
;SmartWindowRefresh(MainWindow, #True)

; aucun effet
;#WS_EX_COMPOSITED = $2000000
;SetWindowLong_(MainWindow, #GWL_EXSTYLE, GetWindowLong_(MainWindow, #GWL_EXSTYLE) | #WS_EX_COMPOSITED)

; Gestion du redimensionnement de la fenetre en temps reel
BindEvent(#PB_Event_SizeWindow,@Window_Resize(),MainWindow)

; on cree une liste de canvasGadgets
For i=0 To nbThumb -1
	AddElement(list_thumbs())
Next

nbThumbByLine = (GadgetWidth(container)-15) /(thumbSize+thumbSep);(largeur ascenceur vertical=15?)

calcThumbPositions()
createGalleryGadgets()

;###############################################################################################################################
;- ------Boucle principale
;###############################################################################################################################
Repeat
	Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow


Si ça fonctionne, je nettoie le code et je poste le résultat.
Avatar de l’utilisateur
kernadec
Messages : 1594
Inscription : ven. 25/avr./2008 11:14

Re: scrollareagadget et imagegadget

Message par kernadec »

salut ymerdy
Je pense que le Module Scroll.pbi de mestnyi est vraiment top
perso jamais vu meilleur démonstration.
il fait tout ce qu'on souhaite pour déplacer un objet sur CanvasGadget() drag drop, ascenseurs
la solution serait peut être de t'inspirer de ce module ou de l’utiliser :wink:
https://www.purebasic.fr/english/viewto ... 12&t=70628

Cordialement
ymerdy
Messages : 19
Inscription : jeu. 19/oct./2017 22:10

Re: scrollareagadget et imagegadget

Message par ymerdy »

Bonjour,

le code de mestnyi est impressionnant.
J'ai appris beaucoup de choses en l'étudiant, pour faire une version simplifiée qui réponde à mes besoins.

J'ai une solution qui me convient, mais il y a un fonctionnement que je ne comprend pas...

Selon que je déclenche le repaint de mon canvas par le handler d’événements de la fenetre, lors du resize,
ou par le handler d’événements du canvas (qui s'active également lors du resize),
le comportement n'est pas le même.
Dans le 1er cas ça clignote, dans le second cas, c'est propre.
Alors qu'il me semble que dans le 1er cas, on a moins de traitements avant de rafraîchir le canvas
Cas1: #Flicker
event windowResize => ResizeWindow_Callback() = resizeCanvas+repaint canvas

Cas2: #NoFlicker
event windowResize => ResizeWindow_Callback() =resizeCanvas =>event canvasResize => CanvasEvent_Callback() = repaint canvas


Voici un exemple (clignotement très fort quand on agrandit la fenêtre, avec #RefreshMode=#Flicker, aucun clignotement avec #RefreshMode=#NoFlicker)

Si quelqu'un pouvait m'expliquer où est le problème...

Code : Tout sélectionner


Enumeration
	#MyCanvas = 1 
EndEnumeration

Enumeration
	#Flicker = 1 
	#NoFlicker = 2
EndEnumeration

  
  ; #RefreshMode  1 (#Flicker)
  ; le repaint du canvas est géré directement par le callback appelé sur event resize de la fenetre
	; L'event est déclenché par le resize effectué par le callback du resize de la fenetre
  ; => clignotements lors du repaint
  
  ; #RefreshMode 2
  ; le repaint du canvas est géré par le callback appelé sur event sur le canvas
	; L'event est déclenché par le resize effectué par le callback du resize de la fenetre
	; => pas de clignotements lors du repaint

 ;#RefreshMode = #NoFlicker
 #RefreshMode = #Flicker

;----------------------------------------------------------------------------------------------
  Procedure ResizeWindow_CallBack()
  	; On resize le canvas pour l'adapter a la fenetre
  	ResizeGadget(#MyCanvas,0,0,WindowWidth(0),WindowHeight(0))
  	
  	If #RefreshMode = #Flicker
  		; et on gère son repaint
  		StartDrawing(CanvasOutput(#MyCanvas))
  		  Box(0,0,GadgetWidth(#MyCanvas),GadgetHeight(#MyCanvas),RGB(255,0,0))
  		StopDrawing()
  	EndIf
  EndProcedure
  
;----------------------------------------------------------------------------------------------
  Procedure.i CanvasEvent_CallBack()
  	; on repaint le canvas
  	StartDrawing(CanvasOutput(#MyCanvas))
  	Box(0,0,GadgetWidth(#MyCanvas),GadgetHeight(#MyCanvas),RGB(255,0,0))
  	StopDrawing()
  EndProcedure
  

;==============================================================================================
  If Not OpenWindow(0, 0, 0, 800, 600, "Test canvas refresh", #PB_Window_SystemMenu | #PB_Window_SizeGadget )
    MessageRequester("Fatal error", "Program terminated.")
    End
  EndIf
  
  ; On attache un callback a l'evenement resize de la fenetre
  BindEvent(#PB_Event_SizeWindow, @ResizeWindow_CallBack())
  
  ; On cree un canvas de la taille de la fenetre
  CanvasGadget(#MyCanvas, 0, 0, 800, 600)
  ; On fait un 1er repaint
  CanvasEvent_CallBack()
  
  ; On attache un callback aux evenements du canvas
  If #RefreshMode = #NoFlicker
  	BindGadgetEvent(#MyCanvas, @CanvasEvent_CallBack())
  EndIf

  ; Boucle principale	
  Repeat
  	testEvent = WaitWindowEvent()
  Until testEvent = #PB_Event_CloseWindow
  End
  
  ;

Répondre