Page 1 sur 1

Gestion des menus dans la barre des menu en mode expert ???

Publié : ven. 29/janv./2016 1:23
par cage
Bonjour a tous,

J'ai quelques questions qui me chagrinent depuis mes débuts avec PB concernant les menus.

Ce n'est pas dans la conception des menus que je bloque, mais avec leur utilisation.

-Le fait de cliquer sur un menu de la barre des menus gèle l'application. Si l"application contient des timers, ceux-ci sont bloqués tant qu'on ne relâche pas le menu.

-Après avoir lancé une tache via menu ou bouton, la tache se gèle si on sélectionne un menu. J'ai pourtant un DoEvents() dans mes taches.

-Dans la barre des menus, cliquer sur un menu sans sous menu ne permet pas de déclencher une action.

Questions:
-peut-on utiliser un Thread pour ses timers et cela fonctionne-t-il correctement
-peut-on rendre la barre de menus non opérationnelle tant qu'une tache se déroule en "batch"
L'interface n'est pas bloquée, mais une action sur un menu bloque la tache.
-peut-on déclencher une action par simple clic sur un menu de la barre des menus.
c'est a dire sans sélectionner un sous menu.

Dans l'application en exemple, l'heure est affichée dans la barre de titre ainsi que le compteur de boucle du Timer
Tant qu'on ne fait rien, tout est normal. Dès qu'on sélectionne un menu, arrêt de l'heure et du compteur. Si on relâche le menu, l'heure s'affiche normalement, mais on voit que le compteur continu la ou il était resté.
Le menu "~" comporte un sous menu qui permet de faire un roll on/off de la fenêtre.
Je voudrais faire la même chose juste en appuyant sur le menu "~" ???
Cela fait beaucoup de lecture, alors j'arrête la.
Place au code. D'avance, merci pour votre aide.

Code : Tout sélectionner

EnableExplicit 

#WinApp=10 : #WinAppWidth  = 553 : #WinAppHeight = 416

#TITLE$ = "APP Light Edition"

Global Event, indexMenu

Enumeration Menus
  #MenuApp
EndEnumeration

Enumeration FormMenu
  #MenuAppQuit
  #MenuAppRoll
EndEnumeration

Enumeration Timer
  #Timer
EndEnumeration

Declare winRoll()
Declare setTitle()

ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_Minimize|#PB_Window_SystemMenu

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #TITLE$, Flags)
  If CreateImageMenu(#MenuApp, WindowID(#WinApp), #PB_Menu_ModernLook)
    MenuTitle("File")
      MenuItem(#MenuAppQuit   , "Exit"+Chr(9)+"Ctrl+Q")
    MenuTitle("~")
      MenuItem(#MenuAppRoll   , "Roll up")
  EndIf
  AddWindowTimer(#WinApp, #Timer, 1000)
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Escape, #MenuAppQuit)                 ; quit     with ESC
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_Q, #MenuAppQuit) ; quit     with CTRL+Q
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_R, #MenuAppRoll) ; win roll with CTRL+R
  SetWindowState(#WinApp, #PB_Window_Normal)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Menu
        indexMenu = EventMenu()
        Select indexMenu
          Case #MenuAppQuit      : Break
          Case #MenuAppRoll      : winRoll()
        EndSelect
      Case #PB_Event_CloseWindow : Break
      Case #PB_Event_Timer       : setTitle()
    EndSelect
  ForEver
EndIf
End

Procedure getTitleHeight(frm)
  Protected MyRect.RECT
  GetClientRect_(WindowID(frm), MyRect)
  ProcedureReturn #WinAppHeight - MyRect\bottom
EndProcedure

Procedure winRoll()
  If WindowHeight(#WinApp) = #WinAppHeight
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll down")
    StickyWindow(#WinApp, #True)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, 250, getTitleHeight(#WinApp))
  Else
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll up")
    StickyWindow(#WinApp, #False)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, #WinAppWidth, #WinAppHeight)
  EndIf
EndProcedure

Procedure setTitle()
  Protected Now$
  Static count
  Now$ = FormatDate("%hh:%ii:%ss", Date())
  SetWindowTitle(#WinApp, #TITLE$+" : "+Now$+" : "+Str(count))
  count+1
EndProcedure

Procedure.a doEvents(loop.a=255)
  Protected n.a 
  For n = 0 To loop
    WindowEvent()
    n + 1
  Next
EndProcedure

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 2:10
par falsam
On ne l'a peut être pas assez souligné. Depuis la version PB 5.30, la gestion classique des événements diffère des versions précédente de PureBasic.

Exemple : L’événement #PB_Event_SizeWindow ne permet pas de redimensionner les gadgets en temps réel. Il faut relâcher le clic gauche de la souris pour que l’événement soit prit en compte.
Aide en Anglais a écrit :The #PB_Event_SizeWindow and #PB_Event_MoveWindow events are no longer reported in realtime in the main event loop. This is to reduce problems with flickering on resize. To get realtime events you have to use the BindEvent() function and a callback in the future.
Les méthodes BindEvent() et BindGadgetEvent() sont utilisées pour attacher un gestionnaire d’événement (une procedure) à la survenue d’un événement.
Exemple : BindEvent(#PB_Event_CloseWindow, @OnEnd())

je pense que les timers sont logés à la même enseigne et se gèrent en temps réel avec un BindEvent() :wink:

J'ai modifié ton code et ton timer fonctionne en temps réel.

Code : Tout sélectionner

EnableExplicit 

#WinApp=10 : #WinAppWidth  = 553 : #WinAppHeight = 416

#TITLE$ = "APP Light Edition"

Global Event, indexMenu

Enumeration Menus
  #MenuApp
EndEnumeration

Enumeration FormMenu
  #MenuAppQuit
  #MenuAppRoll
EndEnumeration

Enumeration Timer
  #Timer
EndEnumeration

Declare winRoll()
Declare setTitle()
Declare OnEnd()

ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_Minimize|#PB_Window_SystemMenu

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #TITLE$, Flags)
  If CreateImageMenu(#MenuApp, WindowID(#WinApp), #PB_Menu_ModernLook)
    MenuTitle("File")
      MenuItem(#MenuAppQuit   , "Exit"+Chr(9)+"Ctrl+Q")
    MenuTitle("~")
      MenuItem(#MenuAppRoll   , "Roll up")
  EndIf
  AddWindowTimer(#WinApp, #Timer, 1000)
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Escape, #MenuAppQuit)                 ; quit     with ESC
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_Q, #MenuAppQuit) ; quit     with CTRL+Q
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_R, #MenuAppRoll) ; win roll with CTRL+R
  SetWindowState(#WinApp, #PB_Window_Normal)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
  
  ;Gestion des evenements
  BindEvent(#PB_Event_Timer, @setTitle(), #WinApp, #Timer)
  BindEvent(#PB_Event_CloseWindow, @OnEnd())
  BindEvent(#PB_Event_Menu, @OnEnd(), #WinApp, #MenuAppQuit)
  BindEvent(#PB_Event_Menu, @winRoll(), #WinApp, #MenuAppRoll)
  
  Repeat : WaitWindowEvent(10) : ForEver
    
  ;Repeat
    ;Event = WaitWindowEvent(10)
    ;Select Event
      ;Case #PB_Event_Menu
      ;  indexMenu = EventMenu()
      ;  Select indexMenu
      ;    Case #MenuAppQuit      : Break
      ;    Case #MenuAppRoll      : winRoll()
      ;  EndSelect
      ;Case #PB_Event_CloseWindow : Break
      ;Case #PB_Event_Timer       : setTitle()
   ;EndSelect
  ;ForEver
EndIf

Procedure getTitleHeight(frm)
  Protected MyRect.RECT
  GetClientRect_(WindowID(frm), MyRect)
  ProcedureReturn #WinAppHeight - MyRect\bottom
EndProcedure

Procedure winRoll()
  If WindowHeight(#WinApp) = #WinAppHeight
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll down")
    StickyWindow(#WinApp, #True)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, 250, getTitleHeight(#WinApp))
  Else
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll up")
    StickyWindow(#WinApp, #False)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, #WinAppWidth, #WinAppHeight)
  EndIf
EndProcedure

Procedure setTitle()
  Protected Now$
  Static count
  Now$ = FormatDate("%hh:%ii:%ss", Date())
  SetWindowTitle(#WinApp, #TITLE$+" : "+Now$+" : "+Str(count))
  count+1
EndProcedure

Procedure.a doEvents(loop.a=255)
  Protected n.a 
  For n = 0 To loop
    WindowEvent()
    n + 1
  Next
EndProcedure

Procedure OnEnd()
  End
EndProcedure
PS : la procédure doEvents() ne sert à rien dans ce code.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 3:01
par cage
Merci falsam pour ton retour.

Un peu tard pour tester, je le garde pour cet après-midi
PS : la procédure doEvents() ne sert à rien dans ce code.
Exact, je la donnais juste pour info car j'en parlais dans mon blabla
Je n'ai jamais utilisé le BindEvent jusqu'ici, mais je crois que je vais m'y mettre.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 7:52
par Ar-S
Oui il faut t'y mettre, c'est un peu déroutant et ça a quelques limites mais pour ce genre d'interaction c'est la solution.
On avait résolu le soucis du chronomètre ainsi. Il se freezait si on bougeait la fenêtre. Avec les Bindevent tout est nikel.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 12:17
par cage
Je viens de tester les 2 solutions, mais je dois dire que les BindEvent me plaisent bien.

Je vais modifier une de mes application pour voir si je ne rencontre pas de problèmes.

Si c'est le cas, je me convertirais avec plaisir.

J'ai beaucoup de menus a gérer, puis-je mixer les 2 méthodes:

-une partie gérée par BindEvent
-le reste géré dans la boucle --> Repeat : WaitWindowEvent(10) : ForEver

J'ai lu des avis partagés dans le forum, mais cela ne semble pas pose de pbs.

Une idée pour activer un menu principal de la barre des menus tel le menu "~" de mon exemple sans avoir a dérouler pour afficher "Roll up" et cliquer dessus. Via API je suppose.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 12:19
par Mesa
On peut utiliser un thread, ce qui permet d'avoir un code multiplateforme:

Code : Tout sélectionner

EnableExplicit 
CompilerIf #PB_Compiler_Thread = 0
  MessageRequester("ATTENTION", "Veuillez mettre la directive du compilateur; Activer la gestion des threads")
  End
CompilerEndIf


#WinApp=10 : #WinAppWidth  = 553 : #WinAppHeight = 416

#TITLE$ = "APP Light Edition"

Global Event, indexMenu

Enumeration Menus
  #MenuApp
EndEnumeration

Enumeration FormMenu
  #MenuAppQuit
  #MenuAppRoll
EndEnumeration

; Enumeration Timer
;   #Timer
; EndEnumeration

Declare winRoll()
Declare setTitle(t)


ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_Minimize|#PB_Window_SystemMenu

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #TITLE$, Flags)
  If CreateImageMenu(#MenuApp, WindowID(#WinApp), #PB_Menu_ModernLook)
    MenuTitle("File")
    MenuItem(#MenuAppQuit   , "Exit"+Chr(9)+"Ctrl+Q")
    MenuTitle("~")
    MenuItem(#MenuAppRoll   , "Roll up")
  EndIf
 ; AddWindowTimer(#WinApp, #Timer, 1000)
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Escape, #MenuAppQuit)                 ; quit     with ESC
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_Q, #MenuAppQuit) ; quit     with CTRL+Q
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_R, #MenuAppRoll) ; win roll with CTRL+R
  SetWindowState(#WinApp, #PB_Window_Normal)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
  
  CreateThread(@setTitle(),1000)
  
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Menu
        indexMenu = EventMenu()
        Select indexMenu
          Case #MenuAppQuit      : Break
          Case #MenuAppRoll      : winRoll()
        EndSelect
      Case #PB_Event_CloseWindow : Break
        ;Case #PB_Event_Timer       : setTitle()
    EndSelect
  ForEver
EndIf
End

; Procedure getTitleHeight(frm) ;<===== MenuHeight()  de PB
; 	Protected MyRect.RECT
; 	GetClientRect_(WindowID(frm), MyRect)
; 	ProcedureReturn #WinAppHeight - MyRect\bottom
; EndProcedure

Procedure winRoll()
  If WindowHeight(#WinApp) = #WinAppHeight
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll down")
    StickyWindow(#WinApp, #True)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, 350, MenuHeight())
  Else
    SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll up")
    StickyWindow(#WinApp, #False)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, #WinAppWidth, #WinAppHeight)
  EndIf
EndProcedure

Procedure setTitle(t)
  
  Protected Now$
  Static count
  Repeat
    
    Now$ = FormatDate("%hh:%ii:%ss", Date())
    SetWindowTitle(#WinApp, #TITLE$+" : "+Now$+" : "+Str(count))
    count+1
    Delay(t)
  ForEver
EndProcedure

J'utilise aussi la fonction MenuHeight() de PB.

M.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 12:24
par Mesa
Pour mixer boucle et bindevent, c'est tout simple:

Code : Tout sélectionner

EnableExplicit 

#WinApp=10 : #WinAppWidth  = 553 : #WinAppHeight = 416

#TITLE$ = "APP Light Edition"

Global Event, indexMenu

Enumeration Menus
	#MenuApp
EndEnumeration

Enumeration FormMenu
	#MenuAppQuit
	#MenuAppRoll
EndEnumeration

Enumeration Timer
	#Timer
EndEnumeration

Declare winRoll()
Declare setTitle()
Declare OnEnd()

ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_Minimize|#PB_Window_SystemMenu

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #TITLE$, Flags)
	If CreateImageMenu(#MenuApp, WindowID(#WinApp), #PB_Menu_ModernLook)
		MenuTitle("File")
			MenuItem(#MenuAppQuit   , "Exit"+Chr(9)+"Ctrl+Q")
		MenuTitle("~")
			MenuItem(#MenuAppRoll   , "Roll up")
	EndIf
	AddWindowTimer(#WinApp, #Timer, 1000)
	AddKeyboardShortcut(#WinApp, #PB_Shortcut_Escape, #MenuAppQuit)                 ; quit     with ESC
	AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_Q, #MenuAppQuit) ; quit     with CTRL+Q
	AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_R, #MenuAppRoll) ; win roll with CTRL+R
	SetWindowState(#WinApp, #PB_Window_Normal)
	HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
	
	;Gestion des evenements
	BindEvent(#PB_Event_Timer, @setTitle(), #WinApp, #Timer)
	;BindEvent(#PB_Event_CloseWindow, @OnEnd())
	;BindEvent(#PB_Event_Menu, @OnEnd(), #WinApp, #MenuAppQuit)
	;BindEvent(#PB_Event_Menu, @winRoll(), #WinApp, #MenuAppRoll)
	
	;Repeat : WaitWindowEvent(10) : ForEver
		
	Repeat
		Event = WaitWindowEvent(10)
		Select Event
			Case #PB_Event_Menu
			 indexMenu = EventMenu()
			 Select indexMenu
			   Case #MenuAppQuit      : Break
			   Case #MenuAppRoll      : winRoll()
			 EndSelect
			Case #PB_Event_CloseWindow : Break
			;Case #PB_Event_Timer       : setTitle()
		EndSelect
	ForEver
EndIf

; Procedure getTitleHeight(frm)
; 	Protected MyRect.RECT
; 	GetClientRect_(WindowID(frm), MyRect)
; 	Debug MenuHeight() 
; Debug #WinAppHeight - MyRect\bottom
; 	ProcedureReturn #WinAppHeight - MyRect\bottom
; EndProcedure

Procedure winRoll()
	If WindowHeight(#WinApp) = #WinAppHeight
		SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll down")
		StickyWindow(#WinApp, #True)
		ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, 350, MenuHeight())
	Else
		SetMenuItemText(#MenuApp, #MenuAppRoll, "Roll up")
		StickyWindow(#WinApp, #False)
		ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, #WinAppWidth, #WinAppHeight)
	EndIf
EndProcedure

Procedure setTitle()
	Protected Now$
	Static count
	Now$ = FormatDate("%hh:%ii:%ss", Date())
	SetWindowTitle(#WinApp, #TITLE$+" : "+Now$+" : "+Str(count))
	count+1
EndProcedure

Procedure.a doEvents(LOOP.a=255)
	Protected n.a 
	For n = 0 To LOOP
		WindowEvent()
		n + 1
	Next
EndProcedure

Procedure OnEnd()
	End
EndProcedure

M.

Re: Gestion des menus dans la barre des menu en mode expert

Publié : ven. 29/janv./2016 19:37
par cage
En regardant de plus près la fonction SetWindowCallback(), j'ai fini par trouver la (une) solution a mon problème avec la fonction WinRoll().
Maintenant, un clic dans la zone libre de la barre des menus affiche ou replie la fenêtre.
Plus besoin de menu.

J'ai rajouté un SetWindowCallback(@windowCallback(),#WinApp) et la procédure windowCallback(win, msg, wParam, lParam)
Voici le code qui reprend les principales améliorations.

Code : Tout sélectionner

EnableExplicit

#WinApp=10 : #WinAppWidth  = 553 : #WinAppHeight = 416

#TITLE$ = "APP Light Edition"

Global Event, indexMenu

Enumeration Menus
  #MenuApp
EndEnumeration

Enumeration FormMenu
  #MenuAppQuit
  #MenuAppRoll
EndEnumeration

Enumeration Timer
  #Timer
EndEnumeration

Declare windowCallback(win, msg, wParam, lParam)
Declare winRoll()
Declare setTitle()
Declare OnEnd()

ExamineDesktops()
Define X = (DesktopWidth(0)-#WinAppWidth)/2
Define Y = (DesktopHeight(0)-#WinAppHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_Minimize|#PB_Window_SystemMenu

If OpenWindow(#WinApp, X, Y, #WinAppWidth, #WinAppHeight, #TITLE$, Flags)
  If CreateImageMenu(#MenuApp, WindowID(#WinApp), #PB_Menu_ModernLook)
    MenuTitle("File")
      MenuItem(#MenuAppQuit   , "Exit"+Chr(9)+"Ctrl+Q")
  EndIf
  AddWindowTimer(#WinApp, #Timer, 1000)
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Escape, #MenuAppQuit)                 ; quit     with ESC
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_Q, #MenuAppQuit) ; quit     with CTRL+Q
  AddKeyboardShortcut(#WinApp, #PB_Shortcut_Control|#PB_Shortcut_R, #MenuAppRoll) ; win roll with CTRL+R
  SetWindowState(#WinApp, #PB_Window_Normal)
  HideWindow(#WinApp, #False, #PB_Window_ScreenCentered)
 
  ;Gestion des evenements
  BindEvent(#PB_Event_Timer      , @setTitle(), #WinApp, #Timer)
  BindEvent(#PB_Event_CloseWindow, @OnEnd())
  BindEvent(#PB_Event_Menu       , @OnEnd()   , #WinApp, #MenuAppQuit)
  BindEvent(#PB_Event_Menu       , @winRoll() , #WinApp, #MenuAppRoll)
  
  ;Gestion d'évenements particuliers
  SetWindowCallback(@windowCallback(),#WinApp)
  
  Repeat : WaitWindowEvent(10) : ForEver
EndIf

Procedure winRoll()
  If WindowHeight(#WinApp) = #WinAppHeight
    StickyWindow(#WinApp, #True)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, 300, MenuHeight())
  Else
    StickyWindow(#WinApp, #False)
    ResizeWindow(#WinApp, #PB_Ignore, #PB_Ignore, #WinAppWidth, #WinAppHeight)
  EndIf
EndProcedure

Procedure setTitle()
  Protected Now$
  Now$ = FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date())
  SetWindowTitle(#WinApp, #TITLE$+" : "+Now$)
EndProcedure

Procedure windowCallback(win, msg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Select Msg
  Case #WM_MENUSELECT
   ;Debug Str(win)+" "+Str(wparam&$ffff)+" "+Str(lparam&$ffff)
    If (wparam&$ffff)=0 And (lparam&$ffff) = 0
      winRoll()
    EndIf
  EndSelect
  ProcedureReturn Result
EndProcedure

Procedure OnEnd()
  End
EndProcedure