这段代码主要用于通过 远程进程内存访问Windows 消息机制 与任务管理器或其他 SysHeader32 控件交互,完成对表头信息(如文本和宽度)以及表头项矩形区域的获取。

 

/*
步骤:
1.获取进程PID (WinGet)。
2. DllCall OpenProcess。
3. DllCall VirtualAllocEx。
4. 创建 RECT 结构。
5. DllCall WriteProcessMemory。
6. 循环 HDM_GETITEMCOUNT。
7. 发送消息 HDM_GETITEMRECT。
8. Dll调用ReadProcessMemory。
9. Num获取结构数据。
X. DllCall VirtualFreeEx e CloseHandle。
*/

; https://www.autohotkey.com/boards/viewtopic.php?f=76&t=52945&start=20
#SingleInstance Force
#NoEnv

; 在任务管理器的SysHeader32标题上,按Capslock键
Capslock::
    MouseGetPos X, Y,, hWnd, 2
    WinGetClass Class, ahk_id %hWnd%

    If (Class != "SysHeader32") {
        MsgBox Move the mouse over a SysHeader32 control.

    } Else {
        a := GetRemoteHeaderItemsRect(hWnd)  ; 返回尺寸大小
        Loop % a.Length()
            MsgBox % a[A_Index].X . " " . a[A_Index].Y . " " . a[A_Index].W . " " . a[A_Index].H
        b := GetHeaderInfo(hWnd)
        ; Debug(b)
        MsgBox % b[1]["Text"] " " b[1]["Width"] " " b[2]["Text"] " " b[2]["Width"]
    }
Return

GetRemoteHeaderItemsRect(hHeader) {
    WinGet PID, PID, ahk_id %hHeader%

    If !(hProc := DllCall("OpenProcess", "UInt", 0x438, "Int", False, "UInt", PID, "Ptr")) {
        Return
    }

    remote_item := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "UPtr", 16, "UInt", 0x1000, "UInt", 4, "Ptr")

    VarSetCapacity(RECT, 16, 0)

    DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", remote_item, "Ptr", &RECT, "uPtr", 16, "Ptr", 0)

    aRECT := []

    SendMessage 0x1200, 0, 0,, ahk_id %hHeader% ; HDM_GETITEMCOUNT
    Loop % (ErrorLevel != "FAIL") ? ErrorLevel : 0 {
        SendMessage 0x1207, A_Index - 1, remote_item,, ahk_id %hHeader% ; HDM_GETITEMRECT
        If (ErrorLevel && ErrorLevel != "FAIL") {
            DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", remote_item, "Ptr", &RECT, "uPtr", 16, "Ptr", 0)        
        }

        X := NumGet(RECT, 0, "Int")
        Y := NumGet(RECT, 4, "Int")
        W := NumGet(RECT, 8, "Int")
        H := NumGet(RECT, 12, "Int")

        aRECT.Push({"X": X, "Y": Y, "W": W, "H": H})
    }
    
    DllCall("VirtualFreeEx", "Ptr", hProc, "Ptr", remote_item, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
    DllCall("CloseHandle", "Ptr", hProc)

    Return aRECT
}

; 返回一个对象包含的文本和宽度SysHeader32遥控的每一项
GetHeaderInfo(hHeader) {
    Static MAX_TEXT_LENGTH := 260
         , MAX_TEXT_SIZE := MAX_TEXT_LENGTH * (A_IsUnicode ? 2 : 1)

    WinGet PID, PID, ahk_id %hHeader%

    ; Open the process for read/write and query info.
    ; PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION
    If !(hProc := DllCall("OpenProcess", "UInt", 0x438, "Int", False, "UInt", PID, "Ptr")) {
        Return
    }

    ; Should we use the 32-bit struct or the 64-bit struct?
    If (A_Is64bitOS) {
        Try DllCall("IsWow64Process", "Ptr", hProc, "int*", Is32bit := true)
    } Else {
        Is32bit := True
    }

    RPtrSize := Is32bit ? 4 : 8
    cbHDITEM := (4 * 6) + (RPtrSize * 6)

    ; Allocate a buffer in the (presumably) remote process.
    remote_item := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0
                         , "uPtr", cbHDITEM + MAX_TEXT_SIZE
                         , "UInt", 0x1000, "UInt", 4, "Ptr") ; MEM_COMMIT, PAGE_READWRITE
    remote_text := remote_item + cbHDITEM

    ; Prepare the HDITEM structure locally.
    VarSetCapacity(HDITEM, cbHDITEM, 0)
    NumPut(0x3, HDITEM, 0, "UInt") ; mask (HDI_WIDTH | HDI_TEXT)
    NumPut(remote_text, HDITEM, 8, "Ptr") ; pszText
    NumPut(MAX_TEXT_LENGTH, HDITEM, 8 + RPtrSize * 2, "Int") ; cchTextMax

    ; Write the local structure into the remote buffer.
    DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", remote_item, "Ptr", &HDITEM, "uPtr", cbHDITEM, "Ptr", 0)

    HDInfo := {}
    VarSetCapacity(HDText, MAX_TEXT_SIZE)

    SendMessage 0x1200, 0, 0,, ahk_id %hHeader% ; HDM_GETITEMCOUNT
    Loop % (ErrorLevel != "FAIL") ? ErrorLevel : 0 {
        ; Retrieve the item text.
        SendMessage, % (A_IsUnicode) ? 0x120B : 0x1203, A_Index - 1, remote_item,, ahk_id %hHeader% ; HDM_GETITEMW
        If (ErrorLevel == 1) { ; Success
            DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", remote_item, "Ptr", &HDITEM, "uPtr", cbHDITEM, "Ptr", 0)
            DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", remote_text, "Ptr", &HDText, "uPtr", MAX_TEXT_SIZE, "Ptr", 0)
        } Else {
            HDText := ""
        }

        HDInfo.Push({"Width": NumGet(HDITEM, 4, "UInt"), "Text": HDText})
    }

    ; Release the remote memory and handle.
    DllCall("VirtualFreeEx", "Ptr", hProc, "Ptr", remote_item, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
    DllCall("CloseHandle", "Ptr", hProc)

    Return HDInfo
}

 

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