. Of all the potential solution's, theirs was the only one that would let me do it remotely, that is without activating the controls window.
It was critical that I achieve a means to do it 'remotely' as I was intending to use it for a PowerShell module that gets the values of various controls, such as combo box, button, edit etc.
Code: Select all
;https://www.autohotkey.com/boards/viewtopic.php?p=231012#p231012
; Returns an object containing the text and width of each item of a remote SysHeader32 control
CTRL_GetHeader(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 [i] 6) + (RPtrSize [/i] 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 [list]1, remote_item,, ahk_id %hHeader% ; HDM_GETITEMW[/list]
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
}