MessageRequester on a separate thread (?)

Just starting out? Need help? Post your questions and find answers here.
AZJIO
Addict
Addict
Posts: 1312
Joined: Sun May 14, 2017 1:48 am

MessageRequester on a separate thread (?)

Post by AZJIO »

How to issue a message in Windows, which will be a separate process not associated with the program?
I suppose it is possible to make a vbs script in the temp folder and execute it.
I need a way that does not block program events.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: MessageRequester on a separate thread (?)

Post by TI-994A »

Perhaps, just use a separate window to emulate a message box. In this example, the message box window stays on top until dismissed, but the running clock in the main window demonstrates that it does not block the event loop:

Code: Select all

Enumeration windows
  #mainWindow
  #messageBox  
EndEnumeration

Enumeration gadgets
  #mainWindowButton
  #mainWindowClock
  #mainWindowTimer
  #messageBoxButton
  #messageBoxText
EndEnumeration

Global mainWindowFlags = #PB_Window_SystemMenu |
                         #PB_Window_SizeGadget |                
                         #PB_Window_ScreenCentered |
                         #PB_Window_MaximizeGadget |
                         #PB_Window_MinimizeGadget

Procedure messageBox(title.s, message.s)
  OpenWindow(#messageBox, 10, 10, 200, 150, title, 
             #PB_Window_WindowCentered, WindowID(#mainWindow))  
  TextGadget(#messageBoxText, 10, 30, 180, 100, message, #PB_Text_Center)
  ButtonGadget(#messageBoxButton, 25, 100, 150, 30, "Close Message Box")
  StickyWindow(#messageBox, #True)
EndProcedure

Procedure mainwindow()  
  OpenWindow(#mainWindow, 0, 0, 600, 400,"Main Window", mainWindowFlags)
  TextGadget(#mainWindowClock, 10, 10, 580, 50, "00:00:00", #PB_Text_Right)
  ButtonGadget(#mainWindowButton, 200, 60, 200, 30, "Show Message Box")
  AddWindowTimer(#mainWindow, #mainWindowTimer, 1000)
EndProcedure

mainwindow()

Repeat
  event = WaitWindowEvent()
  Select EventWindow()
      
    ;handles all the events for the main window  
    Case #mainWindow
      Select event
        Case #PB_Event_CloseWindow
          appQuit = 1
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #mainWindowButton
              messageBox("Message Box", "Message Box Text")
          EndSelect
        Case #PB_Event_Timer
          Select EventTimer()
            Case #mainWindowTimer
              time.s = FormatDate("%hh:%ii:%ss", Date())
              SetGadgetText(#mainWindowClock, time)
          EndSelect          
      EndSelect
      
    ;handles all the events for the message box window   
    Case #messageBox
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(#messageBox)
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #messageBoxButton
              CloseWindow(#messageBox)      
          EndSelect          
      EndSelect      
      
  EndSelect
Until appQuit
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
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: MessageRequester on a separate thread (?)

Post by Axolotl »

Hey TI-994A,
you have created a toolwindow, in my opinion. If you want the effect of the MessageRequester() to come out better, then I would still recommend the use of DisableWindow() on the main window. With that the main window is not reacting on user actions and the clock is still running....
If you want to try it out, add the DisableWindow() as follows

Code: Select all

Procedure messageBox(title.s, message.s)
  DisableWindow(#mainWindow, 1)   ; <--- new 
  OpenWindow(#messageBox, 10, 10, 200, 150, title, 
             #PB_Window_WindowCentered, WindowID(#mainWindow))  
; .... 
; and in the main loop 
; ... 
    ;handles all the events for the message box window   
    Case #messageBox
      Select event
        Case #PB_Event_CloseWindow      ; <-- this never happens, because of window flag above ... 
          CloseWindow(#messageBox)
          DisableWindow(#mainWindow, 0)
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #messageBoxButton   ; <-- the "Ok Button" 
              CloseWindow(#messageBox)      
              DisableWindow(#mainWindow, 0)  ; <--- new 
          EndSelect          
; ...        
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: MessageRequester on a separate thread (?)

Post by TI-994A »

Axolotl wrote: Tue Aug 16, 2022 2:43 pm...I would still recommend the use of DisableWindow() on the main window. With that the main window is not reacting on user actions and the clock is still running...
Hi Axolotl. Great suggestion; thank you. I'm sure that it would be a welcome addition to the feature, provided AZJIO finds the multi-window approach acceptable in the first place.
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
AZJIO
Addict
Addict
Posts: 1312
Joined: Sun May 14, 2017 1:48 am

Re: MessageRequester on a separate thread (?)

Post by AZJIO »

Yes, I like your choice.
I temporarily did this:

Code: Select all

tmp$ = "Title " + Lng(17) + " & @Echo off & @Echo. & Color 1e & @Echo. " + item$ + "& "
tmp$ = EscapeString(tmp$)
tmp$ = ReplaceString(tmp$, ")", "^)")
tmp$ = ReplaceString(tmp$, "(", "^(")
RunProgram("cmd.exe", "/c (" + tmp$ + " set /p Ok=^>^>)", "")
breeze4me
Enthusiast
Enthusiast
Posts: 511
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: MessageRequester on a separate thread (?)

Post by breeze4me »

The MessageRequester function blocks events because the handle of the existing window is automatically put as a parameter even if executed in another thread.
So you can just use the MessageBox API to get the desired result.

Code: Select all

Global thread

Procedure PopupMsg(v)
  MessageBox_(0, "123", "456", #MB_OK | #MB_TOPMOST)
  ;If necessary, an event can be sent using PostEvent according to the response result.
  thread = 0
EndProcedure

If OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 10, 200, 20, "Standard Button")
  ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
  ButtonGadget(2, 10, 70, 200, 20, "Right Button", #PB_Button_Right)
  ButtonGadget(3, 10,100, 200, 60, "Multiline Button  (longer text gets automatically wrapped)", #PB_Button_MultiLine)
  ButtonGadget(4, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
  
  Repeat
    event = WaitWindowEvent()
    
    If event = #PB_Event_Gadget And EventGadget() = 0
      If thread = 0
        thread = CreateThread(@PopupMsg(), 0)
      Else
        Debug "Close the previous Msgbox first."
      EndIf
    EndIf
    
  Until event = #PB_Event_CloseWindow
EndIf
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: MessageRequester on a separate thread (?)

Post by TI-994A »

Great alternatives, AZJIO & breeze4me. The suggested approach was just that; a suggestion. But it does have the advantage of being cross-platform.
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
Jeromyal
Enthusiast
Enthusiast
Posts: 204
Joined: Wed Jul 17, 2013 8:49 am

Re: MessageRequester on a separate thread (?)

Post by Jeromyal »

I was trying to see if there was a way to pass a pointer to a structure into the thread with the structure consisting of the title and message.
I guess I don't know what I am doing.
It would be rather slick to even get the icons to work.
breeze4me
Enthusiast
Enthusiast
Posts: 511
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: MessageRequester on a separate thread (?)

Post by breeze4me »

Jeromyal wrote: Tue Aug 16, 2022 7:17 pm I was trying to see if there was a way to pass a pointer to a structure into the thread with the structure consisting of the title and message.
I guess I don't know what I am doing.
It would be rather slick to even get the icons to work.

Code: Select all

Global thread

Structure MyThreadMsg
  Title.s
  Text.s
  Flags.i
EndStructure

Procedure PopupMsg(*v.MyThreadMsg)
  MessageBox_(0, *v\Text, *v\Title, #MB_OK | #MB_TOPMOST | *v\Flags)
  thread = 0
EndProcedure

If OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 10, 200, 20, "Standard Button")
  ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
  ButtonGadget(2, 10, 70, 200, 20, "Right Button", #PB_Button_Right)
  ButtonGadget(3, 10,100, 200, 60, "Multiline Button  (longer text gets automatically wrapped)", #PB_Button_MultiLine)
  ButtonGadget(4, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
  
  Repeat
    event = WaitWindowEvent()
    
    If event = #PB_Event_Gadget And EventGadget() = 0
      If thread = 0
        v.MyThreadMsg\Title = "test title"
        v\Text = "text"
        v\Flags = #MB_ICONASTERISK | #MB_YESNO | #MB_DEFBUTTON2
        thread = CreateThread(@PopupMsg(), v)
      Else
        Debug "Close the previous Msgbox first."
      EndIf
    EndIf
    
  Until event = #PB_Event_CloseWindow
EndIf
Jeromyal
Enthusiast
Enthusiast
Posts: 204
Joined: Wed Jul 17, 2013 8:49 am

Re: MessageRequester on a separate thread (?)

Post by Jeromyal »

That's great Breeze4me. Thank you, because I think it was going to bug me for hours, or likely days until I figured it out if at all.
procedure PopupMsg(*v.MyThreadMsg) was what I was getting wrong. I was just doing *v
Jeromyal
Enthusiast
Enthusiast
Posts: 204
Joined: Wed Jul 17, 2013 8:49 am

Re: MessageRequester on a separate thread (?)

Post by Jeromyal »

I figured out a way to retrieve the result.

Code: Select all

Global thread

Structure MyThreadMsg
  Title.s
  Text.s
  Flags.i
  Result.i
EndStructure

Procedure PopupMsg(*v.MyThreadMsg)
  *v\Result = MessageBox_(0, *v\Text, *v\Title, #MB_OK | #MB_TOPMOST | *v\Flags)
  thread = 0
EndProcedure

If OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 10, 200, 20, "Standard Button")
  ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
  ButtonGadget(2, 10, 70, 200, 20, "Right Button", #PB_Button_Right)
  ButtonGadget(3, 10,100, 200, 60, "Multiline Button  (longer text gets automatically wrapped)", #PB_Button_MultiLine)
  ButtonGadget(4, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
  
  Repeat
    event = WaitWindowEvent()
    
    If event = #PB_Event_Gadget And EventGadget() = 0
      If thread = 0
        v.MyThreadMsg\Title = "test title"
        v\Text = "text"
        v\Flags = #MB_ICONASTERISK | #MB_YESNO | #MB_DEFBUTTON2
        thread = CreateThread(@PopupMsg(), v)
      Else
        Debug "Close the previous Msgbox first."
      EndIf
    EndIf
    If v\Result
      Debug v\Result
      v\Result = 0
    EndIf
  Until event = #PB_Event_CloseWindow
  Debug v\Result
EndIf
probably there is a better way such as a custom event but there we have it. Nice!
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: MessageRequester on a separate thread (?)

Post by BarryG »

AZJIO wrote: Tue Aug 16, 2022 4:54 amHow to issue a message in Windows, which will be a separate process not associated with the program?
In the topic title, you said a separate thread, but in your post, you said a separate process not associated with the program. These are entirely different. All the answers above are for a separate thread, but that thread will still be associated with the program, which is not what you wanted.

So which do you actually mean?
juergenkulow
Enthusiast
Enthusiast
Posts: 544
Joined: Wed Sep 25, 2019 10:18 am

Re: MessageRequester on a separate thread (?)

Post by juergenkulow »

Run a second program.

Code: Select all

; mymsg.out 
MessageRequester(ProgramParameter(0),ProgramParameter(1))

Code: Select all

; Linux, please adapt filename.
RunProgram("/tmp/mymsg.out",Chr(34)+"Titel"+Chr(34)+" "+Chr(34)+ReplaceString("Text",#LF$,"\n")+Chr(34),"")
Please ask your questions, because switch on the cognition apparatus decides on the only known life in the universe.Wersten :DDüsseldorf NRW Germany Europe Earth Solar System Flake Bubble Orionarm
Milky Way Local_Group Virgo Supercluster Laniakea Universe
Post Reply