Re: Multiple window problem
Posted: Tue Oct 20, 2015 5:30 am
You should always check for a valid PB event, and ignore all other as they are generated by the OS. If you can demonstrate the bug with valid PB event, I will take a look.
http://www.purebasic.com
https://www.purebasic.fr/english/
The correct affects follow the interactioon with some gadgets. It happens in my example it works when the mouse moves over the button but not when it moves over the listview gadget.collectordave wrote:This gives all the same effects as before however if you click on the main window PB reports lots af main window events (mouseMove) carefully move the mouse pointer to the second window and it still reports events for the main window until you move the mouse pointer onto the canvas gadget when hey presto the events are assigned correctly.
All messages intended for PureBasic-created windows would be intercepted by its WaitWindowEvent() function; but that does not mean that PureBasic would process them all.collectordave wrote:I have allways assumed that events\messages passed to my message loop were all valid.
Even if this bug is not fixed it is good to know that eventwindow does not work correctly in all situations.
Since each gadget in a single PureBasic project is assigned unique identifiers, regardless of their parent window, you don't need to determine the event window to process their events.collectordave wrote:...to do this I must be certain that first of all EventWindow() is reporting the event on the correct window then on the correct gadget. Getting to be a nightmare.
Code: Select all
OpenWindow(1000, 0, 0, 600, 220, "MainWindow")
String_0 = StringGadget(#PB_Any, 90, 20, 340, 30, "")
Repeat
event = WaitWindowEvent()
Select Event
Case 513
SetGadgetText(String_0,"Left Button Down")
Case 514
SetGadgetText(String_0,"Left Button Up")
Case 515
SetGadgetText(String_0,"Left Button Double Click")
Case 516
SetGadgetText(String_0,"Right Button Down")
Case 517
SetGadgetText(String_0,"Right Button Up")
Case 518
SetGadgetText(String_0,"Right Button Double Click")
Case 519
SetGadgetText(String_0,"Middle Button Down")
Case 520
SetGadgetText(String_0,"Middle Button Up")
Case 522
SetGadgetText(String_0,"Middle Wheel")
EndSelect
Until event = #PB_Event_CloseWindow
You simply process the PureBasic events and leave the rest to fend for themselves.collectordave wrote:I think I posted earlier, can these non official events be prevented from reaching the message loop in my program? Or is there a way of finding whether it is an official PB event so it can be discarded in my message loop before an attempt to find on which window the event occurred?
Code: Select all
;Author: Demivec
;Date: 10/20/2015
;Written for: PureBasic v5.40 LTS
;General example of a classic event message loop.
;
;Using BindEvent(), BindGadgetEvent(), BindMenuEvent() are powerful alternatives to
;processing events with through the event loop. There is also the use of SetWindowCallback()
;for handling all events generated by the OS that may or may not be handled through
;PureBasic's own message handling functions.
;This code only includes a single window. You would typically place your windows, gadgets,
;and so forth here before the event loop.
OpenWindow(0, 0, 0, 600, 220, "MainWindow", #PB_Window_SystemMenu)
Define event, quit
Repeat
Repeat
event = WindowEvent() ;or WaitWindowEvent()
Select event
Case #PB_Event_Menu
; Select EventMenu()
; Case 0 ;Customize to handle specific menu numbers (or toolbar or keyboard shortcuts)
; Default
Debug "Menu: " + EventMenu() + ", window: " + EventWindow()
; EndSelect
Case #PB_Event_Gadget
; Select EventGadget()
; Case 0 ;Customize to handle specific gadget numbers.
; Default
;Events are neither reported nor handled by every gadget type,
;refer to documentation for specific gadget type for further info.
;The CanvasGadget(), WebGadget() and OpenGLGadget() each also support a special set of events.
Debug "Gadget: " + EventGadget() + ", type: " + EventType() + ", window: " + EventWindow()
; EndSelect
Case #PB_Event_SysTray
Select EventGadget()
Case 0 ;Customize to handle specific system tray icon numbers.
Default
Debug "SysTrayIcon: " + EventGadget() + ", type: " + EventType()
EndSelect
Case #PB_Event_Timer
; Select EventTimer()
; Case 0 ;Customize to handle specific system tray icon numbers.
; Default
Debug "Timer: " + EventTimer() + ", window: " + EventWindow()
; EndSelect
Case #PB_Event_WindowDrop
; Select EventWindow()
; Case 0 ;Customize to handle specific windows as drop targets.
; Default
Debug "Drop onto Window : " + EventWindow() + ", type: " + EventDropType() + ", action: " + EventDropAction()
;Further functions to handle the event may include:
; EventDropText(), EventDropImage(), EventDropFiles(), EventDropPrivate(),
; EventDropBuffer(), EventDropSize(), EventDropX(), EventDropY()
; EndSelect
Case #PB_Event_GadgetDrop
; Select EventGadget()
; Case 0 ;Customize to handle specific gadgets as drop targets.
; Default
Debug "Drop onto Gadget : " + EventGadget() + ", type: " + EventDropType() + ", action: " + EventDropAction() + ", window: " + EventWindow()
;Further functions to handle the event may include:
; EventDropText(), EventDropImage(), EventDropFiles(), EventDropPrivate(),
; EventDropBuffer(), EventDropSize(), EventDropX(), EventDropY()
; EndSelect
Case #PB_Event_CloseWindow
Debug "CloseWindow: " + EventWindow() ;Custom handling for specific windows is possible.
quit = 1
Case #PB_Event_Repaint
Debug "Repaint: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_SizeWindow
Debug "SizeWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_MoveWindow
Debug "MoveWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_MinimizeWindow
Debug "MinimizeWindow : " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_MaximizeWindow
Debug "MaximizeWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_RestoreWindow ;Custom handling for specific windows is possible.
Debug "RestoreWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_ActivateWindow
Debug "ActivateWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_DeactivateWindow
Debug "DeactivateWindow: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_RightClick
Debug "RightClick: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_LeftClick
Debug "LeftClick: " + EventWindow() ;Custom handling for specific windows is possible.
Case #PB_Event_LeftDoubleClick
Debug "LeftDoubleClick: " + EventWindow() ;Custom handling for specific windows is possible.
Default
If event <> 0
;This includes events posted with PostEvent() and all 'OS events' that are not handled by the PureBasic message loop.
;If using custom PostEvent() compare the event to their numbers for proper handling, further details may then
; be obtained with: EventWindow(), EventGadget(), EventType(), EventData()
;IF not using custom PostEvent(), IMHO OS events should be handled with a window callback procedure.
;Debug "Unhandled Event: " + event
EndIf
EndSelect
Until event = 0 Or quit = 1
Delay(10) ;Delay() frees the CPU for the multitasking
Until quit = 1
First I do not want to handle the specific OS messages just the official PB messages. So whatever the place to habdle OS specific messages is just not relevent.Incidentally, if the WindowCallback is used, it would handle the specific OS messages and then pass control to the PureBasic message loop to process the rest. IMHO this means that the PureBasic message loop is not the proper place to handle OS event messages (at least not in the current version of PureBasic) if you are going to handle them at all.
I do not want to hadle them at all! Again it is the erronous result from EventWindow that causes the problem where it rerports the originating window incorrectly.Incidentally, if the WindowCallback is used, it would handle the specific OS messages and then pass control to the PureBasic message loop to process the rest. IMHO this means that the PureBasic message loop is not the proper place to handle OS event messages (at least not in the current version of PureBasic) if you are going to handle them at all.
What gets in the way is that EventWindow() does not report the correct window on which an event takes place in every case, as shown in the first post, and also does not default to -1 or a non existent window causing the meaage loop of the second window to be called.
So nothing at all should get in the way.
This sounds important.Some events can be fired here and here, you have to test for a specific event (like PB_Event_CloseWindow etc.). Just monitoring if a window gets an event isn't reliable (and doesn't make sens).
Code: Select all
OpenWindow(1000, 0, 0, 600, 220, "MainWindow", #PB_Window_SystemMenu)
OpenWindow(1001, 300, 300, 280, 180, "Wnd2", #PB_Window_SystemMenu)
Repeat
event = WaitWindowEvent()
Select event
Case #PB_Event_Menu ,
#PB_Event_Gadget ,
#PB_Event_SysTray ,
#PB_Event_Timer ,
#PB_Event_CloseWindow ,
#PB_Event_Repaint ,
#PB_Event_SizeWindow ,
#PB_Event_MoveWindow ,
#PB_Event_MinimizeWindow ,
#PB_Event_MaximizeWindow ,
#PB_Event_RestoreWindow ,
#PB_Event_ActivateWindow ,
#PB_Event_DeactivateWindow,
#PB_Event_WindowDrop ,
#PB_Event_GadgetDrop ,
#PB_Event_RightClick ,
#PB_Event_LeftClick ,
#PB_Event_LeftDoubleClick
; only after a valid event we can check the return of EventWindow()
Select EventWindow()
Case 1001
Debug "Wnd2"
Case 1000
Debug "MainWindow"
EndSelect ;EventWindow()
EndSelect
Until event = #PB_Event_CloseWindow
Thanks for reading it all. Your solution to the eventwindow problem works fine. Now all I have to do is add that to all main message loops in my progs where i use multiple windows.I think I posted earlier, can these non official events be prevented from reaching the message loop in my program? Or is there a way of finding whether it is an official PB event so it can be discarded in my message loop before an attempt to find on which window the event occurred?
Sorry about this. Checked PB help file and manual and can find no reference to this being a requirement. So maybe the PB documentation should be updated to show this?If you modify your code with the below (as per PB requirements) you can see that everything is in harmony:
From the PureBasic documentation:collectordave wrote:Checked PB help file and manual and can find no reference to this being a requirement. So maybe the PB documentation should be updated to show this?
Code: Select all
Repeat
; Wait until a new window or gadget event occurs.
Event = WaitWindowEvent()
; In programs with more than one form, which window did the event occur on.
EventWindow = EventWindow()
; Which gadget did the event occur on.
EventGadget = EventGadget()
; What sort of event occurred.
EventType = EventType()
; Take some action.
Select Event
Case #PB_Event_Gadget
; A gadget event occurred.
If EventGadget = #Folder
ElseIf EventGadget = #Files
EndIf
Case #PB_Event_CloseWindow
; The window was closed.
If EventWindow = #WindowFiles
CloseWindow(#WindowFiles)
Break
EndIf
EndSelect
; Go round and do it again.
; In practice the loop isn't infinite because it can be stopped by clicking the window's Close button.
ForEver
Is what I was following and hit the problem allthough it is probably a million to one chance. The quote is from the PB documentation and is clearly incorrect as everyone has been saying.; Wait until a new window or gadget event occurs.
Event = WaitWindowEvent()
; In programs with more than one form, which window did the event occur on.
EventWindow = EventWindow()