[Implemented] #WM_USER - Private Messages in WindowEvent

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

[Implemented] #WM_USER - Private Messages in WindowEvent

Post by nco2k »

Implemented as PostEvent()

hi folks,

how to find out when a thread has finished??

possible solution could look like:

Code: Select all

#Title = "Thread-Test"

Procedure Thread()
  ;do stuff...
  MessageRequester(#Title, "a hello from our Thread")
  ;end thread...
  SendMessage_(WindowID(0), #WM_USER+1, 0, 0)
EndProcedure

If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
  
  If CreateThread(@Thread(), 0)
    
    Repeat
      WinEvent.l = WaitWindowEvent()
      Select WinEvent
        Case #WM_USER+1 ;<--- but won't work
          ThreadEnd = #True
          Break
        Case #PB_Event_CloseWindow
          WindowEnd = #True
          Break
      EndSelect
    ForEver
    
    If WindowEnd = #False And ThreadEnd = #True
      MessageRequester(#Title, "App was closed AFTER the Thread has finished")
    Else
      MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
    EndIf
    
  EndIf
  
EndIf

End
but that won't work...

so how to leave the WaitWindowEvent() loop, if you can't / don't want to use WindowEvent() instead ??

i did this by a trick for now:

Code: Select all

#Title = "Thread-Test"

Global ThreadEnd.l

Procedure Thread()
  ;do stuff...
  MessageRequester(#Title, "a hello from our Thread")
  ;end thread...
  ThreadEnd = #True
  ResizeWindow(WindowWidth() + 1, WindowHeight() + 1)
EndProcedure

If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title)
  
  If CreateThread(@Thread(), 0)
    
    Repeat
      WinEvent.l = WaitWindowEvent()
      If WinEvent = #PB_Event_SizeWindow
        If ThreadEnd = #True
          Break
        EndIf
      ElseIf WinEvent = #PB_Event_CloseWindow
        WindowEnd = #True
        Break
      EndIf
    ForEver
    
    If WindowEnd = #False And ThreadEnd = #True
      MessageRequester(#Title, "App was closed AFTER the Thread has finished")
    Else
      MessageRequester(#Title, "App was closed BEFORE the Thread could finished")
    EndIf
    
  EndIf
  
EndIf

End
but stil, i think it would be nice if we could check #WM_USER messages in WindowEvent if possible?! i mean #WM_LBUTTONDOWN etc. also work in WindowEvent.

and btw a IsThread() would be very very very... usefull :wink: for something like Repeat : Until IsThread() = #False.

//EDIT:
hmm... or how about a own simple but very usefull and cross platform compatible, pb intern message system??

something like:

Code: Select all

SendPBMessage(99) ;send a value of 99

WinEvent.l = WaitWindowEvent()
Select WinEvent
  Case #PB_Event_Message
    If GetPBMessage() = 99 ;return the value of 99
      MessageRequester("PB-Message", "dance in the rain!")
    Else
      MessageRequester("PB-Message", "drink beer!")
    EndIf
EndSelect
and it also should/could work without a window, cause of the GetPBMessage() command... just think of the possibilities. :shock:

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

You can get the (#WM_USER+1) event in the callback.

Code: Select all

#Title = "Thread-Test" 
Global ThreadEnd

Procedure Thread() 
  ;do stuff... 
  MessageRequester(#Title, "a hello from our Thread") 
  ;end thread... 
  SendMessage_(WindowID(0), #WM_USER+1, 0, 0) 
EndProcedure 

Procedure callback(WindowID, message, wParam, lParam)
  Result = #PB_ProcessPureBasicEvents
  ;
  If message = #WM_USER+1
    ThreadEnd = #True 
  EndIf
  ;
  ProcedureReturn Result
EndProcedure

If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title) 
  
  SetWindowCallback(@callback())
  If CreateThread(@Thread(), 0) 
    
    Repeat 
      WinEvent.l = WaitWindowEvent() 
      If ThreadEnd = #True
        Break
      EndIf
      Select WinEvent 
      Case #PB_Event_CloseWindow 
        WindowEnd = #True 
        Break 
    EndSelect 
  ForEver 
  
  If WindowEnd = #False And ThreadEnd = #True 
    MessageRequester(#Title, "App was closed AFTER the Thread has finished") 
  Else 
    MessageRequester(#Title, "App was closed BEFORE the Thread could finished") 
  EndIf 
  
EndIf 
  
EndIf 

End
But it's easier to directly set ThreadEnd = #True at the end of the thread.

Code: Select all

#Title = "Thread-Test" 
Global ThreadEnd

Procedure Thread() 
  ;do stuff... 
  MessageRequester(#Title, "a hello from our Thread") 
  ;end thread... 
  ThreadEnd = #True
EndProcedure 

If OpenWindow(0, 0, 0, 480, 320, #PB_Window_TitleBar | #PB_Window_SystemMenu | #PB_Window_ScreenCentered, #Title) 
  
  If CreateThread(@Thread(), 0) 
    
    Repeat 
      WinEvent.l = WaitWindowEvent() 
      If ThreadEnd = #True
        Break
      EndIf
      Select WinEvent 
      Case #PB_Event_CloseWindow 
        WindowEnd = #True 
        Break 
    EndSelect 
  ForEver 
  
  If WindowEnd = #False And ThreadEnd = #True 
    MessageRequester(#Title, "App was closed AFTER the Thread has finished") 
  Else 
    MessageRequester(#Title, "App was closed BEFORE the Thread could finished") 
  EndIf 
  
EndIf 
  
EndIf 

End
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

With SendMessage_(), the message only arrives in the callback. To get the
message in the main loop, you must use PostMessage_() instead.
quidquid Latine dictum sit altum videtur
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@gnozal
erm... did you acctually read what i said?!

this IS the problem... a window event is needed, to check the ThreadEnd variable, so a callback or your other code is useless without a window event.

if you dont move your mouse over your window, or an other event doesnt appear, nothing will happen until then... :roll: maybe its a bad example code because after closing a MessageRequester() the window becomes active and returns a event.

//EDIT:

@freak
you are right, this is great! and i just thought the only difference between SendMessage_() and PostMessage_() is that PostMessage_() doesnt wait for the message to proceed.

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: #WM_USER - Private Messages in WindowEvent

Post by PB »

> how to find out when a thread has finished?

Use a global variable? For example: the app below won't let you close the window
until the thread has finished:

Code: Select all

Global MyThread

Procedure Thread()
  Delay(Random(4000)+1000) ; Delay for 1-5 seconds.
  MyThread=1
EndProcedure

If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
  If CreateThread(@Thread(), 0)
    Repeat : Until WaitWindowEvent()=#PB_EventCloseWindow And MyThread=1
  EndIf
EndIf
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@PB
Use a global variable?
i tried this already.
the app below won't let you close the window
until the thread has finished
and until a window event returns. and that was the problem.

i dont want to close the window. i just wanted, to modify it after the thread has finished, without the need of an user to "force" a window event... but the tip with PostMessage_() works great. :D

p.s.: without a window event, you can wait for hours. :wink:

Code: Select all

Global MyThread

Procedure Thread()
  Delay(Random(4000)+1000) ; Delay for 1-5 seconds.
  MyThread=1
EndProcedure

If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
  If CreateThread(@Thread(), 0)
    Repeat : If MyThread=1 : Break : EndIf : Until WaitWindowEvent()=#PB_EventCloseWindow
  EndIf
EndIf
c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> i dont want to close the window

That was just an example to show that the app was waiting until the thread
was finished -- just like you asked. :)

> If MyThread=1 : Break : EndIf

What point are you making here? Of course this lets you close the window,
because MyThread won't be 1 until the delay has passed. I still fail to see
what the problem is. You asked "how to find out when a thread has finished"
and I showed you. Maybe you can show me some code that is causing you
a problem? It all seems cut-and-dry to me... :?:

> this IS the problem... a window event is needed, to check the ThreadEnd variable

Huh? No window event is needed, observe:

Code: Select all

Global ThreadEnd

Procedure Thread()
  Delay(3000)
  ThreadEnd=1
EndProcedure

CreateThread(@Thread(),0)

Debug "Wait for thread to end after 3 seconds..."
Repeat : Delay(1) : Until ThreadEnd=1
Debug "Thread ended!"
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

So, it depends on how the loop is handled, right? Or wrong?

With waitWindowEvent() you just keep waiting until something happens to trigger an event. But the other apps love you because you're no hog.

With WindowEvent() you get to check the flag each pass through but you are less friendly to the other apps, even with delay?

With callback you get a friendly prod? ( I love callbacks - everything should have a callback option :) ).

And the extra event mooted here would allow WaitWindowEvent good-neighbourliness along with the ability to check for the event you wanted?



What would be nice would be a way to inform the PureBasic controller which extra events to let through. LetThisDogLoose(eventInfo). It could build a table and check ... :)
@}--`--,-- A rose by any other name ..
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@PB
What point are you making here?
that was an example that nothing will happen, without a window event.
You don't need to "force" a window event or anything
of course you have to, because without a window event the code wont go on.
You asked "how to find out when a thread has finished"
and I showed you.
well you showed me how to find out when a thread is finished, but with the need of a window event to check the variable. i was just triyng to check if a thread has finished, without the need to move the window or something like that, to check the global variable and thats what i do now, with the PostMessage_(WindowID(0), #WM_USER+1, 0, 0) without problem. so i "force" a event with this command.

sure the easiest way would be WindowEvent() instead of WaitWindowEvent() but thats another story.
Huh? No window event is needed, observe:
this is so silly, cause there is no Window + WaitWindowEvent(). :roll:

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@PB
yeah and thats a whole other world, cause there is no WaitWindowEvent() which "freeze" your app without a event... so you can go on with the variable checking without any probs... no big deal.

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> you showed me how to find out when a thread is finished, but with the
> need of a window event to check the variable

Because that was just an example... you didn't specify how or when you
need the variable checked, so I did my example in the manner of the user
not being able to exit the app until the thread ends. Sheesh, I can't win! :(
Last edited by PB on Mon Sep 05, 2005 1:16 pm, edited 1 time in total.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> i was just triyng to check if a thread has finished, without the need to move
> the window or something like that, to check the global variable

This is what I don't understand... you don't NEED to move the window, or force
a window event, to check the value of the global variable. Can you show me
a situation where you need to -- where it WON'T work without it? Thanks.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@PB
yes of course, i didnt want to say your example is wrong or bad or something like that, only that its dependent to a window event.

ok deal... how would you break this loop after the thread has finished, without the need for a callback or a window event, only by just looking with your eyes. :)

Code: Select all

Procedure Thread()
  Delay(Random(4000)+1000)
EndProcedure

If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
  
  If CreateThread(@Thread(), 0)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          End
      EndSelect
    ForEver
    
    MessageRequester("test", "test")
    
  EndIf
  
EndIf

End
i showed you already a example where a window event is needed, dont forget moving your mouse causes events too.

Code: Select all

Global ThreadEnd.l

Procedure Thread()
  Delay(Random(4000)+1000)
  ThreadEnd = #True
EndProcedure

If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test")
  
  If CreateThread(@Thread(), 0)
    
    Repeat
      
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          End
      EndSelect
      
      If ThreadEnd = #True
        Break
      EndIf
      
    ForEver
    
    MessageRequester("test", "test")
    
  EndIf
  
EndIf

End
c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> how would you break this loop after the thread has finished

Your second example shows how... let it run and it breaks automatically when
the thread finishes -- just as I would have done -- and it doesn't use a window
event to do it (it just checks the global var alone and breaks accordingly).

I still fail to see any problem here. Maybe I just don't understand what you're
asking. It seems so simple and straightforward to me, that your questions are
starting to confuse me. :lol:
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Post by nco2k »

@PB
yes i think, you dont understand what i mean. :D

wait 15 seconds without causing any events... the MessageRequester() wont appear... only after a event happens.

Code: Select all

Global ThreadEnd.l 

Procedure Thread() 
  Delay(Random(4000)+1000) 
  ThreadEnd = #True 
EndProcedure 

If OpenWindow(0, 300, 200, 480, 320, #PB_Window_SystemMenu, "test") 
  
  If CreateThread(@Thread(), 0) 
    
    Repeat 
      
      WinEvent.l =  WaitWindowEvent() 
      Debug "EVENT!!"
      If ThreadEnd = #True 
        Break 
      EndIf 
      If WinEvent = #PB_Event_CloseWindow 
        End 
      EndIf 
      
    ForEver 
    
    MessageRequester("test", "test") 
    
  EndIf 
  
EndIf 

End
dont forget to put your cursor miles away of the window.

i dont say you need a event to check a variable, i just say, you need a event that the programm goes on, so it can check the variable.


c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
Post Reply