Multiple window problem

Just starting out? Need help? Post your questions and find answers here.
Fred
Administrator
Administrator
Posts: 16687
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Multiple window problem

Post by Fred »

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.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

I am trying to ignore these messages, as you can tell from the shortened code.

It is not the message parsee it is PBs handling of the message, it is reporting messages originating on one window as if they originated on another. It seems that as PB does not recognise the mousemove event on a window that the originating window handle is not passed on but is left at the last window handle that PB dealt with. This gives the effects mentioned. Click on one window and the focus is set, PB passes on the window handle move mouse to second window and windows messages for the second windoe are reported as originating on the first window.

The 512 message would also also seem to be a valid PB event

#PB_EventType_MouseMove for the Canvas gadget. Just not for the window.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

Reading my own post got me thinking again.

I added a canvas gadget to the 2nd window

OpenWindow(1000, 0, 0, 600, 220, "MainWindow")
OpenWindow(1001, 300, 300, 280, 180, "Wnd2")
CanvasGadget(500, 10, 10, 180, 100)

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.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Multiple window problem

Post by Demivec »

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.
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
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

Hi

Yes it does seem to vary with what events are supported by PB on which gadget.

Trying to imagine what is going on here.

1.

Mouse moves over window.

Windows sends message to PB message loop.

PB looks at message and decides it does not support mousemove events on windows so does nothing

PB passes message onto the running programme for processing

2.
Mouse moves over gadget that supports mousemove events

PB ensures gadgetID and windowID are added to the message and passes message to the message loop of the programme.

All works fine.

If in the PB message loop the message was simply ignored and not passed on then no problem message ends it's life in the PB loop. A little more efficient I would think.

If PB is going to pass the message on, I feel it should at least use the correct originating window so EventWindow() can work correctly.

I can't imagine why anyone would want to react to a mousemove event on a window but it would just be another string in PBs bow if that were available.

I am also left wondering how many other events\messages are sent to the message loop with incorrect info attached and from how many gadgets.

This left me wondering how to check for a valid PB event. In this case the mousemove event.

As the event is supported by some gadgets i cannot just look at event type, i must also check that the message originates from a gagdet that does not support mousemove. Of course 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.

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.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Multiple window problem

Post by TI-994A »

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.
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.

Your code simply displays every message that is intercepted. The reason that the event window is not being updated is because PureBasic windows do not process any mouse events. And although it is updated when the window is clicked, the window is only responding to a focus event, and not the mouse-click per se.

The canvas is one of the gadgets that does process mouse events, and that is why the window event gets updated when the mouse hovered over its canvas gadget.
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.
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.

Sleep tight; no bugs, no nightmares. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Fred
Administrator
Administrator
Posts: 16687
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Multiple window problem

Post by Fred »

It seems to be a misunderstanding here. All PB commands like EventWindow(), EventGadget() etc. works only when dealing with official PB events #PB_Event_xxxx . All other events are push by the OS and the PB functions aren't in sync with them. If you want to handle them, the best is to use a regular Windows callback as you would do in C.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

Thanks I can understand all that.

The original post was about EventWindow().

In the help file it says

After a WindowEvent() or WaitWindowEvent() function, use this function to determine on which window the event has occurred.

As shown in the first and some subsequent posts EventWindow() does not allways return the window on which the event occurred.

The problem for me is this. I open a second window to get user input. After the user has entered the details they click a Button to Apply these canges, which are applied after the second window event loop. What happens the user then moves to the main window and the mouse move event being passed to the main window message loop is then routed to the second windows message loop by EventWindow() after which the post event processing happens again. This at best causes flicker on some of the updated gadgets on the main window. This is what made me look in the first place.

I can understand that Eventwindow() etc only works with official PB events, quite reasonable. However, again as shown in the first post, EventWindow() does return a valid windowID with some non official PB events under some circumstances.

As a test I have looked at what other events maybe reported to the main event loop as well. Concentrating on mouse events.

Try this code. The window responds to mouse events. I have not tried these with the double window scenario so keeping away from event window.

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
I have not tried mousemove etc as they are reported anyway. So as a programmer, I can use this undocumented feature to have a bare window respond to mouse events. When trying the button double clicks please remember a button up event is fired immediatly after so watch the string gadget very carefully or use a message requester to show the double click.

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?

At the end I am quite happy to deal with just official PB events and have no wish to get involved in window callbacks etc.

Just a quick warning to anyone who, like me, is writing cross platform code, the above is windows only. To write cross platform compatible code only use the official pb Events. The bare window still reacts to the mouse with such things as #PB_Event_Leftclick etc all documented.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Multiple window problem

Post by Demivec »

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?
You simply process the PureBasic events and leave the rest to fend for themselves.

Here's an extensive and noisy example to show what is handled by PureBasic's message loop. I made the example to use as a reference for myself and I hope it is useful in answering your question as well. It is possible I may have made overlooked something but it was created with reference to the documentation. It makes an effort in the source code to show how various events are generated and what information is available to handle them.

In general everything is handled with Select/Case statements. At the very end is a 'default' case. The events that end up there are ones created using PostEvent(), the 'no event' (i.e. #Null), and events that aren't handled by PureBasic. So after you filter out any PostEvent() messages the rest you can ignore or properly handle by using SetWindowCallback().

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.

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
There has been postings on the meaning of events generated where the window, or gadget event is '0' (a non-documented value). For gadget events it means the gadget has only one event, such as a clicking on a check-box. For windows any events for window -1 should be ignored (as they are not valid events).


@Edit: Changed code to no longer require debugger on to run. Running it without the debugger will keep it from displaying any information but it will operate correctly.
Last edited by Demivec on Fri Jan 01, 2016 10:05 pm, edited 5 times in total.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

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.
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.

Back to the first post. the PB function EventWindow() does not allways return the correct window on which the event occurred. Id EventWidow() returned -1 for something that is not supported then that would be OK as it would not send the message to another existent window but would be ignored.
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.

So nothing at all should get in the way.
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.

Seems there is a lot of missunderstanding here.

1. It all has nothing to do with the messages whether PB official or not.

2. It is only the fact that EventWindow() sometimes returns an incorrect window for the originating event/ message.

Can we forget about what messages are recieved or sent. The fact, and it is a fact, EventWindow() does not allways return the correct window on which an event takes place.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
ElementE
Enthusiast
Enthusiast
Posts: 139
Joined: Sun Feb 22, 2015 2:33 am

Re: Multiple window problem

Post by ElementE »

Fred wrote:
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).
This sounds important.
Why is just monitoring a window for an event not sufficient?
Could someone explain this in more detail, perhaps with an example?
Think Unicode!
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: Multiple window problem

Post by said »

Hi collectordave,

Your claim is very logic but i believe you are missing an important point that Fred, TI994A, Demivec,... have been trying to explain many times, i will try (though am sure my english is far worse than theirs :( ) ...

The number of events managed by WaitWindowEvent()/WindowEvent() is very limited, these are called valid PB-events:
#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 PB event, all related commands EventWidnow(), EventGadget(), EventMenu(), .... are expected to hold valid results.
So only after a valid PB event you can check the results of those commands; Otherwise there is no guarantee that those commands return valid result that we can use. IMO what's happening in your simple code of the 2 windows is that EventWindows() is continuously called without being updated properly because they got updated only after a PB event

If you modify your code with the below (as per PB requirements) you can see that everything is in harmony:

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
I hope this helps!
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

Hi Said

Thankyou. I wrote earlier.
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?
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.

Said Wrote
If you modify your code with the below (as per PB requirements) you can see that everything is in harmony:
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?
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Multiple window problem

Post by TI-994A »

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?
From the PureBasic documentation:

UserGuide - Building a graphical user interface

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
Nevertheless, the logical sequence in a WaitWindowEvent() loop would be to check the returned event first; and only thereafter, determine the windows, gadgets, and types.

It's programming 101; even in a C message loop, the events such as WM_CREATE, WM_PAINT, WM_DESTROY, etc., are intercepted first, before determining the window.

You're placing the horse before the cart. :lol:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Multiple window problem

Post by collectordave »

Couldn't agree more so
; 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()
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.

The solution from said above should really be included in the documentation so that events are checked first and then move on to the rest.

If that had been in the documentation in the first place no problem would have occurred.

Is someone going to suggest that it be included?
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
Post Reply