Hi!
I have an external program, containing a "SysListView321" with a "SysHeader321" on top of it and I'd like to extract the text from the header. Specifically I am interested in the text of the column I click. I can find out the number of the column, but I need the text of its header. I've searched quite a bit, but didn't find any solution. Any help would be appreciated.
How can I get the text of the column header of a SysListView32? Topic is solved
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
This library has JEE_LVHGetText and JEE_AccCtlGetText. Cheers.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: How can I get the text of the column header of a SysListView32?
This is the function I use in WinSpy:
Code: Select all
; Returns an object containing the text and width of each item of a remote SysHeader32 control
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
}
Last edited by Alguimist on 05 Aug 2018, 16:53, edited 2 times in total.
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Thanks for the quick answers!
jeeswg, I downloaded your code (and the Acc library), but stumbled on the call to some nonexistent functions SendMessage(0xE, 0, 0,, "ahk_id " hCtl), JEE_DCOpenProcess(0x438, 0, vPID). Where can I get those?
Alguimist, I have run your function, but it returns all texts empty and all widths 0 (which is not correct).
jeeswg, I downloaded your code (and the Acc library), but stumbled on the call to some nonexistent functions SendMessage(0xE, 0, 0,, "ahk_id " hCtl), JEE_DCOpenProcess(0x438, 0, vPID). Where can I get those?
Alguimist, I have run your function, but it returns all texts empty and all widths 0 (which is not correct).
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
- The additional functions are in the second codebox on the thread linked earlier.
- I'll add a comment on the thread.
- I'll add a comment on the thread.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Arrrghhh... I am just blind , of course they are there. Thanks a lot jeeswg, it works great now!
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
For some reason the isolated function is not working with AHK 64-bit, but if you check the "Extra" tab of WinSpy, the information is displayed, no matter if executed with AHK 32 or 64-bit.
-
- Posts: 4309
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: How can I get the text of the column header of a SysListView32?
Alguimist wrote:For some reason the isolated function is not working with AHK 64-bit
Code: Select all
DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", remote_item, "Ptr", &HDITEM, "uPtr", MAX_TEXT_SIZE, "Ptr", 0)
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Yeah, it works when called from "WinSpy.ahk".
However, now I have a different problem. I thought I could determine which column I clicked the mouse (comparing the mouse X coordinate with the X of the ListView + column widths starting at the column zero until I got sum widths > mouse X), but since the columns can be reordered, I need to know their order. I've tried to use just me's LV_EX_GetColumnOrder() here, but the SendMessage, 0x103B inside the function returns false, and thus the function does too. Anyway, is there some other way of finding out which column number the mouse has clicked?
By the way, WinSpy is an awesome tool, I think I'll be trying some alchemy with it .
However, now I have a different problem. I thought I could determine which column I clicked the mouse (comparing the mouse X coordinate with the X of the ListView + column widths starting at the column zero until I got sum widths > mouse X), but since the columns can be reordered, I need to know their order. I've tried to use just me's LV_EX_GetColumnOrder() here, but the SendMessage, 0x103B inside the function returns false, and thus the function does too. Anyway, is there some other way of finding out which column number the mouse has clicked?
By the way, WinSpy is an awesome tool, I think I'll be trying some alchemy with it .
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
Maybe something like HDM_GETITEMRECT (0x1207) and PtInRect.SunAndSuch wrote:Anyway, is there some other way of finding out which column number the mouse has clicked?
Re: How can I get the text of the column header of a SysListView32?
- Did you pass it the hWnd of the listview (not the header)?
- Actually, that function appears to be written for internal listviews only.
- Try JEE_LVGetColOrder, designed for internal and external listviews.
- Actually, that function appears to be written for internal listviews only.
- Try JEE_LVGetColOrder, designed for internal and external listviews.
Code: Select all
;warning: such functions can potentially crash programs, save any work before testing
;[need functions from here:]
;GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
;==================================================
;pass listview hWnd (not listview header hWnd)
;for local controls only
JEE_LVGetColOrderLocal(hCtl, vSep:="")
{
hLVH := SendMessage(0x101F,,,, "ahk_id " hCtl) ;LVM_GETHEADER := 0x101F
vCountCol := SendMessage(0x1200,,,, "ahk_id " hLVH) ;HDM_GETITEMCOUNT := 0x1200
vData := ""
VarSetCapacity(vData, vCountCol*4, 0)
SendMessage(0x103B, vCountCol, &vData,, "ahk_id " hCtl) ;LVM_GETCOLUMNORDERARRAY := 0x103B
if (vSep = "")
{
oOutput := []
Loop, % vCountCol
oOutput.Push(NumGet(&vData, A_Index*4-4, "Int")+1)
return oOutput
}
else
{
vOutput := ""
Loop, % vCountCol
vOutput .= NumGet(&vData, A_Index*4-4, "Int")+1 vSep
return SubStr(vOutput, 1, -StrLen(vSep))
}
}
;==================================================
;pass listview hWnd (not listview header hWnd)
JEE_LVGetColOrder(hCtl, vSep:="")
{
vErr := A_PtrSize=8 && JEE_WinIs64Bit(hCtl) ? -1 : 0xFFFFFFFF
vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
vPID := WinGetPID("ahk_id " hCtl)
if (vPID = vScriptPID)
vIsLocal := 1, vPIs64 := (A_PtrSize=8)
if !hLVH := SendMessage(0x101F,,,, "ahk_id " hCtl) ;LVM_GETHEADER := 0x101F
return
if !vCountCol := SendMessage(0x1200,,,, "ahk_id " hLVH) ;HDM_GETITEMCOUNT := 0x1200
return
if (vCountCol = vErr) ;-1
return
if !vIsLocal
{
if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
return
if A_Is64bitOS && !DllCall("kernel32\IsWow64Process", Ptr,hProc, PtrP,vIsWow64Process)
return
vPIs64 := !vIsWow64Process
}
vPtrType := vPIs64?"Int64":"Int"
vSize := vCountCol*4
VarSetCapacity(vData, vSize, 0)
if !vIsLocal
{
if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize, 0x3000, 0x4)
return
}
else
pBuf := &vData
SendMessage(0x103B, vCountCol, pBuf,, "ahk_id " hCtl) ;LVM_GETCOLUMNORDERARRAY := 0x103B
if !vIsLocal
{
JEE_DCReadProcessMemory(hProc, pBuf, &vData, vSize, 0)
JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
JEE_DCCloseHandle(hProc)
}
if (vSep = "")
{
oOutput := []
Loop, % vCountCol
oOutput.Push(NumGet(&vData, A_Index*4-4, "Int")+1)
return oOutput
}
else
{
vOutput := ""
Loop, % vCountCol
vOutput .= NumGet(&vData, A_Index*4-4, "Int")+1 vSep
return SubStr(vOutput, 1, -StrLen(vSep))
}
}
;==================================================
;pass listview hWnd (not listview header hWnd)
;for local controls only
JEE_LVSetColOrderLocal(hCtl, oList, vSep:="")
{
if !IsObject(oList)
oList := StrSplit(oList, vSep)
if !(vCountCol := oList.Length())
return
VarSetCapacity(vData, vCountCol*4)
for _, vValue in oList
NumPut(vValue-1, &vData, A_Index*4-4, "Int")
SendMessage(0x103A, vCountCol, &vArray,, "ahk_id " hCtl) ;LVM_SETCOLUMNORDERARRAY := 0x103A
}
;==================================================
;pass listview hWnd (not listview header hWnd)
JEE_LVSetColOrder(hCtl, oList, vSep:="")
{
if !IsObject(oList)
oList := StrSplit(oList, vSep)
if !(vCountCol := oList.Length())
return
vErr := A_PtrSize=8 && JEE_WinIs64Bit(hCtl) ? -1 : 0xFFFFFFFF
vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
vPID := WinGetPID("ahk_id " hCtl)
if (vPID = vScriptPID)
vIsLocal := 1, vPIs64 := (A_PtrSize=8)
if !hLVH := SendMessage(0x101F,,,, "ahk_id " hCtl) ;LVM_GETHEADER := 0x101F
return
if !vCountCol := SendMessage(0x1200,,,, "ahk_id " hLVH) ;HDM_GETITEMCOUNT := 0x1200
return
if (vCountCol = vErr) ;-1
return
if !vIsLocal
{
if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
return
if A_Is64bitOS && !DllCall("kernel32\IsWow64Process", Ptr,hProc, IntP,vIsWow64Process)
return
vPIs64 := !vIsWow64Process
}
vPtrType := vPIs64?"Int64":"Int"
vSize := vCountCol*4
VarSetCapacity(vData, vCountCol*4)
for _, vValue in oList
NumPut(vValue-1, &vData, A_Index*4-4, "Int")
if !vIsLocal
{
if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize, 0x3000, 0x4)
return
JEE_DCWriteProcessMemory(hProc, pBuf, &vData, vSize, 0)
}
else
pBuf := &vData
SendMessage(0x103A, vCountCol, pBuf,, "ahk_id " hCtl) ;LVM_SETCOLUMNORDERARRAY := 0x103A
if !vIsLocal
{
JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
JEE_DCCloseHandle(hProc)
}
}
;==================================================
Last edited by jeeswg on 17 Feb 2019, 17:52, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Yes, I passed the hWnd of the listview.jeeswg wrote:- Did you pass it the hWnd of the listview (not the header)?
Now there are again two functions I can not find: JEE_WinIs64Bit and WinGetPID. I assume the latter one should look something like:
Code: Select all
WinGetPID(hCtl) {
WinGet,cPid,PID,%hCtl%
return cPid
}
Windows 10, Ahk v1 x64-bit.
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Thanks for the suggestion. I am just learning DllCall, so I have tried:Alguimist wrote:Maybe something like HDM_GETITEMRECT (0x1207) and PtInRect.
Code: Select all
ControlGet,hCtl,hwnd,,SysListView321,%winTit%
VarSetCapacity(pt,8,0)
DllCall("GetCursorPos","Ptr",&pt)
SendMessage,0x1207,1,&rect,,ahk_id %hCtl% ;HDM_GETITEMRECT=0x1207
DllCall("PtInRect","Ptr",&rect,"Ptr",&pt)
By the way, when I do:
Code: Select all
ptX:=NumGet(&pt,0,"UInt")
ptY:=NumGet(&pt,1,"UInt")
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
- I've done an overhaul of both codeboxes here. They now match my latest versions.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- Everything should be there now.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- Everything should be there now.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Ok... so I would need many functions from AHK v2 to run your code, right (I am currently in AHK v1)?jeeswg wrote:- I've done an overhaul of both codeboxes here. They now match my latest versions.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- Everything should be there now.
To the other part. I am wondering what I am doing wrong here:
Code: Select all
ControlGet,hCtl,hwnd,,SysListView321,%winTit%
VarSetCapacity(pt,8)
GetCursorPos:=DllCall("GetCursorPos","Ptr",&pt)
;When I check the cursor coordinates, they look reasonable:
ptX:=NumGet(pt,0,"UInt") ; = integer within the screen resolution
ptY:=NumGet(pt,4,"UInt") ; = integer within the screen resolution
;Then I try to get the coordinates of the rectangle:
VarSetCapacity(rect,16)
SendMessage,0x1207,2,&rect,,ahk_id %hCtl% ;HDM_GETITEMRECT=0x1207
;Then I check the coordinates and they are all zero:
rectTopX:=NumGet(rect,0,"UInt") ; = 0
rectTopY:=NumGet(rect,4,"UInt") ; = 0
rectBotX:=NumGet(rect,8,"UInt") ; = 0
rectBotY:=NumGet(rect,12,"UInt") ; = 0
;And unsurprisingly, the PtInRect also returns 0:
PtInRect:=DllCall("PtInRect","Ptr",&rect,"Ptr",&pt) ; = 0
;Even if I try NumPut, for example:
NumPut(100,rect,0,"UInt")
NumPut(200,rect,4,"UInt")
NumPut(1400,rect,8,"UInt")
NumPut(1300,rect,12,"UInt")
;and then PtInRect, it still returns 0, even though the mouse is clearly in the specified rectangle.
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
- It needs code from 2 codeboxes and code from 2 libraries, I've updated the description, here:
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- I program using AHK v1 + 'AHK v2 functions for AHK v1'. I would like to program in a completely two-way compatible way, but Loop remains a problem. (I have mentioned this in my Wish List 2.0.)
- If I tried to maintain 2 versions of all of my functions, I would have time for nothing else.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- I program using AHK v1 + 'AHK v2 functions for AHK v1'. I would like to program in a completely two-way compatible way, but Loop remains a problem. (I have mentioned this in my Wish List 2.0.)
- If I tried to maintain 2 versions of all of my functions, I would have time for nothing else.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Which two libraries? In your description it saysjeeswg wrote:- It needs code from 2 codeboxes and code from 2 libraries, I've updated the description, here:
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- I program using AHK v1 + 'AHK v2 functions for AHK v1'. I would like to program in a completely two-way compatible way, but Loop remains a problem. (I have mentioned this in my Wish List 2.0.)
- If I tried to maintain 2 versions of all of my functions, I would have time for nothing else.
I can not find functions WinGetClass, WinGetPID, ControlGetText, ControlGetStyle and ControlSend so far.To run: the code from both codeboxes is needed, and from Acc.ahk.
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
I updated the description, it says:
To run: the code from both codeboxes is needed, and from two libraries: Acc.ahk and 'AHK v2 functions for AHK v1'.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
-
- Posts: 46
- Joined: 05 Oct 2015, 12:11
Re: How can I get the text of the column header of a SysListView32?
Now that makes sense. But
gives res = "1,11,3,4,8,5,6,1,1,1,7864321,3145780,3145777,1,7864321,53,3670017,1,"
Code: Select all
oColOrd:=JEE_LVGetColOrder(LVhwnd)
Loop,18
res.=oColOrd[A_Index] ","
Windows 10, Ahk v1 x64-bit.
Re: How can I get the text of the column header of a SysListView32?
Are you using x32 or x64? Does it work on any other listview controls? Does it have 18 columns?
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Who is online
Users browsing this forum: jaka1, marypoppins_1 and 135 guests