[ TUTO ] Construire une interface graphique

Informations pour bien débuter en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

[ TUTO ] Construire une interface graphique

Message par microdevweb »

On ma demandé en mp de l'aide pour construire une interface style SpeeDev, bien que je ne refuse pas mon aide en mp je trouve que cela doit profiter à tous le monde. Donc voici la première partie d'une interface similaire

Première partie
Le dessin d'une grille

Code : Tout sélectionner

; Name: DrawGrid
; Author: MicrodevWeb
EnableExplicit
Enumeration 
      #MainForm
      #MainCanvas
EndEnumeration
Global gGridSpace=10 ;L'espace entre les points
Global gGridColor=$2D52A0 ; La couleur du fond
Global gBgColor=$B3DEF5
Procedure Exit()
      End
EndProcedure
Procedure OpenMainForm()
      Protected Flag=#PB_Window_SystemMenu|#PB_Window_Maximize
      ; Ouverture de la fenêtre
      OpenWindow(#MainForm,0,0,800,600,"Dessin d'une grille",Flag)
      ; Création du canvas
      CanvasGadget(#MainCanvas,0,0,WindowWidth(#MainForm),WindowHeight(#MainForm))
      ; On place un Callback pour la fernmeture de la fenêtre
      BindEvent(#PB_Event_CloseWindow,@Exit(),#MainForm)
EndProcedure
Procedure DrawGrid()
      Protected X=gGridSpace,Y=gGridSpace
      ; Déplacement du point de la grille sur l'absice des X
      While X<GadgetWidth(#MainCanvas)
            Y=gGridSpace ; On redémare en haut
            While Y<GadgetHeight(#MainCanvas)
                  Plot(X,Y,gGridColor)
                  Y+gGridSpace ; On déplace le point sur Y
            Wend
            X+gGridSpace ; On déplace le point sur X
      Wend
EndProcedure
Procedure DrawCanvas()
      StartDrawing(CanvasOutput(#MainCanvas))
      ; Efface le canvas
      Box(0,0,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas),gBgColor)
      ; Dessin de la grille
      DrawGrid()
      StopDrawing()
EndProcedure
;-* Run programme
; --> les procédures qui seront lancées au lancement du programme
; On ouvre la fenêtre
; On Dessine le canvas
OpenMainForm()
DrawCanvas()
;}
;-* Main loop
; --> la boucle principale vide car je gère les événements avec le BindEvent etc...
Repeat :WaitWindowEvent():ForEver
;}
Dernière modification par microdevweb le jeu. 05/nov./2015 20:30, modifié 1 fois.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: [ TUTO ] Construire une interface graphique

Message par falsam »

On a du avoir la meme personne en mp :mrgreen:

PS : Que j'ai eu aussi sur FreeChat
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
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Deuxième partie
Mais ou suis-je? 8O

Au dessus de la procédure OpenMainForm() créez cette procédure (si vous la placer en dessous vous devrez la déclarer)

Code : Tout sélectionner

Procedure EventCanvas()
      Select EventType()
            Case #PB_EventType_MouseMove
                  ; Savoir ou l'on est ?
                  ; Je mémorise les position de la souris sur le canvas
                  gMouseX=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseX)
                  gMouseY=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseY)
                  WhereIsMouse()
            Case #PB_EventType_RightButtonDown
                  
            Case #PB_EventType_RightButtonUp
                  
      EndSelect
EndProcedure
N'oubliez pas également de créez les 2 variables globales en début de votre code (remarquez, petite astuce personnel je fais précédé mes variables globales d'un petit g :wink:

Code : Tout sélectionner

Global gMouseX,gMouseY
Au dessus de la procédure EventCanvas() que vous venez de créer, créez maintenant cette procédure

Code : Tout sélectionner

Procedure WhereIsMouse()
      Debug "Je suis à "+Str(gMouseX)+" en X et à "+Str(gMouseY)+" en Y"
EndProcedure
Ajouter ceci à la fin de votre procédure OpenMainForm()

Code : Tout sélectionner

 ; On place un Callback pour la gestion des evenement sur le canvas
      BindGadgetEvent(#MainCanvas,@EventCanvas())
Voila la suite prochainement ...
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Troisième partie
Et si on dessinait quelque chose ?

Dans cette partie on va commencer à implémenté notre partie de dessin, pour cela il faut savoir ou l'on démarre

Ajoutez cette structure ainsi que cette variable en début de code

Code : Tout sélectionner

Structure Pos
      X.i
      Y.i
EndStructure
Global gOldMouse.Pos
Nous allons également ajouté cette variable qui va nous permettre de savoir si le bouton gauche de souris est enfoncé ou pas

Code : Tout sélectionner

Global gClicOn.b=#False
Pour connaitre le type de dessin que utilisateur va faire (qui pourra être gérer par un menu ou autre) nous allons également ajouter ceci (avant les procédures)

Code : Tout sélectionner

Enumeration DrawMode
      #Select
      #DrawBox
EndEnumeration
Global gDrawMode=#DrawBox
Nous allons maintenant modifier la procédure EventCanvas()

Code : Tout sélectionner

Procedure EventCanvas()
      Select EventType()
            Case #PB_EventType_MouseMove
                  ; Savoir ou l'on est ?
                  ; Je mémorise les position de la souris sur le canvas
                  gMouseX=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseX)
                  gMouseY=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseY)
                  If Not gClicOn
                        WhereIsMouse()
                  Else
                        ManageDraw()
                  EndIf
            Case #PB_EventType_LeftButtonDown
                  If Not gClicOn
                        ; On mémorise la position de la souris pour le calcul du déplacement
                        gOldMouse\X=gMouseX
                        gOldMouse\Y=gMouseY
                  EndIf
                  gClicOn=#True ; Signale que l'on clique sur le bt gauche
            Case #PB_EventType_LeftButtonUp
                  gClicOn=#False ;Le bt gauche est relaché
      EndSelect
EndProcedure
Nous allons également ajouter cette procédure au dessus de EventCanvas()

Code : Tout sélectionner

Procedure ManageDraw()
      ;On calcul le déplacement
      Protected DisplacX=gMouseX-gOldMouse\X
      Protected DisplacY=gMouseY-gOldMouse\Y
      Select gDrawMode
            Case #DrawBox  
                  Debug "vous de déplacer de "+Str(DisplacX)+" pixels sur X"
                  Debug "vous de déplacer de "+Str(DisplacY)+" pixels sur Y"
      EndSelect
EndProcedure
Testez et normalement quant vous déplacez la souris vous devriez avoir la distance de déplacement sur les deux axes

Note: Je sais que je vous donne le code en pièce, mais le but de ce tuto n'est pas de faire un simple copier coller mais bien vous expliquer le raisonnement pour arriver à ses fins. Par après il vous sera facile de faire la même chose. Je vous fournirais évidement l'intégralité du code en fin de tuto :wink:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

@Falsam,

Surement :wink: mais je suis gentils donc je partage :mrgreen:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Quatrième parties
Et si on dessinais quelque chose (suite)

Il va s'agir de dessin de type vectoriel donc on va mémoriser tout cela, pour ce faire ajoutez ces 2 structures ainsi que cette liste chainée.

Code : Tout sélectionner

Structure PosAndSize Extends Pos
      W.i
      H.i
EndStructure
Structure Draw
      List myBox.PosAndSize()
EndStructure
Global newList myDraw.Draw()
Bon maintenant on va afficher une simulation du rectangle qui va être dessiné, mais pour ce faire on légèrement modifier notre code. Plutôt que de dessiner directement dans notre Canvas on va dessiner dans une image temporaire que nous allons d'ailleurs tout de suite créer

Code : Tout sélectionner

Global gTmpImg
Et dans le code de la procédure OpenMainForm() après la création du canvas

Code : Tout sélectionner

 gTmpImg=CreateImage(#PB_Any,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas))
Je vais maintenant créer une nouvelle procédure, et déplacer mon code de DrawCanvas() dans cette nouvelle procédure, je modifie maintenant également le StartDrawing

Code : Tout sélectionner

Procedure DrawTmpImg()
      StartDrawing(ImageOutput(gTmpImg))
      ; Efface l'image
      Box(0,0,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas),gBgColor)
      ; Dessin de la grille
      DrawGrid()
      StopDrawing()
EndProcedure
Je modifie aussi le code de DrawCanvas()

Code : Tout sélectionner

Procedure DrawCanvas()
       DrawTmpImg()
      StartDrawing(CanvasOutput(#MainCanvas))
      ; Dessin de l'image temporaire
      DrawImage(ImageID(gTmpImg),0,0)
      StopDrawing()
EndProcedure
Je teste enfin pour être certain que tout fonctionne comme avant :roll: Oufff, ça fonctionne

Bon je vais mémoriser temporairement mon dessin, j'ajoute une nouvelle variable (en début de code)

Code : Tout sélectionner

Global gTmpDraw.PosAndSize
Et je modifie ma procédure ManageDraw()

Code : Tout sélectionner

Procedure ManageDraw()
      ;On calcul le déplacement
      Protected DisplacX=gMouseX-gOldMouse\X
      Protected DisplacY=gMouseY-gOldMouse\Y
      Select gDrawMode
            Case #DrawBox  
                  gTmpDraw\X=gOldMouse\X
                  gTmpDraw\Y=gOldMouse\Y
                  gTmpDraw\W=DisplacX
                  gTmpDraw\H=DisplacY
                  DrawPrevBox()
      EndSelect
EndProcedure
Bon je vais ajouter une procédure avant ManageDraw() c'est la procédure qui va dessiner la vue du futur rectangle (je vais utiliser la nouvelle libraire de Pb 5.40 VectorDrawing)

Code : Tout sélectionner

StartVectorDrawing(CanvasVectorOutput(#MainCanvas))
      ; J'efface en premier le canvas, avec l'image temporaire
      MovePathCursor(0,0)
      DrawVectorImage(ImageID(gTmpImg))
      ; Je dessine maintenant le box
      With gTmpDraw
            AddPathBox(\X,\Y,\W,\H)
            ; ATTENTION couleur RGBA donc avec alpha
            VectorSourceColor(RGBA(0, 255, 127, 255))
            DotPath(2,8)
      EndWith
      StopVectorDrawing()
Testez, maintenez le clic gauche et déplacez la souris normalement vous devriez voir un rectangle vert en pointillés
:arrow: ATTENTION: Vous devez tester avec Pb 5.40

Bon voila c'est fini pour cette partie dans la partie suivante , on va sauver tout ça et dessiner notre rectangle
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Cinquième partie
Et si on dessinais quelque chose (suite)

Bon on vas sauver la position de notre rectangle, mais quand :?:

Hum à votre avis, ben lorsque l'utilisateur relâche le bouton de la souris

Bon pour ça, il faut aussi que je sache s'il y a eu un rectangle d'ajouter :?: je vais donc ajouter un flag
Ajoutez cette variable

Code : Tout sélectionner

Global gNewDraw.b=#False
Et modifier le code de ManageDraw()

Code : Tout sélectionner

Procedure ManageDraw()
      ;On calcul le déplacement
      Protected DisplacX=gMouseX-gOldMouse\X
      Protected DisplacY=gMouseY-gOldMouse\Y
      Select gDrawMode
            Case #DrawBox  
                  gTmpDraw\X=gOldMouse\X
                  gTmpDraw\Y=gOldMouse\Y
                  gTmpDraw\W=DisplacX
                  gTmpDraw\H=DisplacY
                  DrawPrevBox()
      EndSelect
      gNewDraw=#True
EndProcedure
Ainsi que le code de EventCanvas()

Code : Tout sélectionner

Case #PB_EventType_LeftButtonUp
                  If gNewDraw
                        Select gDrawMode
                              Case #DrawBox
                                    AddNewBox()
                        EndSelect
                  EndIf
                  gNewDraw=#False
                  gClicOn=#False ;Le bt gauche est relaché
Je crois que l'aurez maintenant deviner, on va ajouter une procédure :roll:

Code : Tout sélectionner

Procedure AddNewBox()
      AddElement(myDraw())
      AddElement(myDraw()\myBox())
      With myDraw()\myBox()
            \X=gTmpDraw\X
            \Y=gTmpDraw\Y
            \W=gTmpDraw\W
            \H=gTmpDraw\H
      EndWith
      DrawCanvas()
EndProcedure
Et on va également déclarer en début de code la procédure DrawCanvas()

Code : Tout sélectionner

Declare DrawCanvas()
Bon très joli tout ça, mais je ne voie rien à l'écran :twisted:

Ben oui, on a encore rien fais pour dessiner nos objet, mais il existent en mémoire simplement.

Donc on vas .......... Et oui vous avez deviné créer une procédure avant DrawTmpImg() (bon en vérité on vas en faire deux dans le cas ou vous voulez dessiner autre chose que des rectangles

Code : Tout sélectionner

Procedure DrawBox()
      With myDraw()\myBox()
            Box(\X,\Y,\W,\H,RGB(255, 0, 0))
      EndWith
EndProcedure
Procedure DrawOblect()
      ForEach myDraw()
            With myDraw()
                  ForEach \myBox()
                        DrawBox()
                  Next
            EndWith
      Next
EndProcedure 
Maintenant juste une petite modification à DrawTmpImg()

Code : Tout sélectionner

Procedure DrawTmpImg()
      StartDrawing(ImageOutput(gTmpImg))
      ; Efface l'image
      Box(0,0,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas),gBgColor)
      ; Dessin de la grille
      DrawGrid()
      DrawOblect() ; Dessine nos objets
      StopDrawing()
EndProcedure
Voila si vous testez maintenant, vous dessinerez des magnifiques rectangles rouge :P

Prochaine partie modifier tout la taille, la position de nos rectangles
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Partie 6
Sur quel objet ?
Et oui pour la suite il est important de savoir sur quel objet je suis......

On vas ajouter deux variables une de type mémoire qui va mémoriser l'adresse de mon rectangle, et une autre pour connaitre de type d'objet (n'oublions pas que même si pour ce tuto je n'utiliserais que des rectangles on pourrait en avoir d'autres)

Code : Tout sélectionner

Global gTypeObjet
Global *gCurrentObjet
Vous vous souvenez de WhereIsMouse(), ben c'est maintenant que l'on va vraiment s'en servir

Et hop on le modifie

Code : Tout sélectionner

Procedure WhereIsMouse()
      ; On est sur un objet
      ItsHoverObject()
EndProcedure
Quoi encore une procédure ... :x

Ben oui ... J'aime ça moi les procédures :oops:

Code : Tout sélectionner

Procedure ItsHoverObject()
      ; On est sur rien
      *gCurrentObjet=-1
      gTypeObjet=-1
      ForEach myDraw()
            ForEach myDraw()\myBox()
                  With myDraw()\myBox()
                        If (gMouseX>=\X And gMouseX<=(\X+\W)) And (gMouseY>=\Y And gMouseY<=(\Y+\H))
                              *gCurrentObjet=@myDraw()\myBox()
                              gTypeObjet=#DrawBox
                              ProcedureReturn #True
                        EndIf
                  EndWith
            Next
      Next
      ProcedureReturn #False
EndProcedure
Bon un petit mot d'explication, au départ je ne suis sur rien donc je place

Code : Tout sélectionner

*gCurrentObjet=-1
 gTypeObjet=-1
Je regarde ensuite pour chaque rectangle si ma souris est dessus

Code : Tout sélectionner

If (gMouseX>=\X And gMouseX<=(\X+\W)) And (gMouseY>=\Y And gMouseY<=(\Y+\H))
Si oui je mémorise l'objet et le type d'objet, et je signale que je suis sur quelque chose

Code : Tout sélectionner

*gCurrentObjet=@myDraw()\myBox()
 gTypeObjet=#DrawBox
 ProcedureReturn #True
Et si on changeait le type de curseur de souris :?: Ce serait bien non ?

Aller faisons ça...

Code : Tout sélectionner

Procedure WhereIsMouse()
      ; On est sur un objet
      If ItsHoverObject()
            SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Hand)
            ProcedureReturn 
      EndIf
      SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Default)
EndProcedure
Voila testez, dessinez, survolez ...

A bientôt pour la suite :wink:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Shadow
Messages : 1373
Inscription : mer. 04/nov./2015 17:39

Re: [ TUTO ] Construire une interface graphique

Message par Shadow »

Salut,

Super tuto Microdevweb ! :D
Je me suis amusé à le refaire à ma sauce pour voir, tous fonctionne bien...

Du moins, jusqu'au 5 pour moi, après, au 6, j'ai des problèmes, parfois le pointeur de la souris n'est pas changé
quand je passe sur un Box, je ne comprends pas le problème, j'ai eu beau cherché... :roll:

J'ai remarqué que ça le faisait lorsque je créer un Box à proximité d'un autre.

Une idée d’où cela pourrait provenir ?
Est-ce que toi tous fonctionne ?

Code : Tout sélectionner

EnableExplicit

Enumeration
  #FenetrePrincipale
  #CanvasGrille
  #BarreStatue
EndEnumeration

Enumeration DrawMode
  #Select
  #DrawBox
EndEnumeration

Structure PositionSouris
  X.i
  Y.i
EndStructure

Structure PositionEtTaille Extends PositionSouris
  L.i
  H.i
EndStructure

Structure Draw
  List MyBox.PositionEtTaille()
EndStructure

Global Souris.PositionSouris
Global NewList MyDraw.Draw()

Global FenetrePrincipaleLargeur.i = 800 ; La Largeur de la fenêtre.
Global FenetrePrincipaleHauteur.i = 600 ; La Hauteur de la fenêtre.

Global CanvasGrilleLargeur.i = FenetrePrincipaleLargeur.i ; La Largeur de la grille.
Global CanvasGrilleHauteur.i = FenetrePrincipaleHauteur.i - 23 ; La Hauteur de la grille (-23 pour la barre de statue).
Global CanvasGrilleEspacePoint.i = 10 ; L'espace entre les points.
Global CanvasGrilleCouleurPoint.i = RGB(0, 0, 255) ; La couleur des points.
Global CanvasGrilleCouleurArrierePlant.i = RGB(255, 255, 255) ; La couleur d'arrière plant de la grille.

Global CanvasSelectionTaille.i = 2 ; Taille de la selection.
Global CanvasTypeSelection.i = #PB_Path_SquareEnd ; #PB_Path_RoundEnd = Trace des points ronds, #PB_Path_SquareEnd: Trace des points carrés.
Global CanvasSelectionCouleurPoint.i = RGBA(255, 0, 0, 255) ; La couleur de la selection.
Global CanvasSelectionEspacement.i = 4 ; La distance entre les point de la selection.

Global CanvasPositionXsouris.i = 0
Global CanvasPositionYsouris.i = 0

Global CanvasCliqueSouris.b = #False
Global CanvasDrawMode.i = #DrawBox

Global CouleurBox.i = RGB(0, 0, 255)

Global ImageTemps.i = 0
Global TempsDraw.PositionEtTaille

Global NewDraw.b = #False

Global TypeObjet.i
Global *ObjetCourrent

Declare Exit()
Declare EventCanvas()
Declare WhereIsMouse()
Declare ManageDraw()
Declare DrawImageTemps()
Declare DrawSelection()
Declare AddNewBox()
Declare DrawOblect() 
Declare ItsHoverObject()

Procedure FenetrePrincipale()
  
  Protected OptionFenetre.i = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered
  
  ; Ouverture de la fenêtre.
  OpenWindow(#FenetrePrincipale, 0, 0, FenetrePrincipaleLargeur, FenetrePrincipaleHauteur, "Déssin d'une grille...", OptionFenetre.i)
  
  ; Création du canvas.
  CanvasGadget(#CanvasGrille, 0, 0, CanvasGrilleLargeur.i, CanvasGrilleHauteur.i)
  
  ; Création de l'image temps
  ImageTemps.i = CreateImage(#PB_Any, GadgetWidth(#CanvasGrille), GadgetHeight(#CanvasGrille))
  
  ; Création de la barre de statue.
  CreateStatusBar(#BarreStatue, WindowID(#FenetrePrincipale))
  AddStatusBarField(#PB_Ignore)
  AddStatusBarField(#PB_Ignore)
  AddStatusBarField(#PB_Ignore)
  AddStatusBarField(#PB_Ignore)
  
  ; On place un Callback pour la fernmeture de la fenêtre.
  BindEvent(#PB_Event_CloseWindow, @Exit(), #FenetrePrincipale)
  
  ; On place un Callback pour la gestion des evenements sur le canvas.
  BindGadgetEvent(#CanvasGrille, @EventCanvas())
  
EndProcedure

Procedure EventCanvas()
  
  Select EventType()
      
    Case #PB_EventType_MouseMove ; La souris bouge sur le Canvas.
      
      ; Savoir ou l'on est sur la Canvas...
      ; Mémorise la position de la souris sur le canvas.
      CanvasPositionXsouris.i = GetGadgetAttribute(#CanvasGrille, #PB_Canvas_MouseX)
      CanvasPositionYsouris.i = GetGadgetAttribute(#CanvasGrille, #PB_Canvas_MouseY)
      
      If CanvasCliqueSouris.b = #False ; Le bouton gauche de la souris n'est pas appuyé.
        WhereIsMouse()
        
      Else ; Le bouton gauche de la souris est appuyé.
        ManageDraw()
        
      EndIf
      
    Case #PB_EventType_LeftButtonDown ; Le bouton gauche de la souris est appuyé.
      
      If CanvasCliqueSouris.b = #False ; Le bouton gauche de la souris n'est pas appuyé.
        ; On mémorise la position de la souris pour le calcul du déplacement.
        Souris\X.i = CanvasPositionXsouris.i
        Souris\Y.i = CanvasPositionYsouris.i
      EndIf
      
      CanvasCliqueSouris.b = #True ; Signale que l'on à cliqué sur le bouton gauche de la souris.
      
    Case #PB_EventType_LeftButtonUp ; Le bouton gauche de la souris à été relâché.
      
      StatusBarText(#BarreStatue, 1, "L = 0, H = 0", #PB_StatusBar_Raised)
      
      If NewDraw.b = #True
        
        Select CanvasDrawMode.i
            
          Case #DrawBox
            AddNewBox()
            
        EndSelect
        
      EndIf
      
      NewDraw.b = #True
      CanvasCliqueSouris.b = #False ; Signale que l'on à relâché le bouton gauche de la souris.
      
  EndSelect
  
EndProcedure

Procedure DrawCanvas()
  
  ; Ont déssine l'image temporaire.
  DrawImageTemps()
  
  StartDrawing(CanvasOutput(#CanvasGrille))
  
  ; Dessin de l'image temporaire sur la Canvas.
  DrawImage(ImageID(ImageTemps.i), 0, 0)
  
  StopDrawing()
  
EndProcedure

Procedure DrawGrid()
  
  Protected X.i = CanvasGrilleEspacePoint.i, Y.i = CanvasGrilleEspacePoint.i
  
  ; Boucle tans que X est plus petit que la Largeur de la fenêtre.
  While X.i < GadgetWidth(#CanvasGrille)
    
    Y.i = CanvasGrilleEspacePoint.i ; Ont revient à la position Y par du début.
    
    ; Boucle tans que Y est plus petit que la Hauteur de la fenêtre.
    While Y.i < GadgetHeight(#CanvasGrille) 
      Plot(X.i ,Y.i , CanvasGrilleCouleurPoint.i) ; Déssine le point sur le Canvas Gadjet.
      Y.i + CanvasGrilleEspacePoint.i             ; On déplace le la position de Y.
    Wend
    
    X.i + CanvasGrilleEspacePoint.i ; On déplace le la position de X.
    
  Wend
  
EndProcedure

Procedure WhereIsMouse()
  
  StatusBarText(#BarreStatue, 0, "X = " + Str(CanvasPositionXsouris.i) + ", Y = " + Str(CanvasPositionYsouris.i), #PB_StatusBar_Raised)
  
  ; On est sur un objet
  If ItsHoverObject()
    SetGadgetAttribute(#CanvasGrille, #PB_Canvas_Cursor, #PB_Cursor_Hand)
    ProcedureReturn
  EndIf
  
  SetGadgetAttribute(#CanvasGrille, #PB_Canvas_Cursor, #PB_Cursor_Default)
  
EndProcedure

Procedure ManageDraw()
  
  ; On calcul le déplacement de la souris.
  Protected CanvasDesplacementX.i = CanvasPositionXsouris.i - Souris\X
  Protected CanvasDesplacementY.i = CanvasPositionYsouris.i - Souris\Y
  
  Select CanvasDrawMode.i
      
    Case #DrawBox
      
      StatusBarText(#BarreStatue, 0, "X = " + Str(CanvasPositionXsouris.i) + ", Y = " + Str(CanvasPositionYsouris.i), #PB_StatusBar_Raised)
      StatusBarText(#BarreStatue, 1, "L = " + Str(CanvasDesplacementX.i) + ", H = " + Str(CanvasDesplacementY.i), #PB_StatusBar_Raised)
      
      ; Enregistre la position actuel de la souris.
      TempsDraw\X = Souris\X
      TempsDraw\Y = Souris\Y
      
      ; Enregistre la taille de la selection.
      TempsDraw\L = CanvasDesplacementX.i
      TempsDraw\H = CanvasDesplacementY.i
      
      ; Déssine la selection sur le Canvas.
      DrawSelection()
      
  EndSelect
  
  NewDraw.b = #True
  
EndProcedure

Procedure DrawImageTemps()
  
  ; Ont déssine sur l'image temporaire.
  StartDrawing(ImageOutput(ImageTemps.i))
  
  ; Efface l'image avec la couleur d'arriere plant du Canvas.
  Box(0 ,0 , GadgetWidth(#CanvasGrille), GadgetHeight(#CanvasGrille), CanvasGrilleCouleurArrierePlant.i)
  
  ; Dessinne la grille sur l'image.
  DrawGrid()
  
  ; Dessine nos objets.
  DrawOblect() 
  
  StopDrawing()
  
EndProcedure

Procedure DrawSelection()
  
  ; J'efface en premier le canvas, avec l'image temporaire...
  StartVectorDrawing(CanvasVectorOutput(#CanvasGrille))
  
  ; Déplace le curseur du chemin de dessin vectoriel vers un nouvel emplacement.
  MovePathCursor(0, 0)
  
  ; Dessine l'image spécifiée directement sur la sortie de dessin vectoriel.
  DrawVectorImage(ImageID(ImageTemps.i))
  
  ; Déessine maintenant le box (La selection).
  With TempsDraw
    
    ; Ajoute un rectangle (Box ou Boîte) dans le chemin du dessin vectoriel.
    AddPathBox(\X,\Y,\L,\H)
    
    ; Sélectionne une seule couleur 32 bits comme source pour les opérations de dessin vectoriel telles que FillPath(), StrokePath() et autres. 
    ; ATTENTION couleur RGBA donc avec alpha !
    VectorSourceColor(CanvasSelectionCouleurPoint.i)
    
    ; Dessine le chemin de dessin courant avec une ligne de points.
    DotPath(CanvasSelectionTaille.i, CanvasSelectionEspacement.i, CanvasTypeSelection.i) ; Largeur, Distance, Type.

  EndWith
  
  StopVectorDrawing()
  
EndProcedure

Procedure AddNewBox()
  
  AddElement(MyDraw())
  AddElement(MyDraw()\MyBox())
  
  With MyDraw()\MyBox()
    \X = TempsDraw\X
    \Y = TempsDraw\Y
    \L = TempsDraw\L
    \H = TempsDraw\H
  EndWith
  
  DrawCanvas()
  
EndProcedure

Procedure DrawBox()
  With MyDraw()\MyBox()
    Box(\X,\Y,\L,\H, CouleurBox.i)
  EndWith
EndProcedure

Procedure DrawOblect()
  ForEach MyDraw()
    With MyDraw()
      ForEach \MyBox()
        DrawBox()
      Next
    EndWith
  Next
EndProcedure 

Procedure ItsHoverObject()
  
  ; On est sur rien
  *ObjetCourrent = -1
  TypeObjet = -1
  
  ForEach MyDraw()
    ForEach MyDraw()\MyBox()
      With MyDraw()\MyBox()
        If (CanvasPositionXsouris.i >= \X And CanvasPositionXsouris.i <= (\X + \L)) And (CanvasPositionYsouris.i >= \Y And CanvasPositionYsouris.i <= (\Y + \H))
          *ObjetCourrent = @MyDraw()\MyBox()
          TypeObjet.i = #DrawBox
          ProcedureReturn #True
        EndIf
      EndWith
    Next
  Next
  
  ProcedureReturn #False
  
EndProcedure

Procedure Exit()
  End
EndProcedure

; On ouvre la fenêtre.
FenetrePrincipale()

; On Dessine le canvas.
DrawCanvas()

; La boucle principale vide car ont gère les événements avec le BindEvent etc...
Repeat
  WaitWindowEvent()
ForEver
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Salut Shadow,

A première vue ton code fonctionne, évidement mon tuto n'est pas fini. Car la on est qu'en mode dessin alors que l'on devrait être en mode dessin ou sélection. Ceci est la suite du tuto, mais je te félicite pour ta compréhension car avec ça tu peut tout faire avec un canvas il a vraiment peux de limite.

Note: tu peu faire un débug de ta variable *ObjetCourrent avant ProcedureReturn #True et ProcedureReturn #False et tu constatera que tu repère bien l'objet sur lequel tu est :wink:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Partie 7
Dessinons des poignées

Pour suivre cette partie, ils faut différencier le mode de dessin d'objet et le mode de sélection. Je ne vais pas dans le cadre de ce tuto créer un menu mais je vais ajouter deux raccourcis clavier A je serais en mode dessin d'objet E je serais en mode édition

Ajouter ceci à OpenMainForm()

Code : Tout sélectionner

; Ajout de raccourcis clavier,/Add keyboard shorcut
 AddKeyboardShortcut(#MainForm,#PB_Shortcut_A,0)
 AddKeyboardShortcut(#MainForm,#PB_Shortcut_E,1)
 BindEvent(#PB_Event_Menu,@ChangeModeDraw(),#MainForm)
Et on ajoute également cette procédure avant OpenMainForm()

Code : Tout sélectionner

Procedure ChangeModeDraw()
      Select EventMenu()
            Case 0 ;Mode ajout d'objet/Add object mode
                  gDrawMode=#DrawBox
            Case 1 ;Mode édition / Edit mode
                  gDrawMode=#Select
      EndSelect
EndProcedure
Et pour le signaler à l'utilisateur je vais légèrement modifier mon code EventCanvas()

Code : Tout sélectionner

Procedure EventCanvas()
      Select EventType()
            Case #PB_EventType_MouseMove
                  ; Savoir ou l'on est ?
                  ; Je mémorise les position de la souris sur le canvas
                  gMouseX=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseX)
                  gMouseY=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseY)
                  If Not gClicOn And gDrawMode=#Select
                       If WhereIsMouse():ProcedureReturn :EndIf
                  ElseIf gClicOn And gDrawMode<>#Select
                        ManageDraw()
                  EndIf
            Case #PB_EventType_LeftButtonDown
                  If Not gClicOn
                        ; On mémorise la position de la souris pour le calcul du déplacement
                        gOldMouse\X=gMouseX
                        gOldMouse\Y=gMouseY
                  EndIf
                  gClicOn=#True ; Signale que l'on clique sur le bt gauche
            Case #PB_EventType_LeftButtonUp
                  If gNewDraw
                        Select gDrawMode
                              Case #DrawBox
                                    AddNewBox()
                        EndSelect
                  EndIf
                  gNewDraw=#False
                  gClicOn=#False ;Le bt gauche est relaché
      EndSelect
      Select gDrawMode
            Case #DrawBox
                  SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Cross) 
            Case #Select
                  SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Default) 
      EndSelect
EndProcedure
Nous modifierons aussi WhereIsMouse()

Code : Tout sélectionner

Procedure WhereIsMouse()
      ; On est sur un objet / we are under object
      If ItsHoverObject()
            SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Hand)
            ProcedureReturn #True
      EndIf
      ProcedureReturn #False
EndProcedure
On va maintenant attaquer le dessin des poignée, et pour leur gestion future on va ajouter une Enumeration

Code : Tout sélectionner

Enumeration Handles
      #LU ;Gauche en haut /Left Up
      #RU ;Droite en haut /Rigth Up
      #MU ;Milieur en haut /midle Up
      #LD ;Gauche en bas /Left Down
      #RD ;Droite en bas /Rigth Down
      #MD ;Milieur en bas /midle Down
      #LM ; Gauche milieu /Left midle
      #RM ; Droite milieu /Right midle
EndEnumeration
Ainsi que cette map

Code : Tout sélectionner

Global NewMap myHandle.Pos()
; On crée les map
Define N
For N=0 To #RM
      AddMapElement(myHandle(),Str(N))
Next
Pour savoir quel objet est sélectionner on va ajouté cette variable

Code : Tout sélectionner

Global *gObjectSelected
On modifie également EventCanvas() (ben oui c'est ça la programmation on teste on réfléchi, on modifie)

Code : Tout sélectionner

    Case #PB_EventType_LeftButtonDown
                  If Not gClicOn
                        ; On mémorise la position de la souris pour le calcul du déplacement
                        gOldMouse\X=gMouseX
                        gOldMouse\Y=gMouseY
                        ; Aucun objet sélectionner/No object selected
                        *gObjectSelected=-1
                  EndIf
                  gClicOn=#True ; Signale que l'on clique sur le bt gauche
    Case #PB_EventType_LeftButtonUp
                  If gNewDraw
                        Select gDrawMode
                              Case #DrawBox
                                    AddNewBox()
                        EndSelect
                  ElseIf gDrawMode=#Select And *gCurrentObjet<>-1
                        *gObjectSelected=*gCurrentObjet
                         DrawCanvas()
                  EndIf
                  gNewDraw=#False
                  gClicOn=#False ;Le bt gauche est relaché
EndSelect
On ajoute ces 2 variables

Code : Tout sélectionner

Global gHandleSize=8,gHandleColor=$696969
On ajoute maintenant cette procédure avant DrawOblect()

Code : Tout sélectionner

Procedure DrawHandles()
      Protected X,Y
      If @myDraw()\myBox()<>*gObjectSelected
            ProcedureReturn 
      EndIf
      With myDraw()\myBox()
            Y=\Y-(gHandleSize/2)
            ; Poignée/Handle LU
            X=\X-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#LU))\X=X
            myHandle(Str(#LU))\Y=Y
            ; Poignée/Handle RU
            X=(\X+\W)-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#RU))\X=X
            myHandle(Str(#RU))\Y=Y
            ; Poignée/Handle MU
            X=(\X+(\W/2))-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#MU))\X=X
            myHandle(Str(#MU))\Y=Y
             Y=(\Y+\H)-(gHandleSize/2)
            ; Poignée/Handle LD
            X=\X-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#LD))\X=X
            myHandle(Str(#LD))\Y=Y
            ; Poignée/Handle RD
            X=(\X+\W)-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#RD))\X=X
            myHandle(Str(#RD))\Y=Y
            ; Poignée/Handle MD
            X=(\X+(\W/2))-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#MD))\X=X
             myHandle(Str(#MD))\Y=Y
             
             Y=(\Y+(\H/2))-(gHandleSize/2)
             X=\X-(gHandleSize/2)
             Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#LM))\X=X
             myHandle(Str(#LM))\Y=Y
             X=(\X+\W)-(gHandleSize/2)
             Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#RM))\X=X
             myHandle(Str(#RM))\Y=Y
      EndWith
EndProcedure
Et on modifie DrawOblect()

Code : Tout sélectionner

Procedure DrawOblect()
      ForEach myDraw()
            With myDraw()
                  ForEach \myBox()
                        DrawBox()
                        DrawHandles()
                  Next
            EndWith
      Next
EndProcedure 
Voila testez, dessinez des rectangle tapez E pour passer en mode édition et cliquer sur un rectangle
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Shadow
Messages : 1373
Inscription : mer. 04/nov./2015 17:39

Re: [ TUTO ] Construire une interface graphique

Message par Shadow »

microdevweb a écrit :Salut Shadow,

A première vue ton code fonctionne, évidement mon tuto n'est pas fini. Car la on est qu'en mode dessin alors que l'on devrait être en mode dessin ou sélection. Ceci est la suite du tuto, mais je te félicite pour ta compréhension car avec ça tu peut tout faire avec un canvas il a vraiment peux de limite.

Note: tu peu faire un débug de ta variable *ObjetCourrent avant ProcedureReturn #True et ProcedureReturn #False et tu constatera que tu repère bien l'objet sur lequel tu est :wink:
Bonjour Microdevweb,

Justement, j'ai essayé, et non, ça ne fonctionne pas toujours, regarde:
Avec mon code créer un Box en haut, ici tous fonctionne !

Maintenant créer un Box en dessous du premier (Attention nuance ici):
Si tu créer le box en partant du haut (A proximité du premier) et en descendent, ici tous fonctionne !
Si tu créer le box en partant du bas et en montent et en t’arrêtant pas loin de celui du haut, ici ça ne fonctionne plus !

Essaie divers combinaison, de plus quand un Box est sur un autre, il y à aussi problème ici !
Maintenant essaie avec ton code et dis moi si tu rencontre les même soucis que moi ;)

Bref, je vais continuer, ont verra bien si ce problème est résolut par la suite !
Merci pour t'es encouragements, ça fait plaisir !

Edit: ça y est je viens de comprendre la chose !
En faite ça ne fonctionne pas si tu créer le box depuis le bas ou depuis la droite, peut importe le box
ou la position de celui-ci, problème avec les nombre négatif je suppose !
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

c'est possible, il suffit de faire une teste
exemple:

edit

Code : Tout sélectionner

Procedure ManageDraw()
      ;On calcul le déplacement
      Protected DisplacX=gMouseX-gOldMouse\X
      Protected DisplacY=gMouseY-gOldMouse\Y
      Select gDrawMode
            Case #DrawBox  
                  If gMouseX>GadgetWidth(#MainCanvas)
                        ProcedureReturn 
                  EndIf
                  If gMouseX<0
                        ProcedureReturn 
                  EndIf
                  If gMouseY>GadgetHeight(#MainCanvas)
                        ProcedureReturn 
                  EndIf
                  If gMouseY<0
                        ProcedureReturn 
                  EndIf
                  gTmpDraw\X=gOldMouse\X
                  gTmpDraw\Y=gOldMouse\Y
                  gTmpDraw\W=DisplacX
                  gTmpDraw\H=DisplacY
                  DrawPrevBox()
      EndSelect
      gNewDraw=#True
EndProcedure
Procedure AddNewBox()
      AddElement(myDraw())
      AddElement(myDraw()\myBox())
      With myDraw()\myBox()
            \X=gTmpDraw\X
            \Y=gTmpDraw\Y
            \W=gTmpDraw\W
            \H=gTmpDraw\H
      EndWith
      DrawCanvas()
EndProcedure
Ce tuto ne reprend évidement pas toutes les possibilités, il serait trop long et deviendrait complexe à comprendre
(désolé mais actuellement j'ai pas trop le temps pour m'étendre sur tous les détails)
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Shadow
Messages : 1373
Inscription : mer. 04/nov./2015 17:39

Re: [ TUTO ] Construire une interface graphique

Message par Shadow »

Re, merci ça fonctionne là.
Dernière modification par Shadow le ven. 06/nov./2015 12:55, modifié 1 fois.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [ TUTO ] Construire une interface graphique

Message par microdevweb »

Voila tous le code (actuel)

Code : Tout sélectionner

; Name: DrawGrid
; Author: MicrodevWeb
EnableExplicit
Enumeration 
      #MainForm
      #MainCanvas
EndEnumeration
Enumeration DrawMode
      #Select
      #DrawBox
EndEnumeration
Enumeration Handles
      #LU ;Gauche en haut /Left Up
      #RU ;Droite en haut /Rigth Up
      #MU ;Milieur en haut /midle Up
      #LD ;Gauche en bas /Left Down
      #RD ;Droite en bas /Rigth Down
      #MD ;Milieur en bas /midle Down
      #LM ; Gauche milieu /Left midle
      #RM ; Droite milieu /Right midle
EndEnumeration
Global gDrawMode=#DrawBox
Global gGridSpace=10 ;L'espace entre les points
Global gGridColor=$2D52A0 ; La couleur du fond
Global gBgColor=$B3DEF5
Global gMouseX,gMouseY
Global gNewDraw.b=#False
Structure Pos
      X.i
      Y.i
EndStructure
Structure PosAndSize Extends Pos
      W.i
      H.i
EndStructure
Structure Draw
      List myBox.PosAndSize()
EndStructure
Global NewList myDraw.Draw()
Global gOldMouse.Pos
Global gTmpDraw.PosAndSize
Global NewMap myHandle.Pos()
; On crée les map
Define N
For N=0 To #RM
      AddMapElement(myHandle(),Str(N))
Next
Global gClicOn.b=#False
Global gTmpImg
Global gTypeObjet
Global *gCurrentObjet
Global *gObjectSelected
Global gHandleSize=8,gHandleColor=$696969
Declare DrawCanvas()
Procedure Exit()
      End
EndProcedure
Procedure ItsHoverObject()
      ; On est sur rien
      *gCurrentObjet=-1
      gTypeObjet=-1
      ForEach myDraw()
            ForEach myDraw()\myBox()
                  With myDraw()\myBox()
                        If (gMouseX>=\X And gMouseX<=(\X+\W)) And (gMouseY>=\Y And gMouseY<=(\Y+\H))
                              *gCurrentObjet=@myDraw()\myBox()
                              gTypeObjet=#DrawBox
                              ProcedureReturn #True
                        EndIf
                  EndWith
            Next
      Next
      ProcedureReturn #False
EndProcedure
Procedure WhereIsMouse()
      ; On est sur un objet
      If ItsHoverObject()
            SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Hand)
            ProcedureReturn #True
      EndIf
      ProcedureReturn #False
EndProcedure
Procedure DrawPrevBox()
      StartVectorDrawing(CanvasVectorOutput(#MainCanvas))
      ; J'efface en premier le canvas, avec l'image temporaire
      MovePathCursor(0,0)
      DrawVectorImage(ImageID(gTmpImg))
      ; Je dessine maintenant le box
      With gTmpDraw
            AddPathBox(\X,\Y,\W,\H)
            ; ATTENTION couleur RGBA donc avec alpha
            VectorSourceColor(RGBA(0, 255, 127, 255))
            DotPath(2,8)
      EndWith
      StopVectorDrawing()
EndProcedure
Procedure ManageDraw()
      ;On calcul le déplacement
      Protected DisplacX=gMouseX-gOldMouse\X
      Protected DisplacY=gMouseY-gOldMouse\Y
      Select gDrawMode
            Case #DrawBox  
                  If gMouseX>GadgetWidth(#MainCanvas)
                        ProcedureReturn 
                  EndIf
                  If gMouseX<0
                        ProcedureReturn 
                  EndIf
                  If gMouseY>GadgetHeight(#MainCanvas)
                        ProcedureReturn 
                  EndIf
                  If gMouseY<0
                        ProcedureReturn 
                  EndIf
                  gTmpDraw\X=gOldMouse\X
                  gTmpDraw\Y=gOldMouse\Y
                  gTmpDraw\W=DisplacX
                  gTmpDraw\H=DisplacY
                  DrawPrevBox()
      EndSelect
      gNewDraw=#True
EndProcedure
Procedure AddNewBox()
      AddElement(myDraw())
      AddElement(myDraw()\myBox())
      With myDraw()\myBox()
            \X=gTmpDraw\X
            \Y=gTmpDraw\Y
            \W=gTmpDraw\W
            \H=gTmpDraw\H
      EndWith
      DrawCanvas()
EndProcedure
Procedure EventCanvas()
      Select EventType()
            Case #PB_EventType_MouseMove
                  ; Savoir ou l'on est ?
                  ; Je mémorise les position de la souris sur le canvas
                  gMouseX=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseX)
                  gMouseY=GetGadgetAttribute(#MainCanvas,#PB_Canvas_MouseY)
                  If Not gClicOn And gDrawMode=#Select
                       If WhereIsMouse():ProcedureReturn :EndIf
                  ElseIf gClicOn And gDrawMode<>#Select
                        ManageDraw()
                  EndIf
            Case #PB_EventType_LeftButtonDown
                  If Not gClicOn
                        ; On mémorise la position de la souris pour le calcul du déplacement
                        gOldMouse\X=gMouseX
                        gOldMouse\Y=gMouseY
                        ; Aucun objet sélectionner/No object selected
                        *gObjectSelected=-1
                  EndIf
                  gClicOn=#True ; Signale que l'on clique sur le bt gauche
            Case #PB_EventType_LeftButtonUp
                  If gNewDraw
                        Select gDrawMode
                              Case #DrawBox
                                    AddNewBox()
                        EndSelect
                  ElseIf gDrawMode=#Select And *gCurrentObjet<>-1
                        *gObjectSelected=*gCurrentObjet
                        DrawCanvas()
                  EndIf
                  gNewDraw=#False
                  gClicOn=#False ;Le bt gauche est relaché
      EndSelect
      Select gDrawMode
            Case #DrawBox
                  SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Cross) 
            Case #Select
                  SetGadgetAttribute(#MainCanvas,#PB_Canvas_Cursor,#PB_Cursor_Default) 
      EndSelect
EndProcedure
Procedure ChangeModeDraw()
      Select EventMenu()
            Case 0 ;Mode ajout d'objet/Add object mode
                  gDrawMode=#DrawBox
            Case 1 ;Mode édition / Edit mode
                  gDrawMode=#Select
      EndSelect
EndProcedure
Procedure OpenMainForm()
      Protected Flag=#PB_Window_SystemMenu|#PB_Window_Maximize
      ; Ouverture de la fenêtre
      OpenWindow(#MainForm,0,0,800,600,"Dssin d'une grille",Flag)
      ; Création du canvas
      CanvasGadget(#MainCanvas,0,0,WindowWidth(#MainForm),WindowHeight(#MainForm))
      ; On creé l'image temporaire
      gTmpImg=CreateImage(#PB_Any,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas))
      ; On place un Callback pour la fernmeture de la fenêtre
      BindEvent(#PB_Event_CloseWindow,@Exit(),#MainForm)
      ; On place un Callback pour la gestion des evenement sur le canvas
      BindGadgetEvent(#MainCanvas,@EventCanvas())
      ; Ajout de raccourcis clavier,/Add keyboard shorcut
      AddKeyboardShortcut(#MainForm,#PB_Shortcut_A,0)
      AddKeyboardShortcut(#MainForm,#PB_Shortcut_E,1)
      BindEvent(#PB_Event_Menu,@ChangeModeDraw(),#MainForm)
EndProcedure
Procedure DrawGrid()
      Protected X=gGridSpace,Y=gGridSpace
      ; Déplacement du point de la grille sur l'absice des X
      While X<GadgetWidth(#MainCanvas)
            Y=gGridSpace ; On redémare en haut
            While Y<GadgetHeight(#MainCanvas)
                  Plot(X,Y,gGridColor)
                  Y+gGridSpace ; On déplace le point sur Y
            Wend
            X+gGridSpace ; On déplace le point sur X
      Wend
EndProcedure
Procedure DrawBox()
      With myDraw()\myBox()
            Box(\X,\Y,\W,\H,RGB(255, 0, 0))
      EndWith
EndProcedure
Procedure DrawHandles()
      Protected X,Y
      If @myDraw()\myBox()<>*gObjectSelected
            ProcedureReturn 
      EndIf
      With myDraw()\myBox()
            Y=\Y-(gHandleSize/2)
            ; Poignée/Handle LU
            X=\X-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#LU))\X=X
            myHandle(Str(#LU))\Y=Y
            ; Poignée/Handle RU
            X=(\X+\W)-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#RU))\X=X
            myHandle(Str(#RU))\Y=Y
            ; Poignée/Handle MU
            X=(\X+(\W/2))-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#MU))\X=X
            myHandle(Str(#MU))\Y=Y
             Y=(\Y+\H)-(gHandleSize/2)
            ; Poignée/Handle LD
            X=\X-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#LD))\X=X
            myHandle(Str(#LD))\Y=Y
            ; Poignée/Handle RD
            X=(\X+\W)-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
            myHandle(Str(#RD))\X=X
            myHandle(Str(#RD))\Y=Y
            ; Poignée/Handle MD
            X=(\X+(\W/2))-(gHandleSize/2)
            Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#MD))\X=X
             myHandle(Str(#MD))\Y=Y
             
             Y=(\Y+(\H/2))-(gHandleSize/2)
             X=\X-(gHandleSize/2)
             Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#LM))\X=X
             myHandle(Str(#LM))\Y=Y
             X=(\X+\W)-(gHandleSize/2)
             Box(X,Y,gHandleSize,gHandleSize,gHandleColor)
             myHandle(Str(#RM))\X=X
             myHandle(Str(#RM))\Y=Y
      EndWith
EndProcedure
Procedure DrawOblect()
      ForEach myDraw()
            With myDraw()
                  ForEach \myBox()
                        DrawBox()
                        DrawHandles()
                  Next
            EndWith
      Next
EndProcedure 
Procedure DrawTmpImg()
      StartDrawing(ImageOutput(gTmpImg))
      ; Efface l'image
      Box(0,0,GadgetWidth(#MainCanvas),GadgetHeight(#MainCanvas),gBgColor)
      ; Dessin de la grille
      DrawGrid()
      DrawOblect() ; Dessine nos objets
      StopDrawing()
EndProcedure
Procedure DrawCanvas()
      DrawTmpImg()
      StartDrawing(CanvasOutput(#MainCanvas))
      ; Dessin de l'image temporaire
      DrawImage(ImageID(gTmpImg),0,0)
      StopDrawing()
EndProcedure
;-* Run programme
; --> les procédures qui seront lancées au lancement du programme
; On ouvre la fenêtre
; On Dessine le canvas
OpenMainForm()
DrawCanvas()
;}
;-* Main loop
; --> la boucle principale vide car je gère les évenement avec le BindEvent etc...
Repeat :WaitWindowEvent():ForEver
;}
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Répondre