UnbindEvent im zweiten Fenster

Anfängerfragen zum Programmieren mit PureBasic.
matbal
Beiträge: 261
Registriert: 30.03.2011 20:53

UnbindEvent im zweiten Fenster

Beitrag von matbal »

Ich habe bei einigen Projecten den EM_EventManager von ts-soft verwendet, der sehr problemlos zu benutzen ist. BindEvent() und UnbindEvent() arbeite ja ähnlich. Es müßte möglich sein, die Eventverarbeitung eines Programms ausschließlich mit diesen beiden Befehlen aufzubauen.

Es ist allerdings nicht ganz so einfach zu handhaben, da man sich selber um das Lösen der Events kümmern muß, wenn man ein Fenster schließen will, an dem man mit BindEvent Prozeduren geknüpft hat.

Das, was ich will, ist also eigentlich ganz einfach. Meine Form2 hat zusätzlich zur Schaltfläche in der Titelleiste einen Close-Button und Close-Menüeintrag, um das Fenster zu schließen. Beim Schließen rufe ich eine Event-Prozedur auf, die zuerst alle UnbindEvent Aufrufe ausführt und dann CloseWindow. Allerdings scheint die Reihenfolge der UnbindEvent-Aufrufe sehr wichtig zu sein. In meinem Beispiels-Code werden je nachdem, wie ich Form2 schließe, noch falsche Events ausgelöst. Ein Teil der Fehler fange ich ab, da ich in meiner Prozedur Form2_Close erst prüfe, ob die Form2 überhaupt noch geöffnet ist.

Der Code ist etwas Lang, da ich alle Form.pbf und Declares in eine Datei zusammenkopiert habe.

Code: Alles auswählen

EnableExplicit

;{ XIncludeFile "Form1.pbf"
;- Form 1 -------------------------------------------------
Enumeration FormWindow
   #Form1
EndEnumeration

Enumeration FormGadget
   #Form1_Button_Form2
EndEnumeration


Procedure OpenForm1(x = 0, y = 0, width = 595, height = 350)
   OpenWindow(#Form1, x, y, width, height, "Form1", #PB_Window_SystemMenu)
   ButtonGadget(#Form1_Button_Form2, 495, 10, 85, 25, "Form2")
EndProcedure
;}
;{ XIncludeFile "Form2.pbf"
;- Form 2 -------------------------------------------------
Enumeration FormWindow
   #Form2
EndEnumeration

Enumeration FormGadget
   #Form2_Button_Close
   #Form2_Panel
   #Form2_Button_1
   #Form2_Button_2
   #Form2_Button_3
EndEnumeration

Enumeration FormMenu
   #Form2_MenuItem_Close
EndEnumeration


Procedure OpenForm2(x = 0, y = 0, width = 360, height = 235)
   OpenWindow(#Form2, x, y, width, height, "Form2", #PB_Window_SystemMenu | #PB_Window_WindowCentered, WindowID(#Form1))
   CreateMenu(0, WindowID(#Form2))
   MenuTitle("File")
   MenuItem(#Form2_MenuItem_Close, "Close")
   ButtonGadget(#Form2_Button_Close, 255, 180, 90, 25, "Close")
   PanelGadget(#Form2_Panel, 5, 5, 350, 165)
   AddGadgetItem(#Form2_Panel, -1, "Tab 1")
   ButtonGadget(#Form2_Button_1, 15, 18, 85, 25, "Test 1")
   ButtonGadget(#Form2_Button_2, 15, 48, 85, 25, "Test 2")
   ButtonGadget(#Form2_Button_3, 15, 78, 85, 25, "Test 3")
   CloseGadgetList()
EndProcedure
;}
;{ IncludeFile "Declare.pbi"
;--------------------------------------------------------------
Declare Form1_Open()
Declare Form1_Close()
Declare Form1_Button_Form2()

Declare Form2_Open()
Declare Form2_Close()
Declare Form2_Close_Event()
Declare Form2_Button_Close()
Declare Form2_Button_1()
Declare Form2_Button_2()
Declare Form2_Button_3()
Declare Form2_MenuItem_Close()
;}

;---- Form1 Procs ------------------------------------

Procedure Form1_Open()
   OpenForm1()
   BindEvent(#PB_Event_CloseWindow, @Form1_Close(), #Form1)
   BindGadgetEvent(#Form1_Button_Form2, @Form1_Button_Form2())
EndProcedure
Procedure Form1_Close()
   CloseWindow(#Form1)
   End
EndProcedure
;-----
Procedure Form1_Button_Form2()
   Form2_Open()   
EndProcedure

;---- Form2 Procs ------------------------------------

Procedure Form2_Open()
   DisableGadget(#Form1_Button_Form2, 1)
   
   OpenForm2()
   
   BindGadgetEvent(#Form2_Button_1, @Form2_Button_1())
   BindGadgetEvent(#Form2_Button_2, @Form2_Button_2())
   BindGadgetEvent(#Form2_Button_3, @Form2_Button_3())
   BindGadgetEvent(#Form2_Button_Close, @Form2_Button_Close())
   BindMenuEvent(0, #Form2_MenuItem_Close, @Form2_MenuItem_Close())
   BindEvent(#PB_Event_CloseWindow, @Form2_Close_Event(), #Form2)
   
EndProcedure
Procedure Form2_Close()
   
   If IsWindow(#Form2)
      Debug "CloseWindow Form2"
      
      UnbindEvent(#PB_Event_CloseWindow, @Form2_Close_Event(), #Form2)
      UnbindMenuEvent(0, #Form2_MenuItem_Close, @Form2_MenuItem_Close())
      UnbindGadgetEvent(#Form2_Button_1, @Form2_Button_1())
      UnbindGadgetEvent(#Form2_Button_Close, @Form2_Button_Close())
      UnbindGadgetEvent(#Form2_Button_2, @Form2_Button_2())
      UnbindGadgetEvent(#Form2_Button_3, @Form2_Button_3())
      
      CloseWindow(#Form2)
      DisableGadget(#Form1_Button_Form2, 0)
   Else
      Debug "ERROR: Missing Window Form2"
   EndIf
EndProcedure
Procedure Form2_Close_Event()
   Debug "----------"
   Debug "Window Schließfeld in Titelleiste angeklickt"
   
   ;UnbindEvent(#PB_Event_CloseWindow, @Form2_Close_Event(), #Form2)
   Form2_Close()
   
EndProcedure
;-----
Procedure Form2_MenuItem_Close()
   Debug "----------"
   Debug "Menu Close ausgewählt"
   
   ;UnbindMenuEvent(0, #Form2_MenuItem_Close, @Form2_MenuItem_Close())
   Form2_Close()   
   
EndProcedure
;-----
Procedure Form2_Button_Close()
   Debug "----------"
   Debug "Button Close angeklickt"
   
   ;UnbindGadgetEvent(#Form2_Button_Close, @Form2_Button_Close())
   Form2_Close()   
   
EndProcedure
Procedure Form2_Button_1()
   Debug "Button Test 1 angeklickt"   
EndProcedure
Procedure Form2_Button_2()
   Debug "Button Test 2 angeklickt"
EndProcedure
Procedure Form2_Button_3()
   Debug "Button Test 3 angeklickt"
EndProcedure

;----------------------------------------
;----------------------------------------

Form1_Open()

While IsWindow(#Form1)
   WaitWindowEvent()
Wend
Arbeite UnbindEvent fehlerhaft, oder muß ich noch etwas beachten? Oder sollte man diese Funktionen gar nicht so einsetzen?

Wie gesagt, es geht um das Schließen eines Fensters. Code ausführen und Form2 öffnen. Wenn ich auf Form2 dann den Button Close anklicke, wird noch ein Klick auf Test1 ausgelöst, dann ein Menu-Close, und dann #PB_Event_CloseWindow. Bei den letzen beiden Events ist das Fenster aber schon geschlossen.

Wenn ich die UnbindEvent()-Aufrufen in meiner Prozedur Form2_Close() anders umsortiere, kann es passieren, daß auch andere Fehler auftreten (ungültiger Speicherzugriff...)

Eine Lösung habe ich gefunden (Workaround?): Es werden beim Unbinden keine falschen Events mehr abgefeuert, wenn ich zuerst das Event löse, womit ich das Fenster schließen will. Also beim Klick auf den Close-Button löse ich zuerst den Button, beim Klick auf Close-Menü löse ich zuerst den Menüeintrag, beim Klick auf die Schaltfläche in der Titelzeile löse ich zuerst das WindowsEvent #PB_Event_CloseWindow. Einfach die auskommentierte UnbindEvents-Zeilen in Form2_Close_Event(), Form2_MenuItem_Close(), Form2_Button_Close() aktivieren, und es treten keine Fehler mehr auf.

Leider benötige ich so immer separate Event-Prozeduren zum Schließen, um unterscheiden zu können, wer der Auslöser war.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: UnbindEvent im zweiten Fenster

Beitrag von hjbremer »

Ich dir vollkommen zu !
Die Arbeit mit Fenstern und den BindEvent Befehlen ist noch nicht perfekt und einfach.

Dein Workaround ist nicht schlecht, hat aber eben die von dir erwähnten Nachteile.

Ich hatte als Lösung dies ebenfalls versucht, aber haufenweise Bindevent Befehle zu verwenden ist in meinen Augen nur suboptimal (vorsichtig ausgedrückt)

Meine Lösung bestand nun darin, das Fenster nicht zu schliessen, sondern unsichtbar zu machen und bei Bedarf wieder hervorzuholen.

Aber ich habe Hoffnung, bestimmt findet einer eine geniale Lösung.
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Antworten