Message without focus
Moderators: Dorian (MJT support), JRL
Message without focus
If this was already covered, I apologize. I ran a search and could not find it.
Would it be possible to have a small Message> box (or another similar small window) that I can place ON TOP (will not be covered by other windows), in an unused (or seldomly used) portion of the screen, that will update WITHOUT setting the focus on itself?
I want Mac Sched to monitor certain processes in the background and give me update messages, but without stealing the focus (so I can keep on typing, or doing whatever on the computer).
Thanks,
CC
P.S. A quick note of "thanks" to jpuziano for answer to my previous inquiry about how to deal with"multiple instances of the same program". Using the example provided, I have built an awesome macro that does exactly what I needed.
Would it be possible to have a small Message> box (or another similar small window) that I can place ON TOP (will not be covered by other windows), in an unused (or seldomly used) portion of the screen, that will update WITHOUT setting the focus on itself?
I want Mac Sched to monitor certain processes in the background and give me update messages, but without stealing the focus (so I can keep on typing, or doing whatever on the computer).
Thanks,
CC
P.S. A quick note of "thanks" to jpuziano for answer to my previous inquiry about how to deal with"multiple instances of the same program". Using the example provided, I have built an awesome macro that does exactly what I needed.
Here's a sample that displays the cursor position
Code: Select all
OnEvent>key_down,VK27,0,Quit
Dialog>Dialog1
object Dialog1: TForm
AutoSize = True
BorderIcons = []
FormStyle = fsStayOnTop
Caption = ' Message'
object Label1: TLabel
Caption = 'Label1'
end
end
EndDialog>Dialog1
Show>Dialog1
Label>Loop
Wait>0.01
Let>WIN_USEHANDLE=1
GetWindowPos>Dialog1.handle,winX,winY
MoveWindow>Dialog1.handle,winX,winY
Let>WIN_USEHANDLE=0
GetCursorPos>CurX,CurY
SetDialogProperty>Dialog1,label1,caption,X Pos = %CurX%%crlf%Y Pos = %CurY%
Goto>Loop
SRT>Quit
Exit>0
END>Quit
Coming back to this topic:
Although I understand the example provided, which works in a very fast 0.01 sec. loop that keeps dieplaying the dialog, I am not able to understand what exactly makes the dialog to persist On Top.
In my application, Mas Sch is performing a complex script, that involves looking for files, windows, waiting for data to appear, files to appear, images, a variety of stuff.
As long as I keep the fast loop going, yes, the dialog is On Top and I can type and keep the focus.
I figured I would put the info I need to see as text in the "Caption" using SetDialogProperty>
Then Mac Sch execution moves to another part of the program. The dialog no longer stays On Top (it disappears, covered by the other windows that get focus). When I need somthing else displayed, I do again Show> with new text in SetDialogProperty>. The dialog reappears, but does not stay On Top (as I focus on other windows, it gets covered). If I put the SetDialogProperty> in a loop for a while the dialog SOMETIMES becomes persistent On Top, and SOMETIMES gets covered by active window.
The end result is a constantly flashing on and off dialog.
I have not been able to figure out what exactly makes the dialog persist On Top. "FormStyle = fsStayOnTop" is on, but I can not see it doing anything. I know that WIN_USEHANDLE=1 + GetWindowPos> + MoveWindow> does something, but one execution does not seem to be enough to make the dialog persist On Top. Looping for a while seems to do that. But for how long? And why sometimes looping will bring dialog persistent On Top, but other times exactly the same loop will not. And I can not keep MacSch looping for dialog display as it needs to do other stuff.
I was looking for something like MSG_STAYONTOP=1, a persistent window that is always On Top and never gets covered, BUT that does NOT grab focus every time new info is being displayed (when Message> is called). Kind of like the Windows Task Manager: constantly refreshed, always On Top, but never grabbing focus.
Sorry if, because my inexperience, I am overlooking something very obvious.
CC
Although I understand the example provided, which works in a very fast 0.01 sec. loop that keeps dieplaying the dialog, I am not able to understand what exactly makes the dialog to persist On Top.
In my application, Mas Sch is performing a complex script, that involves looking for files, windows, waiting for data to appear, files to appear, images, a variety of stuff.
As long as I keep the fast loop going, yes, the dialog is On Top and I can type and keep the focus.
I figured I would put the info I need to see as text in the "Caption" using SetDialogProperty>
Then Mac Sch execution moves to another part of the program. The dialog no longer stays On Top (it disappears, covered by the other windows that get focus). When I need somthing else displayed, I do again Show> with new text in SetDialogProperty>. The dialog reappears, but does not stay On Top (as I focus on other windows, it gets covered). If I put the SetDialogProperty> in a loop for a while the dialog SOMETIMES becomes persistent On Top, and SOMETIMES gets covered by active window.
The end result is a constantly flashing on and off dialog.
I have not been able to figure out what exactly makes the dialog persist On Top. "FormStyle = fsStayOnTop" is on, but I can not see it doing anything. I know that WIN_USEHANDLE=1 + GetWindowPos> + MoveWindow> does something, but one execution does not seem to be enough to make the dialog persist On Top. Looping for a while seems to do that. But for how long? And why sometimes looping will bring dialog persistent On Top, but other times exactly the same loop will not. And I can not keep MacSch looping for dialog display as it needs to do other stuff.
I was looking for something like MSG_STAYONTOP=1, a persistent window that is always On Top and never gets covered, BUT that does NOT grab focus every time new info is being displayed (when Message> is called). Kind of like the Windows Task Manager: constantly refreshed, always On Top, but never grabbing focus.
Sorry if, because my inexperience, I am overlooking something very obvious.
CC
Hi ccris,
Here's a big thank you going out to all posters who help out by answering questions here... I've learned a lot just by following the forums and you all make this a great place to visit... much appreciated.
JRL's code here is interesting. I recall him posting a trick before and thought the following line was what was making the dialog stay on top:
MoveWindow>Dialog1.handle,winX,winY
But commenting out that line, the dialog still stayed on top. I then commented out the following line as well and...
SetDialogProperty>Dialog1,label1,caption,X Pos = %CurX%%crlf%Y Pos = %CurY%
...yup, it still stayed on top. So I put the above two lines back in and changed the wait line to the following...
Wait>3.01
...to give me a bit more time in between to see how it reacts... then compiled it and ran it without MS itself running.
Even compiled, it stays on top... until you hit Windows Key + D... then it remains hidden and the stay-on-top behavior will not return... until you setfocus back to it by either clicking on its taskbar button in the taskbar at the bottom of the desktop or... by hitting ALT + TAB to set focus back to it. From then on, it will again stay-on-top.
I note that adding the following line (there are 7 spaces in the line below)...
...somewhere inside the loop (but not between the WIN_USEHANDLE lines) will get it to stay-on-top even after you have hit Windows Key + D however it will now steal "keyboard" focus making it impossible to interact with other windows so this isn't really an option here.
I'm curious what JRL or anyone might come up with to get past the Windows Key + D problem... but in the meantime... ccris, if you have MS v13, open up the Help File and read up on AddTrayIcon>.
You can define a systray icon and when you move your mouse over that systray icon, you'll see the tooltip text which can be anything you want.
Originally, there was no way to change it... I requested an enhancement and now Marcus has added ModTrayIcon>. That will let you modify the tooltip text at any time so you could continually update it to say anything you'd like to display about the "current status" of your script... for example...
10% done, 0 errors encountered
20% done, 1 error encountered
75% done, 3 errors encountered
It does not take up any space on your desktop so you have no stay-on-top or focus stealing issues to deal with. Yes you have to mouse over that systray icon to see the tooltip but if that's no problem then this could work for you.
Take care
Again... you're welcome. While I don't help posters near as often as say JRL does (just compare the difference in reputation points earned so far)... I do like to jump in now and then.ccris wrote:P.S. A quick note of "thanks" to jpuziano for answer to my previous inquiry about how to deal with"multiple instances of the same program". Using the example provided, I have built an awesome macro that does exactly what I needed.
Here's a big thank you going out to all posters who help out by answering questions here... I've learned a lot just by following the forums and you all make this a great place to visit... much appreciated.
JRL's code here is interesting. I recall him posting a trick before and thought the following line was what was making the dialog stay on top:
MoveWindow>Dialog1.handle,winX,winY
But commenting out that line, the dialog still stayed on top. I then commented out the following line as well and...
SetDialogProperty>Dialog1,label1,caption,X Pos = %CurX%%crlf%Y Pos = %CurY%
...yup, it still stayed on top. So I put the above two lines back in and changed the wait line to the following...
Wait>3.01
...to give me a bit more time in between to see how it reacts... then compiled it and ran it without MS itself running.
Even compiled, it stays on top... until you hit Windows Key + D... then it remains hidden and the stay-on-top behavior will not return... until you setfocus back to it by either clicking on its taskbar button in the taskbar at the bottom of the desktop or... by hitting ALT + TAB to set focus back to it. From then on, it will again stay-on-top.
I note that adding the following line (there are 7 spaces in the line below)...
Code: Select all
SetFocus> Message
I'm curious what JRL or anyone might come up with to get past the Windows Key + D problem... but in the meantime... ccris, if you have MS v13, open up the Help File and read up on AddTrayIcon>.
You can define a systray icon and when you move your mouse over that systray icon, you'll see the tooltip text which can be anything you want.
Originally, there was no way to change it... I requested an enhancement and now Marcus has added ModTrayIcon>. That will let you modify the tooltip text at any time so you could continually update it to say anything you'd like to display about the "current status" of your script... for example...
10% done, 0 errors encountered
20% done, 1 error encountered
75% done, 3 errors encountered
It does not take up any space on your desktop so you have no stay-on-top or focus stealing issues to deal with. Yes you have to mouse over that systray icon to see the tooltip but if that's no problem then this could work for you.
Take care
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Eureka!
I figured out how to do what I want.
The reason for not being able to have the dialogs persist On Top is because of all the "stuff" the script has to do. I think every time I do a Focus operation, the dialog is covered. The macro is too complex to keep watching for when the dialog will dissappear.
The solution:
Instead of displaying in main script, I leave the main script to do all the complicated stuff. I write the messages I want displayed to display.INI file. I have a separate script "Display" do nothing but loop and read the display.INI and show the dialog. The dialog stays On Top forever and never steals the focus. I compiled both scripts so they will have a "program name". When I start the main script, it runs the "Display" script hidden. The Display script watches for the name of the main script and keeps running in the background as long as the main script is running.
The main script does the job, the Display script provides the display function. When main script terminates, using some VB, the Display script "kills" itself. So I have both scripts run/terminate with one click.
Thanks to all for suggestions.
CC
I figured out how to do what I want.
The reason for not being able to have the dialogs persist On Top is because of all the "stuff" the script has to do. I think every time I do a Focus operation, the dialog is covered. The macro is too complex to keep watching for when the dialog will dissappear.
The solution:
Instead of displaying in main script, I leave the main script to do all the complicated stuff. I write the messages I want displayed to display.INI file. I have a separate script "Display" do nothing but loop and read the display.INI and show the dialog. The dialog stays On Top forever and never steals the focus. I compiled both scripts so they will have a "program name". When I start the main script, it runs the "Display" script hidden. The Display script watches for the name of the main script and keeps running in the background as long as the main script is running.
The main script does the job, the Display script provides the display function. When main script terminates, using some VB, the Display script "kills" itself. So I have both scripts run/terminate with one click.
Thanks to all for suggestions.
CC
Well done ccris, two scripts frees up the display script to keep in its tight loop... however hitting Windows Key + D (a keyboard shortcut used to minimize all windows so you can see your desktop)... still hides your display dialog i.e. stay-on-top is still defeated... yes? If not, please post your code.ccris wrote:The solution:
Instead of displaying in main script, I leave the main script to do all the complicated stuff. I write the messages I want displayed to display.INI file. I have a separate script "Display" do nothing but loop and read the display.INI and show the dialog. The dialog stays On Top forever and never steals the focus. I compiled both scripts so they will have a "program name". When I start the main script, it runs the "Display" script hidden. The Display script watches for the name of the main script and keeps running in the background as long as the main script is running.
The main script does the job, the Display script provides the display function. When main script terminates, using some VB, the Display script "kills" itself. So I have both scripts run/terminate with one click.
Of course, if you never use Windows Key + D then this is fine... but can anyone come up with a way to make this display dialog stay-on-top... even after hitting Windows Key + D ?
jpuziano
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post -
Hi jpuziano,
Happy to report that the display dialog stays-on-top... even after hitting Windows Key + D
THIS IS THE DISPLAY SCRIPT
As to the MAIN_PROGRAM script, I have a SRT>dialog_message_display that takes in 3 variables (for 3 lines of text display) and writes them to your message_ini_path.
Every time you want to display something, do something like:
GoSub>dialog_message_display,My message line 1,My message line 2, My message line 3
(of course, do not use = or , or anything that will confuse read/write on an INI file)
Here is my SRT>dialog_message_display
This was made for a very small Auto Size box, with 3 lines of data, but you can make it bigger, fixed size, more data, etc.
I'm glad I got this figured out!
CC
Happy to report that the display dialog stays-on-top... even after hitting Windows Key + D
THIS IS THE DISPLAY SCRIPT
Code: Select all
rem Provides persistent display
//Esc=VK27
OnEvent>KEY_DOWN,VK27,8,quit
rem Name of the main program this is providing display for
Let>proc_to_monitor=MAIN_PROGRAM.exe
rem Enter your path to message_display.ini
Let>message_ini_path=%ENTER PATH HERE%message_display.ini
Let>null=
GetScreenRes>Width_Reso,Height_Reso
rem ***********************************************************************************
rem Prepare VB functions
VBSTART
'returns the number of copies of ProcessName that are running
'will return 0 if ProcessName is not running
Function IsProcessRunning(ProcessName)
Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcessList = oWMIService.ExecQuery ("Select Name from Win32_Process where Name='" & ProcessName & "'")
IsProcessRunning = colProcessList.count
End Function
VBEND
rem ***********************************************************************************
rem ***********************************************************************************
rem Create dialog. One line (label), AutoSize, fsStayOnTop
rem Message On Top (bottom right)
Dialog>dialog_message_ontop_bottom_right
object dialog_message_ontop_bottom_right: TForm
AutoSize = True
BorderIcons = []
FormStyle = fsStayOnTop
OnTaskBar = True
Caption = ' Message'
object Label1: TLabel
Caption = 'Label1'
end
end
EndDialog>dialog_message_ontop_bottom_right
rem ***********************************************************************************
rem Execute this as a SRT
GoSub>dialog_message_display
rem It should run endless. If not, end.
Goto>end
rem ***********************************************************
rem BEGIN Dialog Message Display
SRT>dialog_message_display
Let>dialog_message_display_bottom_right_left=Width_Reso-275
Let>dialog_message_display_bottom_right_top=Height_Reso-100
Show>dialog_message_ontop_bottom_right
Let>WIN_USEHANDLE=1
MoveWindow>dialog_message_ontop_bottom_right.handle,dialog_message_display_bottom_right_left,dialog_message_display_bottom_right_top
Let>WIN_USEHANDLE=0
rem Infinite loop
Let>k=0
Label>loop_refresh
rem To reduce number of reads, read ini file only when counter is at 0 (once every 50 cycles)
If>k=0
rem Create message to display
Gosub>create_message_to_display
rem See if your MAIN_PROGRAM.exe is still running.
rem If it is no longer running, kill this_process.
GoSub>test_to_kill
EndIf
rem If text in z_message_text_1 is null, close dialog box
If>z_message_text_1=null
CloseDialog>dialog_message_ontop_bottom_right
Let>showing=NO
Else
If>showing=NO
Show>dialog_message_ontop_bottom_right
Let>showing=YES
Else
EndIf
EndIf
Label>after_read_file
Let>WIN_USEHANDLE=1
GetWindowPos>dialog_message_ontop_bottom_right.handle,dialog_message_display_bottom_right_left,dialog_message_display_bottom_right_top
MoveWindow>dialog_message_ontop_bottom_right.handle,dialog_message_display_bottom_right_left,dialog_message_display_bottom_right_top
Let>WIN_USEHANDLE=0
Let>message_to_display=%z_message_text%
SetDialogProperty>dialog_message_ontop_bottom_right,label1,caption,%message_to_display%
rem 0.01 sec is your refresh rate
Wait>0.01
Let>k=k+1
rem 50 is number of cycles between read ini file operations (in this case, 0.5 sec)
If>k>50
Let>k=0
EndIf
Goto>loop_refresh
END>dialog_message_display
rem END Dialog Message Display
rem ***********************************************************
rem ***********************************************************
rem BEGIN Create message to display
SRT>create_message_to_display
rem Make sure variables are clean before reading into them
Let>z_message_text_1=null
Let>z_message_text_2=null
Let>z_message_text_3=null
rem Read the 3 parts
ReadiniFile>%message_ini_path%,message_section,message_text_1,z_message_text_1
ReadiniFile>%message_ini_path%,message_section,message_text_2,z_message_text_2
ReadiniFile>%message_ini_path%,message_section,message_text_3,z_message_text_3
rem Combine the 3 parts in one z_message_text and separate lines with %CRLF%
Let>z_message_text=null
ConCat>z_message_text,z_message_text_1
If>z_message_text_2<>null
ConCat>z_message_text,%CRLF%
ConCat>z_message_text,z_message_text_2
Else
Goto>done_combining
EndIf
If>z_message_text_3<>null
ConCat>z_message_text,%CRLF%
ConCat>z_message_text,z_message_text_3
Else
Goto>done_combining
EndIf
Label>done_combining
END>create_message_to_display
rem END Create message to display
rem ***********************************************************
rem ***********************************************************
rem BEGIN Terminate
rem If pushing Window+Esc, terminate this display program
SRT>exit
CloseDialog>dialog_message_ontop_bottom_right
Exit>0
END>exit
rem END Terminate
rem ***********************************************************
rem ***********************************************************
rem BEGIN Test and kill
rem If your MAIN_PROGRAM.exe is not running, kill this
SRT>test_to_kill
VBEval>IsProcessRunning("%proc_to_monitor%"),eval_result
If>eval_result=0
rem If you are here, your MAIN_PROGRAM.exe is not running. Kill this program
Exit
Endif
END>test_to_kill
rem END Test and kill
rem ***********************************************************
SRT>quit
Exit>0
END>quit
Label>end
Every time you want to display something, do something like:
GoSub>dialog_message_display,My message line 1,My message line 2, My message line 3
(of course, do not use = or , or anything that will confuse read/write on an INI file)
Here is my SRT>dialog_message_display
Code: Select all
rem ***********************************************************
rem BEGIN Dialog Message Display
SRT>dialog_message_display
rem Receiving dialog_message_display_Var_1, dialog_message_display_Var_2, dialog_message_display_Var_3
Let>data_1=dialog_message_display_Var_1
Let>data_2=dialog_message_display_Var_2
Let>data_3=dialog_message_display_Var_3
EditiniFile>%message_ini_path%,message_section,message_text_1,null
EditiniFile>%message_ini_path%,message_section,message_text_2,null
EditiniFile>%message_ini_path%,message_section,message_text_3,null
Label>after_divide_parts
EditiniFile>%message_ini_path%,message_section,message_text_1,dialog_message_display_Var_1
If>data_2<>literal_2
EditiniFile>%message_ini_path%,message_section,message_text_2,dialog_message_display_Var_2
EndIf
If>data_3<>literal_3
EditiniFile>%message_ini_path%,message_section,message_text_3,dialog_message_display_Var_3
EndIf
Let>dialog_message_display_Var_1=null
Let>dialog_message_display_Var_2=null
Let>dialog_message_display_Var_3=null
END>dialog_message_display
rem END Dialog Message Display
rem ***********************************************************
I'm glad I got this figured out!
CC
I forgot a bit that is outside SRT>dialog_message_display
If my SRT call has only 1 or 2 lines, like
GoSub>dialog_message_display,My message line 1
the SRT will get confused and see a non-existent Var_2 like:
"dialog_message_display_Var_2"
So at the beginning I store the literal name like:
and in the SRT
I assign
and only write lines 2 and 3 in INI if there is real data in there:
If my SRT call has only 1 or 2 lines, like
GoSub>dialog_message_display,My message line 1
the SRT will get confused and see a non-existent Var_2 like:
"dialog_message_display_Var_2"
So at the beginning I store the literal name like:
Code: Select all
Let>literal_1=dialog_message_display_Var_1
Let>literal_2=dialog_message_display_Var_2
Let>literal_3=dialog_message_display_Var_3
I assign
Code: Select all
Let>data_1=dialog_message_display_Var_1
Let>data_2=dialog_message_display_Var_2
Let>data_3=dialog_message_display_Var_3
Code: Select all
If>data_2<>literal_2
EditiniFile>%message_ini_path%,message_section,message_text_2,dialog_message_display_Var_2