Plain text
复制到剪贴板
Open code in new window
EnlighterJS 3 Syntax Highlighter
base64Code:="iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACGSURBVDhP5ZThCoAgDIRd7//O1cggz9tOQ/rTB1KpfDsnZPtJWchWn8v4Tmhm9e0CvyOo8K3MoZfigue0EjZ7lRDlCK53R1Zp1Lq85SwdoxGq6gws2CVkiaJCbL4RzsgiZA+drI9YMBWqdKyQTJilY6TCERnuGerhDENC7+U9VOrf/bFLOQBFID0mPAYl2wAAAABJRU5ErkJggg=="
hIcon:=CreateIconFromBase64(base64Code, 48)
; hIcon:=LoadPicture("Shell32.dll", "Icon42 w48 h-1", IMAGE_ICON:=1)
; 获取指定程序的托盘图标信息,传入pid或exe进程名
try TrayIconInfo := GetTrayIconInfo(DllCall("GetCurrentProcessId")) ; 此处以改自身进程图标为例
if TrayIconInfo.hWnd&&hIcon
ReplaceTrayIcon(hIcon, TrayIconInfo.hWnd, TrayIconInfo.Id)
MsgBox % TrayIconInfo.hWnd&&hIcon ? "修改成功!" : "修改失败!"
BitmapFromBase64(ByRef base64) { ; Modified from just me's ImageToInclude
hBitmap := 0
VarSetCapacity(B64, StrLen(base64) << !!A_IsUnicode)
B64 := base64
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
Return False
VarSetCapacity(Dec, DecLen, 0)
If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
Return False
; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap)
DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
;DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
Return {hBitmap:hBitmap,pBitmap:pBitmap}
}
CreateIconFromBase64(base64, icoSize){
chars := StrLen(base64)
if !DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1
, "Ptr", 0, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
throw "CryptStringToBinary failed. LastError: " . A_LastError
VarSetCapacity(icoData, bytes, 0)
DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1
, "Str", icoData, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
Return DllCall("CreateIconFromResourceEx", "Ptr", &icoData, "UInt", bytes, "UInt", true
, "UInt", 0x30000, "Int", icoSize, "Int", icoSize, "UInt", 0, "Ptr")
}
ReplaceTrayIcon(hIcon, hWnd, iconId) {
static flag := NIF_ICON := 2, action := NIM_MODIFY := 1
VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize*4 + 8, 0)
NumPut(size , NOTIFYICONDATA)
NumPut(hWnd , NOTIFYICONDATA, A_PtrSize)
NumPut(iconId, NOTIFYICONDATA, A_PtrSize*2)
NumPut(flag , NOTIFYICONDATA, A_PtrSize*2 + 4)
NumPut(hIcon , NOTIFYICONDATA, A_PtrSize*3 + 8)
Return DllCall("Shell32\Shell_NotifyIcon", "UInt", action, "Ptr", &NOTIFYICONDATA)
}
GetTrayIconInfo(proceccNameOrPID := "") {
static TB_GETBUTTON := 0x417
, TB_BUTTONCOUNT := 0x418
, ptrSize := 4 << A_Is64bitOS
, szTBBUTTON := 8 + ptrSize*3
, szTRAYDATA := 16 + ptrSize*2
Arr := []
dhw_prev := A_DetectHiddenWindows
DetectHiddenWindows, On
WinGet, PID, PID, ahk_exe explorer.exe
RB := new RemoteBuffer(PID, szTRAYDATA)
found := false
Loop 2 {
if (A_Index = 2)
ControlGet, hToolBar, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
else {
for k, v in ["TrayNotifyWnd", "SysPager", "ToolbarWindow32"]
hToolBar := DllCall("FindWindowEx", "Ptr", k = 1 ? WinExist("ahk_class Shell_TrayWnd") : hToolBar, "Ptr", 0, "Str", v, "UInt", 0, "Ptr")
}
SendMessage, TB_BUTTONCOUNT,,,, ahk_id %hToolBar%
Loop % ErrorLevel {
SendMessage, TB_GETBUTTON, A_Index - 1, RB.ptr,, ahk_id %hToolBar%
try RB.Read(TBBUTTON, szTBBUTTON)
catch
continue
try RB.Read(TRAYDATA, szTRAYDATA, NumGet(&TBBUTTON + 8 + ptrSize) - RB.ptr)
catch
continue
tipOffset := NumGet(&TBBUTTON + 8 + ptrSize*2) - RB.ptr
try RB.Read(tip, 1024, tipOffset)
hWnd := NumGet(TRAYDATA)
WinGet, PID, PID, ahk_id %hWnd%
(PID = proceccNameOrPID && found := true)
WinGet, processName, ProcessName, ahk_id %hWnd%
(processName = proceccNameOrPID && found := true)
WinGetTitle, title, ahk_id %hWnd%
Arr.Push({ PID: PID, ProcessName: processName, ID: NumGet(&TRAYDATA + ptrSize, "UInt"), WinTitle: title
, hWnd: hWnd, Tip: tip, CallbackMessage: NumGet(&TRAYDATA + 4 + ptrSize, "UInt")
, HICON: NumGet(&TRAYDATA + 16 + ptrSize, ptrSize = 4 ? "UInt" : "UInt64") })
} until found
} until found
DetectHiddenWindows, %dhw_prev%
if (proceccNameOrPID && !found)
throw "Icon of specified process not found"
Return found ? Arr.Pop() : Arr
}
class RemoteBuffer {
__New(PID, size) {
static flags := (PROCESS_VM_OPERATION := 0x8) | (PROCESS_VM_WRITE := 0x20) | (PROCESS_VM_READ := 0x10)
, Params := ["UInt", MEM_COMMIT := 0x1000, "UInt", PAGE_READWRITE := 0x4, "Ptr"]
if !this.hProc := DllCall("OpenProcess", "UInt", flags, "Int", 0, "UInt", PID, "Ptr")
throw Exception("Can't open remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
if !this.ptr := DllCall("VirtualAllocEx", "Ptr", this.hProc, "Ptr", 0, "Ptr", size, Params*) {
DllCall("CloseHandle", "Ptr", this.hProc)
throw Exception("Can't allocate memory in remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
}
}
__Delete() {
DllCall("VirtualFreeEx", "Ptr", this.hProc, "Ptr", this.ptr, "UInt", 0, "UInt", MEM_RELEASE := 0x8000)
DllCall("CloseHandle", "Ptr", this.hProc)
}
Read(ByRef localBuff, size, offset = 0) {
VarSetCapacity(localBuff, size, 0)
if !DllCall("ReadProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", &localBuff, "Ptr", size, "PtrP", bytesRead)
throw Exception("Can't read data from remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Read")
Return bytesRead
}
Write(pData, size, offset = 0) {
if !res := DllCall("WriteProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", pData, "Ptr", size, "PtrP", bytesWritten)
throw Exception("Can't write data to remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Write")
Return bytesWritten
}
}
base64Code:="iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACGSURBVDhP5ZThCoAgDIRd7//O1cggz9tOQ/rTB1KpfDsnZPtJWchWn8v4Tmhm9e0CvyOo8K3MoZfigue0EjZ7lRDlCK53R1Zp1Lq85SwdoxGq6gws2CVkiaJCbL4RzsgiZA+drI9YMBWqdKyQTJilY6TCERnuGerhDENC7+U9VOrf/bFLOQBFID0mPAYl2wAAAABJRU5ErkJggg==" hIcon:=CreateIconFromBase64(base64Code, 48) ; hIcon:=LoadPicture("Shell32.dll", "Icon42 w48 h-1", IMAGE_ICON:=1) ; 获取指定程序的托盘图标信息,传入pid或exe进程名 try TrayIconInfo := GetTrayIconInfo(DllCall("GetCurrentProcessId")) ; 此处以改自身进程图标为例 if TrayIconInfo.hWnd&&hIcon ReplaceTrayIcon(hIcon, TrayIconInfo.hWnd, TrayIconInfo.Id) MsgBox % TrayIconInfo.hWnd&&hIcon ? "修改成功!" : "修改失败!" BitmapFromBase64(ByRef base64) { ; Modified from just me's ImageToInclude hBitmap := 0 VarSetCapacity(B64, StrLen(base64) << !!A_IsUnicode) B64 := base64 If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0) Return False VarSetCapacity(Dec, DecLen, 0) If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0) Return False ; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN ; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257 hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr") pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr") DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen) DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData) DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream) hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr") VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar") DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0) DllCall("Gdiplus.dll\GdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap) DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0) ;DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap) DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken) DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip) DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream) Return {hBitmap:hBitmap,pBitmap:pBitmap} } CreateIconFromBase64(base64, icoSize){ chars := StrLen(base64) if !DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1 , "Ptr", 0, "UIntP", bytes, "UIntP", 0, "UIntP", 0) throw "CryptStringToBinary failed. LastError: " . A_LastError VarSetCapacity(icoData, bytes, 0) DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1 , "Str", icoData, "UIntP", bytes, "UIntP", 0, "UIntP", 0) Return DllCall("CreateIconFromResourceEx", "Ptr", &icoData, "UInt", bytes, "UInt", true , "UInt", 0x30000, "Int", icoSize, "Int", icoSize, "UInt", 0, "Ptr") } ReplaceTrayIcon(hIcon, hWnd, iconId) { static flag := NIF_ICON := 2, action := NIM_MODIFY := 1 VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize*4 + 8, 0) NumPut(size , NOTIFYICONDATA) NumPut(hWnd , NOTIFYICONDATA, A_PtrSize) NumPut(iconId, NOTIFYICONDATA, A_PtrSize*2) NumPut(flag , NOTIFYICONDATA, A_PtrSize*2 + 4) NumPut(hIcon , NOTIFYICONDATA, A_PtrSize*3 + 8) Return DllCall("Shell32\Shell_NotifyIcon", "UInt", action, "Ptr", &NOTIFYICONDATA) } GetTrayIconInfo(proceccNameOrPID := "") { static TB_GETBUTTON := 0x417 , TB_BUTTONCOUNT := 0x418 , ptrSize := 4 << A_Is64bitOS , szTBBUTTON := 8 + ptrSize*3 , szTRAYDATA := 16 + ptrSize*2 Arr := [] dhw_prev := A_DetectHiddenWindows DetectHiddenWindows, On WinGet, PID, PID, ahk_exe explorer.exe RB := new RemoteBuffer(PID, szTRAYDATA) found := false Loop 2 { if (A_Index = 2) ControlGet, hToolBar, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow else { for k, v in ["TrayNotifyWnd", "SysPager", "ToolbarWindow32"] hToolBar := DllCall("FindWindowEx", "Ptr", k = 1 ? WinExist("ahk_class Shell_TrayWnd") : hToolBar, "Ptr", 0, "Str", v, "UInt", 0, "Ptr") } SendMessage, TB_BUTTONCOUNT,,,, ahk_id %hToolBar% Loop % ErrorLevel { SendMessage, TB_GETBUTTON, A_Index - 1, RB.ptr,, ahk_id %hToolBar% try RB.Read(TBBUTTON, szTBBUTTON) catch continue try RB.Read(TRAYDATA, szTRAYDATA, NumGet(&TBBUTTON + 8 + ptrSize) - RB.ptr) catch continue tipOffset := NumGet(&TBBUTTON + 8 + ptrSize*2) - RB.ptr try RB.Read(tip, 1024, tipOffset) hWnd := NumGet(TRAYDATA) WinGet, PID, PID, ahk_id %hWnd% (PID = proceccNameOrPID && found := true) WinGet, processName, ProcessName, ahk_id %hWnd% (processName = proceccNameOrPID && found := true) WinGetTitle, title, ahk_id %hWnd% Arr.Push({ PID: PID, ProcessName: processName, ID: NumGet(&TRAYDATA + ptrSize, "UInt"), WinTitle: title , hWnd: hWnd, Tip: tip, CallbackMessage: NumGet(&TRAYDATA + 4 + ptrSize, "UInt") , HICON: NumGet(&TRAYDATA + 16 + ptrSize, ptrSize = 4 ? "UInt" : "UInt64") }) } until found } until found DetectHiddenWindows, %dhw_prev% if (proceccNameOrPID && !found) throw "Icon of specified process not found" Return found ? Arr.Pop() : Arr } class RemoteBuffer { __New(PID, size) { static flags := (PROCESS_VM_OPERATION := 0x8) | (PROCESS_VM_WRITE := 0x20) | (PROCESS_VM_READ := 0x10) , Params := ["UInt", MEM_COMMIT := 0x1000, "UInt", PAGE_READWRITE := 0x4, "Ptr"] if !this.hProc := DllCall("OpenProcess", "UInt", flags, "Int", 0, "UInt", PID, "Ptr") throw Exception("Can't open remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New") if !this.ptr := DllCall("VirtualAllocEx", "Ptr", this.hProc, "Ptr", 0, "Ptr", size, Params*) { DllCall("CloseHandle", "Ptr", this.hProc) throw Exception("Can't allocate memory in remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New") } } __Delete() { DllCall("VirtualFreeEx", "Ptr", this.hProc, "Ptr", this.ptr, "UInt", 0, "UInt", MEM_RELEASE := 0x8000) DllCall("CloseHandle", "Ptr", this.hProc) } Read(ByRef localBuff, size, offset = 0) { VarSetCapacity(localBuff, size, 0) if !DllCall("ReadProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", &localBuff, "Ptr", size, "PtrP", bytesRead) throw Exception("Can't read data from remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Read") Return bytesRead } Write(pData, size, offset = 0) { if !res := DllCall("WriteProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", pData, "Ptr", size, "PtrP", bytesWritten) throw Exception("Can't write data to remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Write") Return bytesWritten } }
base64Code:="iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACGSURBVDhP5ZThCoAgDIRd7//O1cggz9tOQ/rTB1KpfDsnZPtJWchWn8v4Tmhm9e0CvyOo8K3MoZfigue0EjZ7lRDlCK53R1Zp1Lq85SwdoxGq6gws2CVkiaJCbL4RzsgiZA+drI9YMBWqdKyQTJilY6TCERnuGerhDENC7+U9VOrf/bFLOQBFID0mPAYl2wAAAABJRU5ErkJggg=="

hIcon:=CreateIconFromBase64(base64Code, 48)
; hIcon:=LoadPicture("Shell32.dll", "Icon42 w48 h-1", IMAGE_ICON:=1)

; 获取指定程序的托盘图标信息,传入pid或exe进程名
try TrayIconInfo := GetTrayIconInfo(DllCall("GetCurrentProcessId")) ; 此处以改自身进程图标为例

if TrayIconInfo.hWnd&&hIcon
  ReplaceTrayIcon(hIcon, TrayIconInfo.hWnd, TrayIconInfo.Id)

MsgBox % TrayIconInfo.hWnd&&hIcon ? "修改成功!" : "修改失败!"


BitmapFromBase64(ByRef base64) { ; Modified from just me's ImageToInclude
  hBitmap := 0
  VarSetCapacity(B64, StrLen(base64) << !!A_IsUnicode)
  B64 := base64
  If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", 0, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
    Return False
  VarSetCapacity(Dec, DecLen, 0)
  If !DllCall("Crypt32.dll\CryptStringToBinary", "Ptr", &B64, "UInt", 0, "UInt", 0x01, "Ptr", &Dec, "UIntP", DecLen, "Ptr", 0, "Ptr", 0)
    Return False
  ; Bitmap creation adopted from "How to convert Image data (JPEG/PNG/GIF) to hBITMAP?" by SKAN
  ; -> http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257
  hData := DllCall("Kernel32.dll\GlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr")
  pData := DllCall("Kernel32.dll\GlobalLock", "Ptr", hData, "UPtr")
  DllCall("Kernel32.dll\RtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen)
  DllCall("Kernel32.dll\GlobalUnlock", "Ptr", hData)
  DllCall("Ole32.dll\CreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream)
  hGdip := DllCall("Kernel32.dll\LoadLibrary", "Str", "Gdiplus.dll", "UPtr")
  VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar")
  DllCall("Gdiplus.dll\GdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0)
  DllCall("Gdiplus.dll\GdipCreateBitmapFromStream",  "Ptr", pStream, "PtrP", pBitmap)
  DllCall("Gdiplus.dll\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0)
  ;DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
  DllCall("Gdiplus.dll\GdiplusShutdown", "Ptr", pToken)
  DllCall("Kernel32.dll\FreeLibrary", "Ptr", hGdip)
  DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream)
  Return {hBitmap:hBitmap,pBitmap:pBitmap}
}

CreateIconFromBase64(base64, icoSize){
  chars := StrLen(base64)
  if !DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1
    , "Ptr", 0, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
    throw "CryptStringToBinary failed. LastError: " . A_LastError
  VarSetCapacity(icoData, bytes, 0)
  DllCall("Crypt32\CryptStringToBinary", "Str", base64, "UInt", chars, "UInt", 1
    , "Str", icoData, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
  Return DllCall("CreateIconFromResourceEx", "Ptr", &icoData, "UInt", bytes, "UInt", true
    , "UInt", 0x30000, "Int", icoSize, "Int", icoSize, "UInt", 0, "Ptr")
}

ReplaceTrayIcon(hIcon, hWnd, iconId) {
  static flag := NIF_ICON := 2, action := NIM_MODIFY := 1
  VarSetCapacity(NOTIFYICONDATA, size := A_PtrSize*4 + 8, 0)
  NumPut(size  , NOTIFYICONDATA)
  NumPut(hWnd  , NOTIFYICONDATA, A_PtrSize)
  NumPut(iconId, NOTIFYICONDATA, A_PtrSize*2)
  NumPut(flag  , NOTIFYICONDATA, A_PtrSize*2 + 4)
  NumPut(hIcon , NOTIFYICONDATA, A_PtrSize*3 + 8)
  Return DllCall("Shell32\Shell_NotifyIcon", "UInt", action, "Ptr", &NOTIFYICONDATA)
}

GetTrayIconInfo(proceccNameOrPID := "") {
  static TB_GETBUTTON	:= 0x417
      , TB_BUTTONCOUNT := 0x418
      , ptrSize := 4 << A_Is64bitOS
      , szTBBUTTON := 8 + ptrSize*3
      , szTRAYDATA := 16 + ptrSize*2
  
  Arr := []
  dhw_prev := A_DetectHiddenWindows
  DetectHiddenWindows, On
  WinGet, PID, PID, ahk_exe explorer.exe
  RB := new RemoteBuffer(PID, szTRAYDATA)
  found := false
  Loop 2 {
    if (A_Index = 2)
      ControlGet, hToolBar, hwnd,, ToolbarWindow321, ahk_class NotifyIconOverflowWindow
    else {
      for k, v in ["TrayNotifyWnd", "SysPager", "ToolbarWindow32"]
        hToolBar := DllCall("FindWindowEx", "Ptr", k = 1 ? WinExist("ahk_class Shell_TrayWnd") : hToolBar, "Ptr", 0, "Str", v, "UInt", 0, "Ptr")
    }
    SendMessage, TB_BUTTONCOUNT,,,, ahk_id %hToolBar%
    Loop % ErrorLevel {
      SendMessage, TB_GETBUTTON, A_Index - 1, RB.ptr,, ahk_id %hToolBar%
      try RB.Read(TBBUTTON, szTBBUTTON)
      catch
        continue
      try RB.Read(TRAYDATA, szTRAYDATA, NumGet(&TBBUTTON + 8 + ptrSize) - RB.ptr)
      catch
        continue
      tipOffset := NumGet(&TBBUTTON + 8 + ptrSize*2) - RB.ptr
      try RB.Read(tip, 1024, tipOffset)
      hWnd := NumGet(TRAYDATA)
      WinGet, PID, PID, ahk_id %hWnd%
      (PID = proceccNameOrPID && found := true)
      WinGet, processName, ProcessName, ahk_id %hWnd%
      (processName = proceccNameOrPID && found := true)
      WinGetTitle, title, ahk_id %hWnd%
      
      Arr.Push({ PID: PID, ProcessName: processName, ID: NumGet(&TRAYDATA + ptrSize, "UInt"), WinTitle: title
            , hWnd: hWnd, Tip: tip, CallbackMessage: NumGet(&TRAYDATA + 4 + ptrSize, "UInt")
            , HICON: NumGet(&TRAYDATA + 16 + ptrSize, ptrSize = 4 ? "UInt" : "UInt64") })
    } until found
  } until found
  DetectHiddenWindows, %dhw_prev%
  if (proceccNameOrPID && !found)
    throw "Icon of specified process not found"
  Return found ? Arr.Pop() : Arr
}

class RemoteBuffer {
  __New(PID, size) {
    static flags := (PROCESS_VM_OPERATION := 0x8) | (PROCESS_VM_WRITE := 0x20) | (PROCESS_VM_READ := 0x10)
        , Params := ["UInt", MEM_COMMIT := 0x1000, "UInt", PAGE_READWRITE := 0x4, "Ptr"]

    if !this.hProc := DllCall("OpenProcess", "UInt", flags, "Int", 0, "UInt", PID, "Ptr")
      throw Exception("Can't open remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")

    if !this.ptr := DllCall("VirtualAllocEx", "Ptr", this.hProc, "Ptr", 0, "Ptr", size, Params*) {
      DllCall("CloseHandle", "Ptr", this.hProc)
      throw Exception("Can't allocate memory in remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
    }
  }

  __Delete() {
    DllCall("VirtualFreeEx", "Ptr", this.hProc, "Ptr", this.ptr, "UInt", 0, "UInt", MEM_RELEASE := 0x8000)
    DllCall("CloseHandle", "Ptr", this.hProc)
  }

  Read(ByRef localBuff, size, offset = 0) {
    VarSetCapacity(localBuff, size, 0)
    if !DllCall("ReadProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", &localBuff, "Ptr", size, "PtrP", bytesRead)
      throw Exception("Can't read data from remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Read")
    Return bytesRead
  }

  Write(pData, size, offset = 0) {
    if !res := DllCall("WriteProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", pData, "Ptr", size, "PtrP", bytesWritten)
      throw Exception("Can't write data to remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Write")
    Return bytesWritten
  }
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。