The problem was that for certain calls that require structures, you have to manage the memory space stuff yourself with OpenProcess and VirtualAllocEx.
The example returns the tab captions from the specified window in a comma-delimited string.
I made it a function for ease-of-use. You specifiy the window Title, ClassNN, TabControl ClassNN, and tab number:
Code:
getTabText(vTitle, vWin, vControl, vTabnum)
Code:
;reference (thanks shimanov): http://www.autohotkey.com/forum/viewtopic.php?t=8840
aTitle := "AutoHotkey Help"
sWin := "HH Parent"
sControl := "SysTabControl321"
SendMessage, 0x1304, 0, 0, %sControl%, %aTitle% ahk_class %sWin% ;TCM_GETITEMCount
TabCount := ErrorLevel ;get number of tabs
tabs=
loop %TabCount%
{ sTabnum := A_Index - 1
vTab := getTabText(aTitle, sWin, sControl, sTabnum)
tabs .= vTab . ","
}
msgbox,%tabs%
Return
;vTitle=window title vWin=window class vControl=control ClassNN vTabNum=tab number
getTabText(vTitle, vWin, vControl, vTabnum)
{
global
WinGet, pid_target, PID, %vTitle% ahk_class %vWin%
;get handle to process inside pid_target ;0x38=PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE
remote_process := DllCall("OpenProcess", "uint", 0x38, "int", false, "uint", pid_target)
IfEqual, remote_process, , Goto errEnd
;get address allocated for foreign structure ;0x1000=MEM_COMMIT ;0x4=PAGE_READWRITE
remote_struct := DllCall("VirtualAllocEx", "uint", remote_process, "uint", 0, "uint", 20, "uint", 0x1000, "uint", 0x4)
IfEqual, remote_struct, , Goto errEnd
;get address allocated for foreign text buffer ;0x1000=MEM_COMMIT ;0x4=PAGE_READWRITE
remote_buffer := DllCall("VirtualAllocEx", "uint", remote_process, "uint", 0, "uint", 128, "uint", 0x1000, "uint", 0x4)
IfEqual, remote_buffer, , Goto errEnd
;create structure for TCM_GETITEM
VarSetCapacity(TCITEM, 20, 1) ;allocate var
InsertInteger(1, TCITEM, 0) ;Mask - TCIF_TEXT=1
InsertInteger(remote_buffer, TCITEM, 12) ;pszText
InsertInteger(128, TCITEM, 16) ;cchTextMax
;write structure to foreign address
res := DllCall( "WriteProcessMemory", "uint", remote_process, "uint", remote_struct, "uint", &TCITEM, "uint", 20, "uint", 0 )
SendMessage, 0x1305, %vTabnum%, remote_struct, %vControl%, ahk_pid %pid_target% ;TCM_GETITEM
getres = %ErrorLevel% ;get the info for the tab
VarSetCapacity(TabName, 128, 1) ;get the tab text
result := DllCall("ReadProcessMemory", "uint", remote_process, "uint", remote_buffer, "uint", &TabName, "uint", 128, "uint", 0)
free()
Return TabName
errEnd:
free()
Return "Fail"
}
free()
{
global
;free buffer
result := DllCall( "VirtualFreeEx", "uint", remote_process, "uint", remote_buffer, "uint", 0, "uint", 0x8000 ) ; MEM_RELEASE
;free structure
result := DllCall( "VirtualFreeEx", "uint", remote_process, "uint", remote_struct, "uint", 0, "uint", 0x8000 ) ; MEM_RELEASE
;free willy
result := DllCall( "CloseHandle", "uint", remote_process )
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity. To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
[EDIT]Fixed typo - thanks skrommel!