Page 1 sur 1

CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 13:03
par Golfy
Bonjour à tous,

Sur le lien suivant, vous pouvez voir un screenshot de mon programme :
http://forum.velleman.eu/viewtopic.php? ... 778#p40929

Mon problème est que je dois faire du Drag'n Drop (les symboles de la colonne à droite peuvent aller sur un des étages). Une fois le symbole "lié" à son plan, je veux cliquer dessus pour éteindre/allumer une lampe, etc.

Je voudrais utiliser des Canvasgadget mais mon image de fond étant un CanvasGadget (le plan), puis-je ajouter par dessus d'autres CanvasGadget (les symboles) ?
Sachant que je veux détecter un clic sur le symbole... (un clic sur le plan ne m'intéresse pas).

Actuellement, je pose une image sur le plan et je détecte les coordonnées de la souris sur le CanvasGadget "planRdC", "Plan1er", etc.

Re: CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 16:33
par Ar-S
Ajouter des gadgets par dessus des gadgets c'est jamais bien bon.
- j'utiliserai qu'un seul Canvas et de nombreuses images.
1 image de ton plan (l'original) et 1 image par symbole et une image crée à la volée plan + symbole(s)
Au drag n Drop tu redessines le plan + l'image désignée par le Drag N Drop.
Inconvénient c'est de ne pas pouvoir déplacer "en live" ce symbole s'il est mal placé par exemple.
Par contre tu peux surement faire en sorte d'ajouter des boutons pour décaler le symbole à droite haut bas gauche (en fait le canvas se redessinerait incluant canvas original plus symbole décalé de "N"

Re: CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 17:54
par falsam
Un code simplifié qui permet de :
-Dessiner avec la souris.
-Insérer deux symboles depuis un menu contextuel accessible avec le bouton droit de la souris, ou alors par drag&drop depuis les deux symboles sur la gauche.
-Possibilité de déplacer les symboles avec la souris.
-Possibilité d'allumer ou d’éteindre les symboles depuis le menu contextuel.
-Possibilité de supprimer un symbole.

je ne traite pas de la sauvegarde du dessin mais si demande alors pourquoi pas :)

Code : Tout sélectionner

EnableExplicit

Enumeration Window
  #Mainform
  #S1
  #S2
  #Design
  #PM
  #PMS1
  #PMS2
  #PMOnOff
  #PMDelete
EndEnumeration

Enumeration Image
  #BackGround  ;Fond du canvas
  #IMAGES1     ;Image du symbole 1
  #IMAGES2     ;Image du symbole 2
EndEnumeration


Define.l Event, WEvent, MEvent, GEvent, TEvent

Global WindowStyle.i=#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered

Global MouseX.i, MouseY.i ;Position x y de la souris
Global DeltaX.i, DeltaY.i ;Delta bord gauche et haut du symbole et Coordonnées de la souris 
Global LeftButtonDown.b   ;Etat bouton gauche de la souris
Global Model.i            ;Model du symbole en cours de drag depuis la liste des modéles

Structure Symbol
  Actif.b   ;Supression du dessin #True or #False
  Model.i   ;Model de symbole utilisé
  Status.b  ;OnOff (#True, #False)
  x.i       ;Position x sur le dessin
  y.i       ;Position y sur le dessin
  Width.i   ;Largeur du symbole (ou rayon)
  height.i  ;Hauteur du symbole (ou rayon)
EndStructure

Global NewList Elements.Symbol(), *ActiveElement.Symbol

;Mise à jour du dessin
;Appel ElementAdd(), ExamineDesignEvenement, Boucle Evenementielle
Procedure DesignUpdate()
  StartDrawing(CanvasOutput(#Design))
  
  ;Reset
  Box(0, 0, 800, 600, RGBA(255, 255, 255, 255))
  
  ;Dessin de l'image de fond
  DrawImage(ImageID(#BackGround), 0, 0)
  
  ;et des différents symboles ajoutés
  ForEach Elements()
    If Elements()\Actif = #True
      Select Elements()\Model
          
        Case 1 ;Dessin du symbole 1
          If Elements()\Status = #False
            Circle(Elements()\x+10, Elements()\y+10, (Elements()\Width)/2, RGB(255, 0, 0))
          Else
            Circle(Elements()\x+10, Elements()\y+10, (Elements()\Width)/2, RGB(0, 255, 0))
          EndIf
          DrawingMode(#PB_2DDrawing_Outlined)
          Circle(Elements()\x+10, Elements()\y+10, (Elements()\Width)/2, RGB(0, 0, 0))
          DrawingMode(#PB_2DDrawing_Default)
          
        Case 2 ;Dessin du symbole 2
          If Elements()\Status = #False
            Box(Elements()\x, Elements()\y, Elements()\Width, Elements()\height, RGB(220, 220, 220))
          Else
            Box(Elements()\x, Elements()\y, Elements()\Width, Elements()\height, RGB(0, 255, 0))
          EndIf
          DrawingMode(#PB_2DDrawing_Outlined)
          Box(Elements()\x, Elements()\y, Elements()\Width, Elements()\height, RGB(0, 0, 0))
          DrawingMode(#PB_2DDrawing_Default)

      EndSelect
    EndIf
  Next
  
  StopDrawing()
EndProcedure

;Ajout d'un symbole
;Appel : ExamineDesignEvenement(), Boucle evenementielle
Procedure ElementAdd(Model, x, y)
  AddElement(Elements())
  
  Select Model
    Case 1 ;Symbole 1
      Elements()\Actif = #True
      Elements()\Model = 1
      Elements()\Status = #False
      Elements()\x = x-10
      Elements()\y = y-10
      Elements()\Width = 20
      Elements()\height = 20
        
    Case 2 ;Symbole 2
      Elements()\Actif = #True
      Elements()\Model = 2
      Elements()\Status = #False
      Elements()\x = x
      Elements()\y = y
      Elements()\Width = 20
      Elements()\height = 20
  EndSelect
  
  DesignUpdate()
  
EndProcedure

;Evenements Canvas
;Appel : Boucle evenementielle
Procedure ExamineDesignEvenement(EventType) 

  ;Mémorisation des coordonnées de la souris sur le canvas
	MouseX = GetGadgetAttribute(#Design, #PB_Canvas_MouseX)
	MouseY = GetGadgetAttribute(#Design, #PB_Canvas_MouseY)
	
	;? Drag d'un model 
	If Model <>0
	  ElementAdd(Model, MouseX, MouseY)
	  Model=0
	EndIf
	
	;? Element survolé	
	ForEach Elements()
	  If LeftButtonDown = #False
	  If Elements()\Actif = #True
	    If MouseX > Elements()\x And MouseX < Elements()\x + Elements()\Width And
	       MouseY > Elements()\y And MouseY < Elements()\y + Elements()\height
	      *ActiveElement = @Elements()
	      SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Hand) 
 		    DeltaX=MouseX-*ActiveElement\x
		    DeltaY=MouseY-*ActiveElement\y

	      Break
	    Else
	      *ActiveElement = 0
	      SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Default)  
	    EndIf
	  EndIf  
	  EndIf 
	Next
	
	;? Evenement souris
	Select EventType
	    
	  Case #PB_EventType_RightButtonDown	;Appel du menu contextuel
	    SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Default)
	    LeftButtonDown = #False
	    
	    If *ActiveElement ;Un élément est survolé
	      DisableMenuItem(#PM, #PMDelete, #False)
	      DisableMenuItem(#PM, #PMOnOff, #False)
	      SetMenuItemState(#PM,#PMOnOff, *ActiveElement\Status)
	        
	    Else
	      DisableMenuItem(#PM, #PMDelete, #True)
	      DisableMenuItem(#PM, #PMOnOff, #True)
	      SetMenuItemState(#PM,#PMOnOff, #False)
	    EndIf
	    
	    DisplayPopupMenu(#PM, WindowID(#Mainform))	      
	    
	  Case 	#PB_EventType_LeftButtonUp
	    SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Default)	    
	    LeftButtonDown = #False
	    
	  Case 	#PB_EventType_LeftButtonDown
	    SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Cross)
	    LeftButtonDown = #True

	  Case #PB_EventType_MouseMove
	    If LeftButtonDown = #True
	      If *ActiveElement = 0
	        SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Cross)
	        StartDrawing(ImageOutput(#BackGround))
	        Circle(MouseX,MouseY, 2, RGB(128, 128, 128))
	        StopDrawing()
	      Else
	        SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Hand) 
	        *ActiveElement\x = MouseX-DeltaX
	        *ActiveElement\Y = MouseY-DeltaY
	      EndIf
	      DesignUpdate()
	    EndIf
	EndSelect
	
EndProcedure


;Fenetre de l'application
Procedure MainFormOpen()
  Protected Image.i
  
  OpenWindow(#Mainform, 0, 0, 800, 600, "Dessin et symbole", WindowStyle)
  
  ;Création des symboles sur le bord gauche de la fenetre
  ;Symbole 1
  CreateImage(#IMAGES1, 24, 24, 24, RGB(255, 255, 255))
  StartDrawing(ImageOutput(#IMAGES1))
  Circle(12, 12, 10, RGB(255, 0, 0))
  DrawingMode(#PB_2DDrawing_Outlined)
  Circle(12, 12, 10, RGB(0, 0, 0))
  StopDrawing()
  
  ImageGadget(#S1, 10, 10, 0, 0, ImageID(#IMAGES1))
  
  ;Symbole 2
  CreateImage(#IMAGES2, 24, 24, 24, RGB(255, 255, 255))
  StartDrawing(ImageOutput(#IMAGES2))
  Box(2, 2, 20, 20, RGB(220, 220, 220))
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(2, 2, 20, 20, RGB(220, 220, 220))
  StopDrawing()
  
  ImageGadget(#S2, 10, 40, 0, 0, ImageID(#IMAGES2))
  
  ;Design
  CanvasGadget(#Design, 45, 0, 755, 600)
  EnableGadgetDrop(#Design, #PB_Drop_Image, #PB_Drag_Copy)
  
  ;menu Contextuel
  If CreatePopupImageMenu(#PM)
    OpenSubMenu("Insérer un symbole")
    MenuItem(#PMS1, "Insérer Symbole 1")
    MenuItem(#PMS2, "Insérer Symbole 2")
      
    CloseSubMenu()
    MenuItem(#PMOnOff, "Actif")
    MenuItem(#PMDelete, "Supprimer le symbole")
  EndIf 
EndProcedure

Procedure Start()
  CreateImage(#BackGround, 800, 600)
  StartDrawing(ImageOutput(#BackGround))
  Box(0, 0, 800, 600, RGB(255, 255, 255))
  StopDrawing()
  
  MainFormOpen()
EndProcedure

start()
;-Boucle evenementielle
Repeat
  Event  = WaitWindowEvent(10)
  WEvent = EventWindow()
  MEvent = EventMenu()
  GEvent = EventGadget()
  TEvent = EventType()
  	
  Select Event
    Case #PB_Event_Menu
      Select MEvent
        Case #PMS1 ;Insertion du symbole 1
          ElementAdd(1, MouseX, MouseY)
          
        Case #PMS2 ;Insertion du symbole 2
          ElementAdd(2, MouseX, MouseY)
          
        Case #PMOnOff
          If GetMenuItemState(#PM, #PMOnOff) = #True
            *ActiveElement\Status = #False
          Else
            *ActiveElement\Status = #True
          EndIf
          DesignUpdate()
          
        Case #PMDelete
          *ActiveElement\Actif = #False
          DesignUpdate()
          
      EndSelect
              
    Case #PB_Event_Gadget
      If TEvent = #PB_EventType_DragStart
        Select EventGadget()
          Case #IMAGES1
            Model = 1            
            DragImage(ImageID(#IMAGES1))
          Case #IMAGES2
            Model = 2
            DragImage(ImageID(#IMAGES2))
        EndSelect
      EndIf

      Select GEvent          
        Case #Design          
          ExamineDesignEvenement(Tevent) 
        
      EndSelect
        
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Re: CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 17:58
par Golfy
@Ar-S: Tel que je comprend ton propos, un Canvas est en réalité une zone "transparente" ou "vide" qu'il faut meubler par une image ou un gadget ?
Dans ce cas,
1) je place mon plan en image de fond (pour le moment, c'est ce canvas qui réagit aux clics (et je détermine quel symbole est sous la souris à l'ancienne : if coordonnées à l'endroit où j'ai placé l'image, alors agir sur ce symbole)
2) je place mes images-symboles et créé la zone canvas de ce symbole au même endroit

Du coup, je n'ai des évènements que lorsque la souris survole un symbole ? (actuellement, évènement sur le plan complet).
@Falsam: je teste ton code tout de suite, merci :)

Re: CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 18:06
par Ar-S
Le code de falsam est top :wink:

Re: CanvasGadget et mise en oeuvre

Publié : jeu. 14/nov./2013 18:10
par Golfy
@Falsam: Ton code fait ce que je veux faire... mais comme je le fais actuellement avec la même boucle de test :

Code : Tout sélectionner

   ForEach Elements()
     If LeftButtonDown = #False
     If Elements()\Actif = #True
       If MouseX > Elements()\x And MouseX < Elements()\x + Elements()\Width And
          MouseY > Elements()\y And MouseY < Elements()\y + Elements()\height
         *ActiveElement = @Elements()
         SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Hand)
          DeltaX=MouseX-*ActiveElement\x
          DeltaY=MouseY-*ActiveElement\y

         Break
       Else
         *ActiveElement = 0
         SetGadgetAttribute(#Design, #PB_Canvas_Cursor, #PB_Cursor_Default) 
       EndIf
     EndIf 
     EndIf
   Next
J'espérais trouver un GEvent = EventGadget() qui correspondent directement à mon symbole (j'ai Element()\CanvasNumber dans ma structure)
Par contre, je ne gère pas encore le déplacement de symbole, ni le menu contextuel : Merci 1000 fois pour ces pistes Image