It seems to work.
I wrote the script wich posts messages to a tray icon by its index. It works with Shell_TrayWnd and NotifyIconOverflowWindow both (without NotifyIconOverflowWindow showing).
However, it doesn't work with system icons for some reason.
Code: Select all
#NoTrayIcon
idx := 3
PostMessage2TrayIconIndex(idx
, "Shell_TrayWnd" ; "Shell_TrayWnd" or "NotifyIconOverflowWindow"
, WM_RBUTTONUP := 0x205)
Return
PostMessage2TrayIconIndex(idx, winClass, messages*)
{
/*
typedef TRAYDATA
{
IntPtr hwnd;
uint uID;
uint uCallbackMessage;
uint Reserved;
uint Reserved2;
IntPtr hIcon;
}
*/
static WM_USER := 0x400, TB_BUTTONCOUNT := WM_USER + 24, TB_GETBUTTON := WM_USER + 23
, PtrSize := A_Is64bitOS ? 8 : 4, szTBBUTTON := 8 + PtrSize*3, szTRAYDATA := 16 + PtrSize*2
DHW_Prev := A_DetectHiddenWindows
DetectHiddenWindows, On
if (winClass = "NotifyIconOverflowWindow")
ControlGet, hWnd, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
else {
for k, v in ["TrayNotifyWnd", "SysPager", "ToolbarWindow32"]
hWnd := DllCall("FindWindowEx", Ptr, k = 1 ? WinExist("ahk_class Shell_TrayWnd") : hWnd, Ptr, 0, Str, v, UInt, 0, Ptr)
}
WinExist("ahk_id" hWnd)
WinGet, PID, PID
if !IsObject(RemoteBuff := New RemoteBuffer(PID, szTRAYDATA)) {
DetectHiddenWindows, %DHW_Prev%
Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Failed to create the remote buffer`nError " A_LastError, Str, "", UInt, 0)
}
SendMessage, TB_GETBUTTON, idx - 1, RemoteBuff.ptr
if ! ( pTBBUTTON := RemoteBuff.Read(szTBBUTTON) )
|| !pTRAYDATA := RemoteBuff.Read(szTRAYDATA, NumGet(pTBBUTTON + 8 + PtrSize) - RemoteBuff.ptr) {
DetectHiddenWindows, %DHW_Prev%
Return
}
WinExist("ahk_id" NumGet(pTRAYDATA+0))
uID := NumGet(pTRAYDATA + PtrSize, "UInt")
uCallbackMessage := NumGet(pTRAYDATA + PtrSize + 4, "UInt")
for i, message in messages
PostMessage, uCallbackMessage, uID, message
DetectHiddenWindows, %DHW_Prev%
}
class RemoteBuffer
{
__New(PID, size) {
static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20
, PROCESS_VM_READ := 0x10, MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x4
if !(this.hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr))
Return
if !(this.ptr := DllCall("VirtualAllocEx", Ptr, this.hProc, Ptr, 0, Ptr, size, UInt, MEM_COMMIT, UInt, PAGE_READWRITE, Ptr))
Return, "", DllCall("CloseHandle", Ptr, this.hProc)
this.hHeap := DllCall("GetProcessHeap", Ptr)
}
__Delete() {
DllCall("VirtualFreeEx", Ptr, this.hProc, Ptr, this.ptr, UInt, 0, UInt, MEM_RELEASE := 0x8000)
DllCall("CloseHandle", Ptr, this.hProc)
DllCall("HeapFree", Ptr, this.hHeap, UInt, 0, Ptr, this.pHeap)
}
Read(size, offset = 0) {
(this.pHeap && DllCall("HeapFree", Ptr, this.hHeap, UInt, 0, Ptr, this.pHeap))
this.pHeap := DllCall("HeapAlloc", Ptr, this.hHeap, UInt, HEAP_ZERO_MEMORY := 0x8, Ptr, size, Ptr)
if !DllCall("ReadProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, this.pHeap, Ptr, size, Int, 0)
Return, 0, DllCall("MessageBox", Ptr, 0, Str, "Failed to read data`nError " A_LastError, Str, "", UInt, 0)
Return this.pHeap
}
Write(pLocalBuff, size, offset = 0) {
if !res := DllCall("WriteProcessMemory", Ptr, this.hProc, Ptr, this.ptr + offset, Ptr, pLocalBuff, Ptr, size, PtrP, writtenBytes)
DllCall("MessageBox", Ptr, 0, Str, "Failed to write data`nError " A_LastError, Str, "", UInt, 0)
Return writtenBytes
}
}