Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
About the System Tray
#1
In addition to that last post. I see a lot of useful "Wait for" statements in Quick Macros but I missing "Wait for" statement for tray icons that occur in the notification area.

For instance if a user plugs in a USB stick the "The Safely Remove Hardware and Eject Media" tray icon comes up. How do I make that trigger a OnScreenDisplay (persistent, no timeout) message? And, how do I make the OnScreenDisplay red instead of green and placed in the bottom right corner (instead of the center of the screen)?

Thanks.
#2
Yes I would be interested in a Wait for notification area (tray icons) procedure as well.
#3
Menu Tools / Output / Log /Acc trigger events.
Then add a tray icon.
Stop logging and look for useful events.
This can be useful:

2. CREATE, CLIENT, 1
    ow: class="ToolbarWindow32", id=1504, text="User Promoted Notification Area"
    pw: class="Shell_TrayWnd"
    ao: role=PUSHBUTTON, state=0x0, name="tooltip text"

Tested on Windows 10.

You can use this event for:
- trigger "Accessible object".
- to create a wait function.
- to receive notifications while your script shows a dialog or does something else.

Read more about "Accessible object" triggers in QM Help.
To start creating code for the last two, use menu File / New / Templates / Hook / Hook_SetWinEventHook. Google for function SetWinEventHook. I can help to create code, but maybe you prefer trigger.
#4
If I create a template I get this (I uncommented the bottom section):

Function Hook_SetWinEventHook2
Code:
Copy      Help
;/
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

outw hwnd ;;debug

;your code here


;;SetWinEventHook example
int hh=SetWinEventHook(EVENT_SYSTEM_FOREGROUND EVENT_SYSTEM_FOREGROUND 0 &sub.Hook_SetWinEventHook 0 0 WINEVENT_OUTOFCONTEXT)
if(!hh) end F"{ERR_FAILED}. {_s.dllerror}"
opt waitmsg 1
wait -1
UnhookWinEvent hh

Could you give me an example command using this function where the generation of the "Safely Remove Hardware and Eject Media" tray icon is hooked (when the user plugs in a USB stick in his computer assuming there is no other USB device plugged in yet). I want to attach an action to that.
#5
Hook code would be this. But Windows gives incorrect idChild, always 1. Therefore we don't know what icon has been added.

Macro Macro1708
Code:
Copy      Help
out

int hh=SetWinEventHook(EVENT_OBJECT_CREATE EVENT_OBJECT_CREATE 0 &sub.Hook_SetWinEventHook 0 0 WINEVENT_OUTOFCONTEXT)
if(!hh) end F"{ERR_FAILED}. {_s.dllerror}"
opt waitmsg 1
wait -1
UnhookWinEvent hh


#sub Hook_SetWinEventHook
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

;outw hwnd ;;debug
;out "%i %i" idObject idChild
if(idObject!=-4 or !WinTest(hwnd "ToolbarWindow32")) ret
_s.getwintext(hwnd); if(_s!="User Promoted Notification Area") ret
Acc a1.FromEvent(hwnd idObject idChild)
_s=a1.Name
out _s

Other option - find the icon as accessible object, and wait. To create code, use dialog "Find accessible object"; it's in the floating toolbar. But it uses CPU while waiting; on my PC 4.5%.

Macro Macro1710
Code:
Copy      Help
int w=wait(-1 WV win("" "Shell_TrayWnd"))
Acc a.Find(w "PUSHBUTTON" "Safely Remove Hardware and Eject Media" "class=ToolbarWindow32[]id=1504" 0x1005 -1)
out a.Name
#6
Thank you. The Accessible Object route sounds like the easiest? My main objective is to keep the on-screen display persistent until the user plugs out the USB device after which it should either disappear (probably easier) or be replaced by another on-screen message ("USB device plugged out") which also needs to be persistent. Of course when the user plugs in the device again the "USB device plugged in" on screen display should return. 

I cannot get the on-screen display persistent in the compiled executable quite contrary to when I run the script within Quick Macros itself. I also don't know how to keep the function itself persistent without using rep (with a big number). But that's extremely messy and burdens the CPU (particularly when the device is plugged out). You probably know a cleaner and better solution then the following:


Function USB_Device
Code:
Copy      Help
rep 5000
,int w=wait(-1 WV win("" "Shell_TrayWnd"))
,Acc a.Find(w "PUSHBUTTON" "Safely Remove Hardware and Eject Media" "class=ToolbarWindow32[]id=1504" 0x1005 -1)
,OnScreenDisplay "USB device plugged in" -1 0 -1 "Arial" 0 4 0xff0000
,1
,OsdHide    
,if a.NotFound
,,OsdHide    
,,OnScreenDisplay "USB device plugged out" -1 0 -1 "Arial" 0 4 0xff0000
,,;ret
#7
the way you have that currently setup osd is called over and over again which will cause some issues.  also need to change acc statement so it can detect when device is unplugged. i also set a check condition so osd is not called over and over again unnecessarily.

try this
Code:
Copy      Help
int ticheck
rep 
,int w=wait(-1 WV win("" "Shell_TrayWnd"))
,Acc a.Find(w "PUSHBUTTON" "Safely Remove Hardware and Eject Media" "class=ToolbarWindow32[]id=1504" 0x5 1)
,if a.NotFound
,,if ticheck =1
,,,OsdHide
,,,OnScreenDisplay "USB device plugged out" 5 0 -1 "Arial" 0 4 0xff0000
,,,ticheck=0
,else
,,if ticheck =0
,,,OnScreenDisplay "USB device plugged in" -1 0 -1 "Arial" 0 4 0xff0000
,,,ticheck=1
,0.5
#8
hybrid

Function tray_icon_added_removed_notifications
Code:
Copy      Help
;/exe

int iconExisted=sub.TrayIconExists

int hh=SetWinEventHook(EVENT_OBJECT_CREATE EVENT_OBJECT_DESTROY 0 &sub.Hook_SetWinEventHook 0 0 WINEVENT_OUTOFCONTEXT)
opt waitmsg 1
wait -1
UnhookWinEvent hh


#sub Hook_SetWinEventHook v
function hHook event hwnd idObject idChild dwEventThread dwmsEventTime

;outw hwnd ;;debug
;out "%i %i %i" event idObject idChild

if(idObject!=-4 or !WinTest(hwnd "ToolbarWindow32")) ret
_s.getwintext(hwnd); if(_s!="User Promoted Notification Area") ret
Acc a1.FromEvent(hwnd idObject idChild)
;_s=a1.Name; out _s
int iconExists=sub.TrayIconExists(a1)
if(iconExists=iconExisted) ret
iconExisted=iconExists
OnScreenDisplay iif(iconExists "Icon added" "Icon removed") -1 0 0 0 0 0 4|8 "Safely Remove"


#sub TrayIconExists
function! [Acc&anyIcon]

Acc a1
if &anyIcon
,anyIcon.Navigate("parent" a1)
,a1.Find(a1.a "PUSHBUTTON" "Safely Remove Hardware and Eject Media" "class=ToolbarWindow32" 0x5)
else
,int w=win("" "Shell_TrayWnd")
,a1.Find(w "PUSHBUTTON" "Safely Remove Hardware and Eject Media" "class=ToolbarWindow32" 0x5)
ret !a1.NotFound

;BEGIN PROJECT
;END PROJECT
#9
Thanks for both options. I will see what works best for me. Interesting for sure.


Forum Jump:


Users browsing this thread: 1 Guest(s)