J'ai créer un code pour pouvoir facilement gérer l'affichage dans un canevas.
Ce module est un module de gestion d'affichage dans un canevas.
Ce module permet de gérer l'affichage dans un canevas.
Il peut fonctionner en mode FPS (Image par secondes) ou en mode statique (Il ne se passera rien, car la procédure ne sera pas appelée).
Vous pourrez également limiter le nombre de FPS par secondes, ce qui peut être très pratique pour rendre l'affichage stable.
1 FPS = une boucle d'affichage, le nombre de FPS maximum dépend de la puissance de votre machine !
A chaque boucle d'affichage, une procédure DE VOTRE CHOIX sera appelée, c'est vous qui personnalisez l'affichage de celui-ci.
Ce module fonctionne un peu à la façon d'un écran de jeu vidéo ou à chaque boucle, l'affichage s'actualise.
Cependant ici c'est dans un canevas, pas dans un écran, ce sera donc plus lent, mais vous pourrez gérer grâce à PB tous
les évènements de celui-ci et inclure ça dans votre programme facilement, c'est très simple d'utilisation et personnalisable.
Dans votre procédure de dessins, certains évènements de la souris y seront transmis automatiquement:
- Position de la souris sur le canevas.
- Largeur et Hauteur du canevas.
- Une valeur personnalisée de votre choix (Optionnel).
- Vous pourrez aussi savoir l'état des boutons de la souris (Enfoncé ou non) grâce à des fonctions.
- Vous pourrez également savoir quel touche du clavier a été enfoncé.
Dans cette procédure de dessins, vous allez vous-même dessiner sur le canevas (A chaque boucle).
De plus, le module permet de personnaliser le mode de dessins de celui-ci:
En Mode 2DDrawing (La procédure de dessins devra uniquement utiliser des fonctions de la bibliothèque 2DDrawing).
En Mode VectorDrawing (La procédure de dessins devra uniquement utiliser des fonction de la bibliothèque VectorDrawing).
Vous pourrez même le changer en cours de fonctionnement, mais jamais les deux à la fois, c'est soit l'un soit l'autre.
Le module contient également, mais pas que, des fonctions pour avoir des informations sur le taux de rafraichissement de l'affichage du canevas.
Par exemple, le nombre de FPS par seconde de rafraichissement du canevas, et pleins d'autres fonctions de ce type.
Ce module pourrait par exemple servir à aider à créer de petits jeux, par exemple des jeux drôles, ou des logiciels de dessins ou autre choses.
Voilà, c'est à vous de jouer comme on dit !
Le dossier complet ici avec 9 exemples d'utilisation:
https://drive.google.com/file/d/1eqFfMV ... share_link
; Le Module ici:
Code : Tout sélectionner
;{ Créé par Dieppedalle David alias Shadow Storm le 12/02/2022.
; Merci à Naheulf pour m'avoir un peu aidé en me disant comment optimiser un peu la vitesse du programme.
; Merci à Micoute d'avoir corrigé les fautes d'orthographe.
;
; Version actuelle: 1.12.0
;}
; Message pour Option de compilation des Threads (Merci à Falsam pour l'idée).
CompilerIf Not #PB_Compiler_Thread
CompilerError "Vous devez activer dans votre fichier de code l'option 'Activer la gestion des threads' dans les options de compilation !"
CompilerEndIf
DeclareModule CanvasDrawingManager
#CanvasDrawingManager_All = -1
#CanvasAttributeMouseX = -2
#CanvasAttributeMouseY = -3
#CanvasAttributeMouseOver = -4
#CanvasAttributeLeftMouseButtonHold = -5
#CanvasAttributeRightMouseButtonHold = -6
#CanvasAttributeMiddleMouseButtonHold = -7
#CanvasAttributeKeyBoardLastKeyHold = -8
#CanvasAttributeKeyBoardInput = -9
#CanvasDrawingMode2DDrawing = -10
#CanvasDrawingModeVectorDrawing = -11
;{ Ceci sert à créer une procédure personnalisée pour définir le dessins du canevas qui sera actualisé à chaque boucle, cette boucle est gérée par un Thread.
; Le nom du prototype est 'PrototypeCanvasDrawingCallBack', celui-ci contient 3 paramètres.
; Dans la procédure de dessins personnalisée, ce nom sera remplacé par un nom de procédure quelconque, mais devra contenir ces 3 paramètres
; Le nom des paramètres dans la procédure de dessins n'a aucune importance, mais les types doivent rester inchangés.
; Au final cela deviendra quelque chose du style: MaProcedureDessinsCanevas(NumeroCanevas.i, LargeurCanevas.i, HauteurCanevas.i)
; Pour pouvoir appeler cette fameuse procédure de dessins personnalisés, le programme devra donc savoir son adresse, et comment on fait ça ?:
;
; Avec la fonction suivante: SetCallBackCanvasDrawingManager(CanvasNumber.i, ProcedureDrawingCallBack.PrototypeCanvasDrawingCallBack)
; Le paramètre 'ProcedureDrawingCallBack.PrototypeCanvasDrawingCallBack' est une variable (ProcedureDrawingCallBack) qui pointe vers le prototype (PrototypeCanvasDrawingCallBack)
; et contiendra donc l'adresse de cette procédure en la renseignant, par exemple comme ceci:
;
; SetCallBackCanvasDrawingManager(#CanvasGadget, @MaProcedureDessinsCanevas())
; Le paramètre donné suivant '@MaProcedureDessinsCanevas' est l'adresse de cette fameuse procédure de dessins personnalisés pour ce canevas !
;}
Prototype.i PrototypeCanvasDrawingCallBack(CanvasNumber.i, CanvasMouseX.i, CanvasMouseY.i, CanvasWidth.i, CanvasHeight.i, Value.i)
Declare.b InitCanvasDrawingManager(CanvasNumber.i, DrawingMode.i = #CanvasDrawingMode2DDrawing, AutoRefrech.b = #True, Delay.i = 0, Priority.i = 0)
Declare.b IsCanvasDrawingManager(CanvasNumber.i)
Declare.b SetDrawingModeCanvasDrawingManager(CanvasNumber.i, DrawingMode.i)
Declare.b SetCallBackCanvasDrawingManager(CanvasNumber.i, ProcedureDrawingCallBack.PrototypeCanvasDrawingCallBack, Value.i = 0)
Declare.b SetDelayRefhechCanvasDrawingManager(CanvasNumber.i, Delay.i)
Declare.b SetRefhechPriorityCanvasDrawingManager(CanvasNumber.i, Priority.i)
Declare.b SetRefhechLimiteFPSCanvasDrawingManager(CanvasNumber.i, FPS.i)
Declare.b SetAutoRefrechCanvasDrawingManager(CanvasNumber.i, AutoRefrech.b)
Declare.b SetImageCanvasDrawingManager(CanvasNumber.i, Image.i)
Declare.i GetDrawingModeCanvasDrawingManager(CanvasNumber.i)
Declare.i GetDelayRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetRefhechPriorityCanvasDrawingManager(CanvasNumber.i)
Declare.b GetAutoRefrechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.f GetMediumTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetTotaleTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetLoopRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetFPSRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetRefhechLimiteFPSCanvasDrawingManager(CanvasNumber.i)
Declare.i GetTimeWaitLoopLimiteFPSCanvasDrawingManager(CanvasNumber.i)
Declare.i GetMinimumFPSRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetMaximumFPSRefhechCanvasDrawingManager(CanvasNumber.i)
Declare.i GetCanvasAttributeCanvasDrawingManager(CanvasNumber.i, CanvasAttribut.i)
Declare.i GetImageCanvasDrawingManager(CanvasNumber.i)
Declare.b ReleaseCanvasDrawingManager(CanvasNumber.i = #CanvasDrawingManager_All)
EndDeclareModule
Module CanvasDrawingManager
;{ Structure
Structure StructureCanvasDrawingManager
CanvasInit.b ; Si le canevas est intitialisé (#True) ou non (#False).
CanvasNumber.i ; Le numéro du canevas.
CanvasImage.i ; L'image du canevas.
CanvasDrawingMode.i ; Le mode de dessins, soit 2DDrawing (Par Défaut), soit VectorDrawing.
CanvasAutoRefrech.b ; #True (1) si l'auto-rafraissement du canevas est activé, sinon #False (0).
CanvasDrawingCallBack.PrototypeCanvasDrawingCallBack ; Adresse de la procédure pour dessiner sur le canevas.
CanvasDrawingCallBackValue.i ; Une valeur qui sera transmise à la procédure de dessins du canevas.
CanvasThreadNumber.i ; Le numéro du Thread du canevas.
CanvasThreadDelay.i ; Le delai entre chaque boucle d'affichage du canevas.
CanvasThreadPriority.i ; La priorité du thread du canevas qui gère l'affichage de celui-ci.
CanvasTimeLoop.i ; Le temps de la boucle (Frame) actuel d'affichage du canevas.
CanvasMediumTimeLoop.f ; Le temps moyen des boucles (Frame) d'affichage du canevas, calculé et actualisé à chaque seconde.
CanvasTotaleTimeLoop.i ; Le temps total de toutes les boucles (Frame) d'affichage du canevas, remis à 0 à chaque seconde.
CanvasLoop.i ; Le nombre de boucles (Frame) actuelles accomplies, remis à 0 à chaque seconde.
CanvasFPS.i ; Le nombre de boucles (Frame) accomplies en 1 seconde, actualisé à chaque seconde.
CanvasLimiteFPS.i ; Le nombre de boucles (Frame) maximum que devra accomplir en 1 seconde le canevas.
CanvasTimeWaitLimiteFPS.i ; Le temps en MS qu'attend le thread dans la boucle actuelle si 'CanvasLimiteFPS.i' est actif.
CanvasMinimumFPS.i ; Le nombre de boucles (Frame) minimum accomplies en 1 seconde, actualisé à chaque seconde.
CanvasMaximumFPS.i ; Le nombre de boucles (Frame) maximum accomplies en 1 seconde, actualisé à chaque seconde.
CanvasMouseX.i ; La dernière position connue X de la souris sur le canevas.
CanvasMouseY.i ; La dernière position connue Y de la souris sur le canevas.
CanvasMouseOver.b ; #True (1) la souris est sur le canevas, sinon #False (0).
CanvasLeftMouseButtonHold.b ; #True (1) si le bouton gauche de la souris est enfoncé sur le canevas, sinon #False (0).
CanvasRightMouseButtonHold.b ; #True (1) si le bouton droit de la souris est enfoncé sur le canevas, sinon #False (0).
CanvasMiddleMouseButtonHold.b ; #True (1) si le bouton centre de la souris est enfoncé sur le canevas, sinon #False (0).
CanvasKeyBoardLastKeyHold.i ; La dernière touche du clavier qui est actuellement pressée.
CanvasKeyBoardImput.i ; Le dernier caractère qui à été saisi au clavier.
EndStructure
;}
; Map qui sert pour enregistrer les canevas.
Global NewMap MapCanvasDrawingManager.StructureCanvasDrawingManager()
; Teste si le canevas est initialisé pour l'utiliser avec CanvasDrawingManager.
; Donne #True (1) si le canevas a été initialisé pour l'utiliser avec CanvasDrawingManager, sinon renvoie #False (0) si le canevas n'existe pas. (Cette macro est Privée au module).
Macro _IsCanvasDrawingManager(CanvasNumber) ; Pour usage dans le module
Bool(IsGadget(CanvasNumber.i) And MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasInit = #True)
EndMacro
;{ Procédures
;{ Teste si le canevas est initialisé pour l'utiliser avec CanvasDrawingManager.
; CanvasNumber.i = Le numéro du canevas.
; Renvoie #True (1) si le canevas existe et est initialisé pour l'utiliser avec CanvasDrawingManager, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn _IsCanvasDrawingManager(CanvasNumber)
EndProcedure
; La CallBack qui va enregistrer la position et l'état de la souris sur le canevas dès que celle-ci va bouger ou qu'un évènement intervient sur celui-ci (Cette procédure est Privée au module, les autres sont publiques).
Procedure CallBackEventCanvasDrawingManager()
; On récupère le numéro du canevas ou l'évènement s'est produit.
Canvas.i = EventGadget()
; Le pointeur '*Manager' pointe sur la structure 'StructureCanvasDrawingManager' à l'adresse du numéro du canevas.
Protected *Manager.StructureCanvasDrawingManager = @MapCanvasDrawingManager(Str(Canvas.i))
Select EventType()
Case #PB_EventType_MouseEnter ; Le curseur de la souris est entré dans le gadget.
*Manager\CanvasMouseOver = #True
Case #PB_EventType_MouseLeave ; Le curseur de la souris est sorti du gadget.
*Manager\CanvasMouseOver = #False
Case #PB_EventType_MouseMove; Le curseur de la souris a bougé.
*Manager\CanvasMouseX = GetGadgetAttribute(Canvas.i, #PB_Canvas_MouseX)
*Manager\CanvasMouseY = GetGadgetAttribute(Canvas.i, #PB_Canvas_MouseY)
Case #PB_EventType_LeftButtonDown ; Le bouton gauche de la souris a été pressé.
*Manager\CanvasLeftMouseButtonHold = #True
Case #PB_EventType_LeftButtonUp ; Le bouton gauche de la souris a été relâché.
*Manager\CanvasLeftMouseButtonHold = #False
Case #PB_EventType_RightButtonDown ; Le bouton droit de la souris a été pressé.
*Manager\CanvasRightMouseButtonHold = #True
Case #PB_EventType_RightButtonUp ; Le bouton droit de la souris a été relâché.
*Manager\CanvasRightMouseButtonHold = #False
Case #PB_EventType_MiddleButtonDown ; Le bouton centre de la souris a été pressé.
*Manager\CanvasMiddleMouseButtonHold = #True
Case #PB_EventType_MiddleButtonUp ; Le bouton centre de la souris a été relâché.
*Manager\CanvasMiddleMouseButtonHold = #False
Case #PB_EventType_KeyDown ; Une touche du clavier a été enfoncée.
*Manager\CanvasKeyBoardLastKeyHold = GetGadgetAttribute(Canvas.i, #PB_Canvas_Key)
Case #PB_EventType_KeyUp ; Une touche du clavier a été relâchée.
*Manager\CanvasKeyBoardLastKeyHold = 0
*Manager\CanvasKeyBoardImput = 0
Case #PB_EventType_Input ; Un caractère a été entré avec le clavier.
*Manager\CanvasKeyBoardImput = GetGadgetAttribute(Canvas.i, #PB_Canvas_Input)
Case #PB_EventType_Resize
; Canvas.i
Default
; Debug EventType()
EndSelect
EndProcedure
; Le Thread qui va gérer l'affichage sur le canevas. (Cette procédure est Privée au module, les autres sont publiques).
Procedure ThreadCanvasDrawingManager(CanvasNumber.i)
; Le pointeur '*Manager' pointe sur la structure 'StructureCanvasDrawingManager' à l'adresse du numéro du canevas.
Protected *Manager.StructureCanvasDrawingManager = @MapCanvasDrawingManager(Str(CanvasNumber.i))
; Appelle une procédure de gestion des évènements du canevas.
BindGadgetEvent(CanvasNumber.i, @CallBackEventCanvasDrawingManager(), #PB_All)
Repeat
; Si l'auto-rafraichissement du canevas est activé.
If *Manager\CanvasAutoRefrech = #True
; Sauvegarde le temps actuel.
TimeStart.i = ElapsedMilliseconds()
; Si le mode de dessins du canevas est 2DDrawing.
If *Manager\CanvasDrawingMode = #CanvasDrawingMode2DDrawing
; Si on peut dessiner sur le canevas.
If StartDrawing(CanvasOutput(CanvasNumber.i))
; Si le canevas à une procédure de dessins.
If *Manager\CanvasDrawingCallBack <> #Null ; Si l'adresse de la procédure est différente de 0.
; Appelle la procédure de dessins du canevas avec les paramètres demandés, depuis son adresse, définie par l'utilisateur, voir la fonction 'SetCallBackCanvasDrawingManager'.
; Ceci utilise le prototype 'PrototypeCanvasDrawingCallBack', voir dans DeclareModule.
*Manager\CanvasDrawingCallBack(CanvasNumber.i, *Manager\CanvasMouseX, *Manager\CanvasMouseY, GadgetWidth(CanvasNumber.i), GadgetHeight(CanvasNumber.i), *Manager\CanvasDrawingCallBackValue)
EndIf
StopDrawing()
EndIf
; Si le mode de dessins du canevas est VectorDrawing ou n'importe quoi d'autre.
Else ; #CanvasDrawingModeVectorDrawing.
; Si on peut dessiner sur le canevas.
If StartVectorDrawing(CanvasVectorOutput(CanvasNumber.i))
; Si le canevas à une procédure de dessins.
If *Manager\CanvasDrawingCallBack <> #Null ; Si l'adresse de la procédure est différente de 0.
; Appelle la procédure de dessins du canevas avec les paramètres demandés, depuis son adresse, définie par l'utilisateur, voir la fonction 'SetCallBackCanvasDrawingManager'.
; Ceci utilise le prototype 'PrototypeCanvasDrawingCallBack', voir dans DeclareModule.
*Manager\CanvasDrawingCallBack(CanvasNumber.i, *Manager\CanvasMouseX, *Manager\CanvasMouseY, GadgetWidth(CanvasNumber.i), GadgetHeight(CanvasNumber.i), *Manager\CanvasDrawingCallBackValue)
EndIf
StopVectorDrawing()
EndIf
EndIf
; Attend le temps défini dans la procédure d'initialisation du canevas ou dans la procédure SetDelayRefhechCanvasDrawingManager().
Delay(*Manager\CanvasThreadDelay)
; Si la limite de FPS est supérieure à 0 et qu'il y à un temps de calculé (Les calculs sont réalisés à partir de la boucle précédante).
If *Manager\CanvasLimiteFPS > 0 And *Manager\CanvasTimeLoop > 0
; Calcule le nombre de frames actuelles potentielles.
; 1 seconde = 1000 MS, 1000 est divisé par le temps de la dernière boucle pour estimer le nombre de frame par seconde et ainsi ajuster les FPS en temps réel.
CalculeFrameSeconde.f = 1000 / *Manager\CanvasTimeLoop
; Si le nombre de FPS potentiel calculé est supérieur au nombre de FPS limite.
If CalculeFrameSeconde.f > *Manager\CanvasLimiteFPS
*Manager\CanvasTimeWaitLimiteFPS + 1 ; Ajoute 1 MS de temps d'attente.
; Sinon si le nombre de FPS potentielles calculées est inférieur au nombre de FPS limite et que le temps d'attente est supérieur à 0.
ElseIf (CalculeFrameSeconde.f < *Manager\CanvasLimiteFPS) And *Manager\CanvasTimeWaitLimiteFPS > 0
*Manager\CanvasTimeWaitLimiteFPS - 1 ; Enlève 1 MS de temps d'attente.
EndIf
If *Manager\CanvasTimeWaitLimiteFPS < 0
*Manager\CanvasTimeWaitLimiteFPS = 0
EndIf
; Attent ce nombre de MS avant de continuer.
Delay(*Manager\CanvasTimeWaitLimiteFPS)
EndIf
; Sauvegarde le temps actuel.
TimeEnd.i = ElapsedMilliseconds()
; Le temps de cette boucle.
*Manager\CanvasTimeLoop = (TimeEnd.i - TimeStart.i)
; Le temps total de toutes les boucles.
*Manager\CanvasTotaleTimeLoop + *Manager\CanvasTimeLoop
; Le nombre de boucles actuelles.
*Manager\CanvasLoop + 1
; Si une seconde s'est écoulée.
If *Manager\CanvasTotaleTimeLoop >= 1000
; Le nombre de boucles faites en 1 seconde.
*Manager\CanvasFPS = *Manager\CanvasLoop
If *Manager\CanvasMinimumFPS > 0 And *Manager\CanvasLoop < *Manager\CanvasMinimumFPS
; Le nombre de boucles minimum faites en 1 seconde.
*Manager\CanvasMinimumFPS = *Manager\CanvasLoop
ElseIf *Manager\CanvasMinimumFPS = 0
; Le nombre de boucles minimum faites en 1 seconde.
*Manager\CanvasMinimumFPS = *Manager\CanvasLoop
EndIf
If *Manager\CanvasLoop > *Manager\CanvasMaximumFPS
; Le nombre de boucles maximum faites en 1 seconde.
*Manager\CanvasMaximumFPS = *Manager\CanvasLoop
EndIf
; Le temps moyen de toutes les boucles sur une seconde, actualisé à chaque seconde.
*Manager\CanvasMediumTimeLoop = *Manager\CanvasTotaleTimeLoop / *Manager\CanvasLoop
; Le temps total de toutes les boucles, remis à 0.
*Manager\CanvasTotaleTimeLoop = 0
; Le nombre de boucle actuel est remis à 0.
*Manager\CanvasLoop = 0
EndIf
Else ; Si l'auto-rafraichissement du canevas est désactivé, attendra indéfiniment 25 MS, à moins que celui-ci ne soit réactivé.
Delay(25)
EndIf
ForEver
EndProcedure
;{ Initialise la gestion du canevas pour gérer l'affichage automatiquement de celui-ci.
; CanvasNumber.i = Le numéro du canevas.
; DrawingMode.i = #CanvasDrawingMode2DDrawing pour utiliser le mode de dessins 2DDrawing dans la procédure personnalisé de dessins du canevas.
; #CanvasDrawingModeVectorDrawing pour utiliser le mode de dessins VectorDrawing dans la procédure personnalisé de dessins du canevas.
; AutoRefrech.b = #True (1) pour actualiser l'affichage automatiquement du canevas en mode FPS, 1 FPS = 1 appel de la procédure de dessins
; sinon #False (0) = l'affichage du canevas ne sera pas actualisé et la procédure de dessins du canevas ne sera pas appelé.
; Delay.i = le délai d'attente dans le Thread qui gére l'affichage du canevas (Entre chaque boucle de l'affichage du canevas), 0 = pas d'attente = rapidité et utilisation du processeur (1 Thread) au maximum.
; Priority.i = La priorité du Thread qui gére l'affichage du canevas, 0 = Normale, entre 1 et 31, plus le nombre est grand et plus la priorité sera grande, 32 = temps réel.
;
; Renvoie #True (1) si le canevas à été initialisé, sinon renvoie #False (0) si le canevas ou l'image n'existe pas ou si celui-ci est déjà initialisé.
;}
Procedure.b InitCanvasDrawingManager(CanvasNumber.i, DrawingMode.i = #CanvasDrawingMode2DDrawing, AutoRefrech.b = #True, Delay.i = 0, Priority.i = 0)
; Cherche si l'élément est présent dans la map et récupère son adresse s'il existe.
; S'il n'existe pas (Car n'a pas encore été ajouté) l'adresse vaut #Null = #False = 0
Protected *Manager.StructureCanvasDrawingManager = FindMapElement(MapCanvasDrawingManager(), Str(CanvasNumber.i))
; Si l'élément n'existe pas
If Not *Manager
; Crée l'élément et récupére son adresse.
*Manager = AddMapElement(MapCanvasDrawingManager(), Str(CanvasNumber.i), #PB_Map_NoElementCheck)
EndIf
If IsGadget(CanvasNumber.i) And *Manager\CanvasInit = #False
*Manager\CanvasNumber = CanvasNumber.i
If Delay.i < 0
Delay.i = 0
EndIf
Thread.i = CreateThread(@ThreadCanvasDrawingManager(), CanvasNumber.i)
If IsThread(Thread.i)
If Priority.i < 0
Priority.i = 0
ElseIf Priority.i > 32
Priority.i = 32
EndIf
If DrawingMode.i <> #CanvasDrawingMode2DDrawing And DrawingMode.i <> #CanvasDrawingModeVectorDrawing
DrawingMode.i = #CanvasDrawingMode2DDrawing
EndIf
ThreadPriority(Thread.i, Priority.i)
*Manager\CanvasThreadNumber = Thread.i
*Manager\CanvasThreadDelay.i = Delay.i
*Manager\CanvasThreadPriority = Priority.i
*Manager\CanvasInit = #True
*Manager\CanvasAutoRefrech = AutoRefrech.b
*Manager\CanvasDrawingMode = DrawingMode.i
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;{ Change le mode de dessins du canevas.
; CanvasNumber.i = Le numéro du canevas.
; DrawingMode.i = Le mode de dessins de la procédure de dessins personnalisé du canevas:
; #CanvasDrawingMode2DDrawing = Pour utiliser des fonctions de type 2DDrawing dans la procédure de dessins personnaliser du canevas.
; #CanvasDrawingModeVectorDrawing = Pour utiliser des fonctions de type VectorDrawing dans la procédure de dessins personnaliser du canevas.
;
; Renvoie #True (1) si le mode de dessins du canevas a été Changé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetDrawingModeCanvasDrawingManager(CanvasNumber.i, DrawingMode.i)
If IsCanvasDrawingManager(CanvasNumber.i)
If DrawingMode.i <> #CanvasDrawingMode2DDrawing And DrawingMode.i <> #CanvasDrawingModeVectorDrawing
DrawingMode.i = #CanvasDrawingMode2DDrawing
EndIf
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasDrawingMode = DrawingMode.i
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Définit la procédure de dessins du canevas.
; CanvasNumber.i = Le numéro du canevas.
; ProcedureDrawingCallBack.PrototypeCanvasDrawingCallBack = Adresse de la procédure de dessins du canevas > '@' suivie du nom de la procédure de dessins personnalisé pour ce canevas, Exemple: @MaProcedureDessinsCanevas().
; Value.i = Une valeur quelconque envoyée à la procédure de dessins du canevas, Optionnel.
; Renvoie #True (1) si la procédure de dessins du canevas a été définie, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetCallBackCanvasDrawingManager(CanvasNumber.i, ProcedureDrawingCallBack.PrototypeCanvasDrawingCallBack, Value.i = 0)
If IsCanvasDrawingManager(CanvasNumber.i)
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasDrawingCallBack = ProcedureDrawingCallBack
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasDrawingCallBackValue = Value.i
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Change le délai de rafraichissement du thread qui gére l'affichage du canevas.
; CanvasNumber.i = Le numéro du canevas.
; Delay.i = Le délai d'attente entre chaque boucle d'affichage du canevas en MS.
; Renvoie #True (1) si le delai de rafraichissement du canevas a été changé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetDelayRefhechCanvasDrawingManager(CanvasNumber.i, Delay.i)
If IsCanvasDrawingManager(CanvasNumber.i)
If Delay.i < 0
Delay.i = 0
EndIf
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadDelay = Delay.i
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Change la priorité du thread qui gére l'affichage du canevas.
; CanvasNumber.i = Le numéro du canevas.
; Priority.i = La priorité du Thread, 0 = Normale, 1 à 31, plus le nombre est haut, plus la priorité du Thread sera importante, 32 = temps réel.
; Renvoie #True (1) si la priorité de l'affichage du canevas a été changée, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetRefhechPriorityCanvasDrawingManager(CanvasNumber.i, Priority.i)
If IsCanvasDrawingManager(CanvasNumber.i)
If Priority.i < 0
Priority.i = 0
ElseIf Priority.i > 32
Priority.i = 32
EndIf
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadPriority = Priority.i
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Active ou désactive l'auto-rafraissement de l'affichage du canevas.
; CanvasNumber.i = Le numéro du canevas.
; AutoRefrech.b = #True pour activer l'auto-rafraissement de l'affichage du canevas, #False pour le désactivé.
; Renvoie #True (1) si l'auto-rafraissement de l'affichage du canevas a été changé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetAutoRefrechCanvasDrawingManager(CanvasNumber.i, AutoRefrech.b)
If IsCanvasDrawingManager(CanvasNumber.i)
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasAutoRefrech = AutoRefrech.b
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Définit le nombre de FPS (Frame par seconde) de rafraichissement maximum du canevas.
; CanvasNumber.i = Le numéro du canevas.
; FPS.i = Le nombre de FPS maximum, Minimum = 5, attention plus ce nombre est grand et moins la limitation risque d'être précise, le calcule est fait à chaque Frame.
; Renvoie #True (1) si le nombre de FPS du canevas a été changé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
;}
Procedure.b SetRefhechLimiteFPSCanvasDrawingManager(CanvasNumber.i, FPS.i)
If IsCanvasDrawingManager(CanvasNumber.i)
If FPS.i <= 5
FPS.i = 5
EndIf
MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasLimiteFPS = FPS.i
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;{ Change l'image affiché sur le canevas.
; CanvasNumber.i = Le numéro du canevas.
; Image.i = L'image à afficher sur le canevas.
; Renvoie #True (1) si l'image du canevas a été changé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé ou si l'image n'est pas initialisé.
;}
Procedure.b SetImageCanvasDrawingManager(CanvasNumber.i, Image.i)
If IsCanvasDrawingManager(CanvasNumber.i)
If IsImage(Image.i) And StartDrawing(CanvasOutput(CanvasNumber.i))
DrawImage(ImageID(Image.i), 0, 0)
StopDrawing()
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le mode de dessins du canevas: #CanvasDrawingMode2DDrawing ou #CanvasDrawingModeVectorDrawing, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetDrawingModeCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasDrawingMode
EndIf
ProcedureReturn #False
EndProcedure
;{ Renvoie l'état de l'auto-rafraissement de l'affichage du canevas.
; CanvasNumber.i = Le numéro du canevas.
; Renvoie #True (1) si l'auto-rafraissement de l'affichage du canevas est activé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé ou si l'auto rafraissement de l'affichage du canevas est désactivé.
;}
Procedure.b GetAutoRefrechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasAutoRefrech
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le délai d'actualisation du thread qui gére l'affichage du canevas, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetDelayRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadDelay
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie la priorité du thread qui gére l'affichage du canevas, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetRefhechPriorityCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadPriority
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le délai d'actualisation de la boucle actuelle du canevas, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasTimeLoop
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le délai d'actualisation moyen de toutes les boucles du canevas sur une seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.f GetMediumTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasMediumTimeLoop
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le délai d'actualisation total actuel de toutes les boucles effectuées du canevas, pour une seule seconde maximum, remis à 0 à chaque seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetTotaleTimeLoopRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasTotaleTimeLoop
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le nombre de boucles actuelles effectuées du canevas, pour une seule seconde maximum, remis à 0 à chaque seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetLoopRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasLoop
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le nombre de boucles (Frame) qu'effectue le canevas par seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetFPSRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasFPS
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie la limite de FPS du canevas, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetRefhechLimiteFPSCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasLimiteFPS
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le temps d'attente de la boucle actuelle pour correspondre à la limite de FPS du canevas, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetTimeWaitLoopLimiteFPSCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasTimeWaitLimiteFPS
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le nombre de boucles (Frame) minimum accomplies en 1 seconde, actualisé à chaque seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetMinimumFPSRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasMinimumFPS
EndIf
ProcedureReturn #False
EndProcedure
; Renvoie le nombre de boucles (Frame) maximum accomplies en 1 seconde, actualisé à chaque seconde, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé.
; CanvasNumber.i = Le numéro du canevas.
Procedure.i GetMaximumFPSRefhechCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
ProcedureReturn MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasMaximumFPS
EndIf
ProcedureReturn #False
EndProcedure
;{ Renvoie l'état de la souris sur le canevas suivant l'attribut demandé, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé ou si l'attribut demandé n'existe pas.
; CanvasNumber.i = Le numéro du canevas.
; MouseState:
; #CanvasAttributeMouseX = La dernière position connue X de la souris sur le canevas.
; #CanvasAttributeMouseY = La dernière position connue Y de la souris sur le canevas.
; #CanvasAttributeMouseOver = #True (1) la souris est sur le canevas, sinon #False.
; #CanvasAttributeLeftMouseButtonHold = #True (1) si le bouton gauche de la souris est enfoncé sur le canevas, sinon #False (0).
; #CanvasAttributeRightMouseButtonHold = #True (1) si le bouton droit de la souris est enfoncé sur le canevas, sinon #False (0).
; #CanvasAttributeMiddleMouseButtonHold = #True (1) si le bouton centre de la souris est enfoncé sur le canevas, sinon #False (0).
;}
Procedure.i GetCanvasAttributeCanvasDrawingManager(CanvasNumber.i, CanvasAttribut.i)
If IsCanvasDrawingManager(CanvasNumber.i)
; Cherche si l'élément est présent dans la map et récupère son adresse s'il existe.
; S'il n'existe pas (Car n'a pas encore été ajouté) l'adresse vaut #Null = #False = 0
Protected *Manager.StructureCanvasDrawingManager = FindMapElement(MapCanvasDrawingManager(), Str(CanvasNumber.i))
If *Manager
Select CanvasAttribut.i
Case #CanvasAttributeMouseX ; = -2
ProcedureReturn *Manager\CanvasMouseX
Case #CanvasAttributeMouseY ; = -3
ProcedureReturn *Manager\CanvasMouseY
Case #CanvasAttributeMouseOver ; = -4
ProcedureReturn *Manager\CanvasMouseOver
Case #CanvasAttributeLeftMouseButtonHold ; = -5
ProcedureReturn *Manager\CanvasLeftMouseButtonHold
Case #CanvasAttributeRightMouseButtonHold ; = -6
ProcedureReturn *Manager\CanvasRightMouseButtonHold
Case #CanvasAttributeMiddleMouseButtonHold ; = -7
ProcedureReturn *Manager\CanvasMiddleMouseButtonHold
Case #CanvasAttributeKeyBoardLastKeyHold ; = -8
ProcedureReturn *Manager\CanvasKeyBoardLastKeyHold
Case #CanvasAttributeKeyBoardInput ; = -9
ProcedureReturn *Manager\CanvasKeyBoardImput
EndSelect
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;{ Crée et Renvoie l'image du canevas à cet instant ou la fonction est appelée, c'est comme une impression écran, mais pour le canevas.
; CanvasNumber.i = Le numéro du canevas.
; Renvoie le numéro de l'image qui vient d'être créée, sinon renvoie #False (0) si le canevas n'existe pas ou si celui-ci n'est pas initialisé ou si la création de l'image a échoué.
;}
Procedure.i GetImageCanvasDrawingManager(CanvasNumber.i)
If IsCanvasDrawingManager(CanvasNumber.i)
; Cherche si l'élément est présent dans la map et récupère son adresse s'il existe.
; S'il n'existe pas (Car n'a pas encore été ajouté) l'adresse vaut #Null = #False = 0
Protected *Manager.StructureCanvasDrawingManager = FindMapElement(MapCanvasDrawingManager(), Str(CanvasNumber.i))
; Si il y a déjà une image.
If IsImage(*Manager\CanvasImage)
FreeImage(*Manager\CanvasImage) ; Supprime l'image.
EndIf
; Crée une image vide de la taille du canevas.
*Manager\CanvasImage = CreateImage(#PB_Any, GadgetWidth(CanvasNumber.i), GadgetHeight(CanvasNumber.i))
; Si l'image est créée.
If IsImage(*Manager\CanvasImage)
If StartDrawing(ImageOutput(*Manager\CanvasImage)) ; Si on peut dessiner sur cette image.
DrawImage(GetGadgetAttribute(CanvasNumber.i, #PB_Canvas_Image), 0, 0) ; Dessine l'image du canevas sur l'image créée précédément.
StopDrawing()
ProcedureReturn *Manager\CanvasImage
EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;{ Libère le thread du canevas indiqué ou tous les threads créés de tous les canevas, très important, à mettre AVANT de libérer un canevas et quand le programme est terminé.
; NOTE: Si vous libèrez un canevas avant de libérer le thread qui lui est associé, alors le programme plantera.
; CanvasNumber.i = Le numéro du canevas ou #CanvasDrawingManager_All pour tous.
; Renvoie #True (1) si le ou les threads ont été liberés, sinon renvoi #False (0).
;}
Procedure.b ReleaseCanvasDrawingManager(CanvasNumber.i = #CanvasDrawingManager_All)
If CanvasNumber.i = #CanvasDrawingManager_All ; = -1
ForEach MapCanvasDrawingManager()
If IsThread(MapCanvasDrawingManager(MapKey(MapCanvasDrawingManager()))\CanvasThreadNumber)
KillThread(MapCanvasDrawingManager(MapKey(MapCanvasDrawingManager()))\CanvasThreadNumber)
EndIf
Next
Else
If IsThread(MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadNumber)
KillThread(MapCanvasDrawingManager(Str(CanvasNumber.i))\CanvasThreadNumber)
Else
ProcedureReturn #False
EndIf
EndIf
ProcedureReturn #True
EndProcedure
;}
EndModule
; Partie créée par Amitris_de le 10/12/2021.
; Traduit et modifié par Shadow (Dieppedalle David).
Enumeration ErrorHandler
#ErrorHandler_Window
#ErrorHandler_Text
#ErrorHandler_String
#ErrorHandler_ExitBtn
#ErrorHandler_ClipBoardBtn
EndEnumeration
; Procédure de gestion de Bugs.
Procedure ErrorHandler()
Protected ErrorMessage$, Event_ID
Select OSVersion()
Case #PB_OS_Windows_8_1
ErrorMessage$ + "Windows: 8.1" + #CRLF$
Case #PB_OS_Windows_8
ErrorMessage$ + "Windows: 8" + #CRLF$
Case #PB_OS_Windows_XP
ErrorMessage$ + "Windows: XP" + #CRLF$
Case #PB_OS_Windows_Vista
ErrorMessage$ + "Windows: Vista" + #CRLF$
Case #PB_OS_Windows_7
ErrorMessage$ + "Windows: 7" + #CRLF$
Case #PB_OS_Windows_2000
ErrorMessage$ + "Windows: 2000" + #CRLF$
Case #PB_OS_Windows_95
ErrorMessage$ + "Windows: 95" + #CRLF$
Case #PB_OS_Windows_98
ErrorMessage$ + "Windows: 98" + #CRLF$
Case #PB_OS_Windows_Future
ErrorMessage$ + "Windows: Future" + #CRLF$
Case #PB_OS_Windows_ME
ErrorMessage$ + "Windows: ME" + #CRLF$
Case #PB_OS_Windows_NT3_51
ErrorMessage$ + "Windows: NT3_51" + #CRLF$
Case #PB_OS_Windows_NT_4
ErrorMessage$ + "Windows: NT_4" + #CRLF$
Case #PB_OS_Windows_Server_2003
ErrorMessage$ + "Windows: Server_2003" + #CRLF$
Case #PB_OS_Windows_Server_2008
ErrorMessage$ + "Windows: Server_2008" + #CRLF$
Case #PB_OS_Windows_10
ErrorMessage$ + "Windows: 10" + #CRLF$
EndSelect
ErrorMessage$ + "Message d'erreur: " + ErrorMessage() + #CRLF$
Select ErrorCode()
Case #PB_OnError_InvalidMemory ; Lecture ou écriture dans une zone protégée.
ErrorMessage$ + "Lecture ou écriture dans une zone mémoire protégée - " + "Adresse mémoire cible: " + Str(ErrorTargetAddress()) + #CRLF$
Case #PB_OnError_Floatingpoint ; Erreur de calcul flottant.
ErrorMessage$ + "Erreur de calcul flottant." + #CRLF$
Case #PB_OnError_Breakpoint ; Point d'arrêt débogueur atteint (autres que ceux du PureBasic.
ErrorMessage$ + "Point d'arrêt du débogueur atteint." + #CRLF$
Case #PB_OnError_IllegalInstruction ; Exécution d'une instruction invalide.
ErrorMessage$ + "Instruction rencontrée invalide." + #CRLF$
Case #PB_OnError_PriviledgedInstruction ; Exécution d'une instruction privilégiée (system-) non autorisée.
ErrorMessage$ + "Instruction rencontrée privilégiée système non autorisée." + #CRLF$
Case #PB_OnError_DivideByZero ; Division par zéro (Windows seulement).
ErrorMessage$ + "Division par zéro." + #CRLF$
Default
ErrorMessage$ + "Code d'erreur inconnue: " + ErrorCode() + #CRLF$
EndSelect
ErrorMessage$ + "Ligne Code Source: " + Str(ErrorLine()) + #CRLF$
ErrorMessage$ + "Fichier Code Source: " + GetFilePart(ErrorFile())
If OpenWindow(#ErrorHandler_Window, 0, 0, 500, 220, "Une erreur à été rencontrée !", #PB_Window_ScreenCentered)
TextGadget(#ErrorHandler_Text, 10, 10, 400, 30, "Veuillez envoyer ces informations au développeur.")
StringGadget(#ErrorHandler_String, 10, 30, 480, 140, ErrorMessage$, #ES_MULTILINE | #WS_VSCROLL)
ButtonGadget(#ErrorHandler_ExitBtn, 415, 180, 75, 30, "Quitter")
ButtonGadget(#ErrorHandler_ClipBoardBtn, 10, 180, 175, 30, "Copier dans le Presse Papier")
Repeat
Event_ID = WaitWindowEvent()
If Event_ID = #PB_Event_Gadget
Select EventGadget()
Case #ErrorHandler_ExitBtn
End
Case #ErrorHandler_ClipBoardBtn
SetClipboardText(ErrorMessage$)
End
EndSelect
EndIf
Until Event_ID = #PB_Event_CloseWindow
EndIf
End
EndProcedure
; Si une erreur a été rencontrée, appelle la procédure ErrorHandler().
OnErrorCall(@ErrorHandler())