I managed to get all the lines from a window listview by this script line:
Code: Select all
ControlGet, Output, List, , SysListView321, ahk_class MMCMainFrame
MsgBox % Output
Thanks in advance!
Code: Select all
ControlGet, Output, List, , SysListView321, ahk_class MMCMainFrame
MsgBox % Output
Code: Select all
; ----------------------------------------------------------------------------------------------------------------------
; Name .........: ExtListView library
; Description ..: Collection of functions dealing with the ListViews of external processes.
; AHK Version ..: AHK_L 1.1.13.01 x32/64 ANSI/Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: May 18, 2013 - v0.1 - First revision.
; ..............: Jun. 28, 2013 - v0.2 - Added resizable buffer option.
; ..............: Feb. 04, 2014 - v0.3 - Unicode and x64 compatibility.
; ..............: Apr. 10, 2014 - v1.0 - Code refactoring. Added encoding option and simple error management.
; ..............: May 04, 2014 - v1.1 - Detached the handles and memory allocation code.
; ..............: May 05, 2014 - v1.2 - Created ExtListView_GetAllItems and ExtListView_ToggleSelection functions.
; ..............: May 06, 2014 - v2.0 - Complete rewrite of the library. Code more modular and updateable. Separated
; ..............: code for De/Initialization, GetNextItem and GetItemText.
; ..............: Jul 24, 2017 - v2.1 - Fixed LVITEM size issue.
; ----------------------------------------------------------------------------------------------------------------------
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetSingleItem
; Description ..: Get the first item with the desired state.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; ..............: nCol - Column of the desired item (0-based index).
; Info .........: For more info on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Single item as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetSingleItem(ByRef objLV, sState, nCol) {
Try {
If ( (nRow := ExtListView_GetNextItem(objLV, -1, sState)) != 0xFFFFFFFF )
sItem := ExtListView_GetItemText(objLV, nRow, nCol)
} Catch e
Throw e
Return (sItem) ? sItem : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetAllItems
; Description ..: Get all items that share the same status on the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: For more infor on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Multidimensional array containing ListView's items. Eg: array[row][column] := "SomeString".
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetAllItems(ByRef objLV, sState:=0x0000) {
Try {
nRow := -1, objList := []
Loop
{
If ( (nRow := ExtListView_GetNextItem(objLV, nRow, sState)) == 0xFFFFFFFF )
Break
x := A_Index, objList[x] := []
Loop % objLV.cols
objList[x][A_Index] := ExtListView_GetItemText(objLV, nRow, A_Index-1)
}
} Catch e
Throw e
Return ( objList.MaxIndex() ) ? objList : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_ToggleSelection
; Description ..: Select/deselect items in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: bSelect - 1 for selection, 0 for deselection.
; ..............: nItem - -1 for all items or "n" (0-based) for a specific ListView item.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_ToggleSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0002 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0002, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetNextItem
; Description ..: Get the next item in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row where to start the search for the next item (0-based index).
; ..............: lParam - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: LVM_GETNEXTITEM - http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetNextItem(ByRef objLV, nRow, lParam:=0x0000) {
; LVM_GETNEXTITEM = LVM_FIRST (0x1000) + 12 = 0x100C.
SendMessage, 0x100C, %nRow%, %lParam%,, % "ahk_id " objLV.hlv
Return ErrorLevel
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetItemText
; Description ..: Get the text of the desired item.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row of the desired item (0-based index).
; ..............: nCol - Column of the desired item (0-based index).
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetItemText(ByRef objLV, nRow, nCol) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0001, LVITEM, 0 ) ; mask = LVIF_TEXT = 0x0001.
NumPut( nRow, LVITEM, 4 ) ; iItem = Row to retrieve (0 = 1st row).
NumPut( nCol, LVITEM, 8 ) ; iSubItem = The column index of the item to retrieve.
NumPut( objLV.preadbuf, LVITEM, 20 + (A_PtrSize - 4) ) ; pszText = Pointer to item text string.
NumPut( objLV.szreadbuf, LVITEM, 20 + ((A_PtrSize * 2) - 4) ) ; cchTextMax = Number of TCHARs in the buffer.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf
, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
; LVM_GETITEMTEXTA = LVM_FIRST (0x1000) + 45 = 0x102D.
; LVM_GETITEMTEXTW = LVM_FIRST (0x1000) + 115 = 0x1073.
LVM_GETITEMTEXT := (objLV.senc == "UTF-8" || objLV.senc == "UTF-16") ? 0x1073 : 0x102D
SendMessage, %LVM_GETITEMTEXT%, %nRow%, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
VarSetCapacity(cRecvBuf, objLV.szreadbuf, 1)
If ( !DllCall( "ReadProcessMemory", Ptr,objLV.hproc, Ptr,objLV.preadbuf, Ptr,&cRecvBuf, UInt,objLV.szreadbuf
, Ptr,0 ) )
Throw Exception("objLV.preadbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
Return StrGet(&cRecvBuf, objLV.szreadbuf, objLV.senc)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_Initialize
; Description ..: Initialize the object containing ListView's related data.
; Parameters ...: sWnd - Title of the window containing the ListView.
; ..............: szReadBuf - Size of the buffer used for reading the target process memory. It must be capable enough
; ..............: to hold the longest cell in the ListView.
; ..............: sEnc - Target ListView's encoding. "CP0" for ANSI, "UTF-8" or "UTF-16" for Unicode.
; Return .......: objLV - External ListView initialized object with the following keys:
; ..............: objLV.swnd - Title of the window owning the ListView.
; ..............: objLV.hwnd - Handle to the window owning the ListView.
; ..............: objLV.hproc - Handle to the process owning the ListView.
; ..............: objLV.hlv - Handle to the ListView.
; ..............: objLV.hhdr - Handle to the header of the ListView.
; ..............: objLV.rows - Number of rows in the ListView.
; ..............: objLV.cols - Number of columns in the ListView.
; ..............: objLV.senc - Encoding used by the process owning the ListView.
; ..............: objLV.pwritebuf - Address to the buffer used to write the LVITEM message to the target ListView.
; ..............: objLV.szwritebuf - Size of the write buffer.
; ..............: objLV.preadbuf - Address to the buffer used to read the answer to the message sent.
; ..............: objLV.szreadbuf - Size of the read buffer.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_Initialize(sWnd, szReadBuf:=1024, sEnc:="CP0") {
objLV := Object()
objLV.swnd := sWnd
objLV.hwnd := WinExist(sWnd)
objLV.szwritebuf := (A_OSVersion == "WIN_XP") ? 52 + (A_PtrSize-4)*5 : 60 + (A_PtrSize-4)*7 ; Size of LVITEM
objLV.szreadbuf := szReadBuf
objLV.senc := sEnc
ControlGet, hLv, Hwnd,, SysListView321, % "ahk_id " objLV.hwnd
objLV.hlv := hLv
DllCall( "GetWindowThreadProcessId", Ptr,hLv, PtrP,dwProcessId )
; PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020.
If ( !(objLV.hproc := DllCall( "OpenProcess", UInt,0x0008|0x0010|0x0020, Int,0, UInt,dwProcessId )) )
Throw Exception("objLV.hproc: error opening process", "OpenProcess", "LastError: " A_LastError)
; LVM_GETITEMCOUNT = LVM_FIRST (0x1000) + 4 = 0x1004.
SendMessage, 0x1004, 0, 0,, % "ahk_id " objLV.hlv
objLV.rows := ErrorLevel
; LVM_GETHEADER = LVM_FIRST (0x1000) + 31 = 0x101F.
SendMessage, 0x101F, 0, 0,, % "ahk_id " objLV.hlv
objLV.hhdr := ErrorLevel
; HDM_GETITEMCOUNT = HDM_FIRST (0x1200) + 0 = 0x1200.
SendMessage, 0x1200, 0, 0,, % "ahk_id " objLV.hhdr
objLV.cols := ErrorLevel
; Allocate memory on the target process before returning the object.
If ( !__ExtListView_AllocateMemory(objLV) )
Throw Exception("Error allocating memory", "__ExtListView_Initialize", "LastError: " A_LastError)
Return objLV
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_DeInitialize
; Description ..: DeInitialize the object.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_DeInitialize(ByRef objLV) {
; Free the previously allocated memory on the target process.
If ( !__ExtListView_DeAllocateMemory(objLV) )
Throw Exception("Error deallocating memory", "__ExtListView_DeInitialize", "LastError: " A_LastError)
DllCall( "CloseHandle", Ptr,objLV.hproc )
objLV := ""
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_CheckInitObject
; Description ..: Check if the object is still referring to a valid ListView.
; Parameters ...: objLV - External ListView initialized object.
; Return .......: 0 if false, handle of the window containing the ListView if true.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_CheckInitObject(ByRef objLV) {
Return WinExist("ahk_id " objLV.hwnd)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
If ( !(objLV.preadbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
Return 1
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_DeAllocateMemory
; Description ..: Frees previously allocated memory.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_DeAllocateMemory(ByRef objLV) {
; MEM_RELEASE = 0x8000.
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("pwritebuf")
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.preadbuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("preadbuf")
Return 1
}
;~ /* EXAMPLE CODE:
OnExit, QUIT
WINTITLE = Active Directory Users and Computers ahk_class MMCMainFrame
objLV := ExtListView_Initialize(WINTITLE)
HotKey, IfWinActive, %WINTITLE%
HotKey, F1, TOGGLESEL
Return
TOGGLESEL:
( ExtListView_CheckInitObject(objLV) ) ? objLV := ExtListView_Initialize(WINTITLE)
ExtListView_ToggleSelection(objLV, 1, 0)
Return
QUIT:
ExtListView_DeInitialize(objLV)
ExitApp
;~ */
Code: Select all
LVwindowTitle := "Test" ; Adjust as needed
#Include D:\utils\listviewLibrary.ahk
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
LV_Add("", "ghiff", "jklff")
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
LV := ExtListView_Initialize(LVwindowTitle)
findText := "ghi"
row := row(LV, findText)
MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
findText := "jklff"
row := row(LV, findText, 2)
MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
findText := "bbbbbbbbbbbbbb"
row := row(LV, findText)
MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
select(LV, "xxghi")
select(LV, "jkl", COL := 2)
; select(LV, "hif")
Return
select(LV, str, col := 1) { ; Select a row in a ListView, by string
(row := row(LV, str, col)) && ExtListView_ToggleSelection(LV, SELECT := True, row - 1)
}
row(LV, str, col := 1) { ; Find string in a ListView column
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; https://www.autohotkey.com/boards/viewtopic.php?p=463971#p463971
Loop {
next := ExtListView_GetNextItem(LV, row := A_Index - 1)
pos := Instr(ExtListView_GetItemText(LV, row, col - 1), str)
} Until (next < 1 || pos)
Return pos ? row + 1 : 0 ; Return the row number found, or zero
}
GuiClose:
GuiEscape:
ExitApp
Code: Select all
; ----------------------------------------------------------------------------------------------------------------------
; Name .........: ExtListView library
; Description ..: Collection of functions dealing with the ListViews of external processes.
; AHK Version ..: AHK_L 1.1.13.01 x32/64 ANSI/Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: May 18, 2013 - v0.1 - First revision.
; ..............: Jun. 28, 2013 - v0.2 - Added resizable buffer option.
; ..............: Feb. 04, 2014 - v0.3 - Unicode and x64 compatibility.
; ..............: Apr. 10, 2014 - v1.0 - Code refactoring. Added encoding option and simple error management.
; ..............: May 04, 2014 - v1.1 - Detached the handles and memory allocation code.
; ..............: May 05, 2014 - v1.2 - Created ExtListView_GetAllItems and ExtListView_ToggleSelection functions.
; ..............: May 06, 2014 - v2.0 - Complete rewrite of the library. Code more modular and updateable. Separated
; ..............: code for De/Initialization, GetNextItem and GetItemText.
; ..............: Jul 24, 2017 - v2.1 - Fixed LVITEM size issue.
; ----------------------------------------------------------------------------------------------------------------------
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetSingleItem
; Description ..: Get the first item with the desired state.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; ..............: nCol - Column of the desired item (0-based index).
; Info .........: For more info on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Single item as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetSingleItem(ByRef objLV, sState, nCol) {
Try {
If ( (nRow := ExtListView_GetNextItem(objLV, -1, sState)) != 0xFFFFFFFF )
sItem := ExtListView_GetItemText(objLV, nRow, nCol)
} Catch e
Throw e
Return (sItem) ? sItem : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetAllItems
; Description ..: Get all items that share the same status on the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: For more infor on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Multidimensional array containing ListView's items. Eg: array[row][column] := "SomeString".
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetAllItems(ByRef objLV, sState:=0x0000) {
Try {
nRow := -1, objList := []
Loop
{
If ( (nRow := ExtListView_GetNextItem(objLV, nRow, sState)) == 0xFFFFFFFF )
Break
x := A_Index, objList[x] := []
Loop % objLV.cols
objList[x][A_Index] := ExtListView_GetItemText(objLV, nRow, A_Index-1)
}
} Catch e
Throw e
Return ( objList.MaxIndex() ) ? objList : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_ToggleSelection
; Description ..: Select/deselect items in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: bSelect - 1 for selection, 0 for deselection.
; ..............: nItem - -1 for all items or "n" (0-based) for a specific ListView item.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_ToggleSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0002 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0002, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetNextItem
; Description ..: Get the next item in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row where to start the search for the next item (0-based index).
; ..............: lParam - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: LVM_GETNEXTITEM - http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetNextItem(ByRef objLV, nRow, lParam:=0x0000) {
; LVM_GETNEXTITEM = LVM_FIRST (0x1000) + 12 = 0x100C.
SendMessage, 0x100C, %nRow%, %lParam%,, % "ahk_id " objLV.hlv
Return ErrorLevel
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetItemText
; Description ..: Get the text of the desired item.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row of the desired item (0-based index).
; ..............: nCol - Column of the desired item (0-based index).
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetItemText(ByRef objLV, nRow, nCol) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0001, LVITEM, 0 ) ; mask = LVIF_TEXT = 0x0001.
NumPut( nRow, LVITEM, 4 ) ; iItem = Row to retrieve (0 = 1st row).
NumPut( nCol, LVITEM, 8 ) ; iSubItem = The column index of the item to retrieve.
NumPut( objLV.preadbuf, LVITEM, 20 + (A_PtrSize - 4) ) ; pszText = Pointer to item text string.
NumPut( objLV.szreadbuf, LVITEM, 20 + ((A_PtrSize * 2) - 4) ) ; cchTextMax = Number of TCHARs in the buffer.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf
, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
; LVM_GETITEMTEXTA = LVM_FIRST (0x1000) + 45 = 0x102D.
; LVM_GETITEMTEXTW = LVM_FIRST (0x1000) + 115 = 0x1073.
LVM_GETITEMTEXT := (objLV.senc == "UTF-8" || objLV.senc == "UTF-16") ? 0x1073 : 0x102D
SendMessage, %LVM_GETITEMTEXT%, %nRow%, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
VarSetCapacity(cRecvBuf, objLV.szreadbuf, 1)
If ( !DllCall( "ReadProcessMemory", Ptr,objLV.hproc, Ptr,objLV.preadbuf, Ptr,&cRecvBuf, UInt,objLV.szreadbuf
, Ptr,0 ) )
Throw Exception("objLV.preadbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
Return StrGet(&cRecvBuf, objLV.szreadbuf, objLV.senc)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_Initialize
; Description ..: Initialize the object containing ListView's related data.
; Parameters ...: sWnd - Title of the window containing the ListView.
; ..............: szReadBuf - Size of the buffer used for reading the target process memory. It must be capable enough
; ..............: to hold the longest cell in the ListView.
; ..............: sEnc - Target ListView's encoding. "CP0" for ANSI, "UTF-8" or "UTF-16" for Unicode.
; Return .......: objLV - External ListView initialized object with the following keys:
; ..............: objLV.swnd - Title of the window owning the ListView.
; ..............: objLV.hwnd - Handle to the window owning the ListView.
; ..............: objLV.hproc - Handle to the process owning the ListView.
; ..............: objLV.hlv - Handle to the ListView.
; ..............: objLV.hhdr - Handle to the header of the ListView.
; ..............: objLV.rows - Number of rows in the ListView.
; ..............: objLV.cols - Number of columns in the ListView.
; ..............: objLV.senc - Encoding used by the process owning the ListView.
; ..............: objLV.pwritebuf - Address to the buffer used to write the LVITEM message to the target ListView.
; ..............: objLV.szwritebuf - Size of the write buffer.
; ..............: objLV.preadbuf - Address to the buffer used to read the answer to the message sent.
; ..............: objLV.szreadbuf - Size of the read buffer.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_Initialize(sWnd, szReadBuf:=1024, sEnc:="CP0") {
objLV := Object()
objLV.swnd := sWnd
objLV.hwnd := WinExist(sWnd)
objLV.szwritebuf := (A_OSVersion == "WIN_XP") ? 52 + (A_PtrSize-4)*5 : 60 + (A_PtrSize-4)*7 ; Size of LVITEM
objLV.szreadbuf := szReadBuf
objLV.senc := sEnc
ControlGet, hLv, Hwnd,, SysListView321, % "ahk_id " objLV.hwnd
objLV.hlv := hLv
DllCall( "GetWindowThreadProcessId", Ptr,hLv, PtrP,dwProcessId )
; PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020.
If ( !(objLV.hproc := DllCall( "OpenProcess", UInt,0x0008|0x0010|0x0020, Int,0, UInt,dwProcessId )) )
Throw Exception("objLV.hproc: error opening process", "OpenProcess", "LastError: " A_LastError)
; LVM_GETITEMCOUNT = LVM_FIRST (0x1000) + 4 = 0x1004.
SendMessage, 0x1004, 0, 0,, % "ahk_id " objLV.hlv
objLV.rows := ErrorLevel
; LVM_GETHEADER = LVM_FIRST (0x1000) + 31 = 0x101F.
SendMessage, 0x101F, 0, 0,, % "ahk_id " objLV.hlv
objLV.hhdr := ErrorLevel
; HDM_GETITEMCOUNT = HDM_FIRST (0x1200) + 0 = 0x1200.
SendMessage, 0x1200, 0, 0,, % "ahk_id " objLV.hhdr
objLV.cols := ErrorLevel
; Allocate memory on the target process before returning the object.
If ( !__ExtListView_AllocateMemory(objLV) )
Throw Exception("Error allocating memory", "__ExtListView_Initialize", "LastError: " A_LastError)
Return objLV
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_DeInitialize
; Description ..: DeInitialize the object.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_DeInitialize(ByRef objLV) {
; Free the previously allocated memory on the target process.
If ( !__ExtListView_DeAllocateMemory(objLV) )
Throw Exception("Error deallocating memory", "__ExtListView_DeInitialize", "LastError: " A_LastError)
DllCall( "CloseHandle", Ptr,objLV.hproc )
objLV := ""
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_CheckInitObject
; Description ..: Check if the object is still referring to a valid ListView.
; Parameters ...: objLV - External ListView initialized object.
; Return .......: 0 if false, handle of the window containing the ListView if true.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_CheckInitObject(ByRef objLV) {
Return WinExist("ahk_id " objLV.hwnd)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
If ( !(objLV.preadbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
Return 1
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_DeAllocateMemory
; Description ..: Frees previously allocated memory.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_DeAllocateMemory(ByRef objLV) {
; MEM_RELEASE = 0x8000.
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("pwritebuf")
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.preadbuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("preadbuf")
Return 1
}
LVwindowTitle := "Test" ; Adjust as needed
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
Loop, 50
{
LV_Add("", "test"A_Index, "mike"A_Index)
}
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
LV := ExtListView_Initialize(LVwindowTitle)
;~ findText := "ghi"
;~ row := row(LV, findText)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "jklff"
;~ row := row(LV, findText, 2)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "bbbbbbbbbbbbbb"
;~ row := row(LV, findText)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
select(LV, "test42")
;~ select(LV, "jkl", COL := 2)
; select(LV, "hif")
MsgBox, "test42" selected - scroll down to see!
Return
select(LV, str, col := 1) { ; Select a row in a ListView, by string
(row := row(LV, str, col)) && ExtListView_ToggleSelection(LV, SELECT := True, row - 1)
}
row(LV, str, col := 1) { ; Find string in a ListView column
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; https://www.autohotkey.com/boards/viewtopic.php?p=463971#p463971
Loop {
next := ExtListView_GetNextItem(LV, row := A_Index - 1)
pos := Instr(ExtListView_GetItemText(LV, row, col - 1), str)
} Until (next < 1 || pos)
Return pos ? row + 1 : 0 ; Return the row number found, or zero
}
GuiClose:
GuiEscape:
ExitApp
Code: Select all
select(LV, "test41")
LV_Modify(LV_GetCount(), "Vis")
Thanks teadrinker !
Code: Select all
ExtListView_EnsureVisible(objLV, Row, fPartialOK:=false)
Code: Select all
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; ----------------------------------------------------------------------------------------------------------------------
; Name .........: ExtListView library
; Description ..: Collection of functions dealing with the ListViews of external processes.
; AHK Version ..: AHK_L 1.1.13.01 x32/64 ANSI/Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: May 18, 2013 - v0.1 - First revision.
; ..............: Jun. 28, 2013 - v0.2 - Added resizable buffer option.
; ..............: Feb. 04, 2014 - v0.3 - Unicode and x64 compatibility.
; ..............: Apr. 10, 2014 - v1.0 - Code refactoring. Added encoding option and simple error management.
; ..............: May 04, 2014 - v1.1 - Detached the handles and memory allocation code.
; ..............: May 05, 2014 - v1.2 - Created ExtListView_GetAllItems and ExtListView_ToggleSelection functions.
; ..............: May 06, 2014 - v2.0 - Complete rewrite of the library. Code more modular and updateable. Separated
; ..............: code for De/Initialization, GetNextItem and GetItemText.
; ..............: Jul 24, 2017 - v2.1 - Fixed LVITEM size issue.
; ----------------------------------------------------------------------------------------------------------------------
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetSingleItem
; Description ..: Get the first item with the desired state.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001 ;The item has the focus, so it is surrounded by a standard focus rectangle. Although more than one item may be selected, only one item can have the focus.
; ..............: LVNI_SELECTED - 0x0002 ;The item is selected. The appearance of a selected item depends on whether it has the focus and also on the system colors used for selection.
; ..............: LVNI_CUT - 0x0004 ;The item is marked for a cut-and-paste operation.
; ..............: LVNI_DROPHILITED - 0x0008 ;The item is highlighted as a drag-and-drop target.
; ..............: nCol - Column of the desired item (0-based index).
; Info .........: For more info on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Single item as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetSingleItem(ByRef objLV, sState, nCol) {
Try {
If ( (nRow := ExtListView_GetNextItem(objLV, -1, sState)) != -1 )
sItem := ExtListView_GetItemText(objLV, nRow, nCol)
} Catch e
Throw e
Return (sItem) ? sItem : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetAllItems
; Description ..: Get all items that share the same status on the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: For more infor on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Multidimensional array containing ListView's items. Eg: array[row][column] := "SomeString".
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetAllItems(ByRef objLV, sState:=0x0000) {
Try {
nRow := -1, objList := []
Loop
{
If ( (nRow := ExtListView_GetNextItem(objLV, nRow, sState)) == -1 )
Break
x := A_Index, objList[x] := []
Loop % objLV.cols
objList[x][A_Index] := ExtListView_GetItemText(objLV, nRow, A_Index-1)
}
} Catch e
Throw e
Return ( objList.MaxIndex() ) ? objList : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_ToggleSelection
; Description ..: Select/deselect items in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: bSelect - 1 for selection, 0 for deselection.
; ..............: nItem - -1 for all items or "n" (0-based) for a specific ListView item.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_ToggleSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0002 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0002, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.pwritebuf, "Ptr",&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv ;LVM_SETITEMSTATE
;#####, this works because it's reading from it's OWN MEMORY objLV.pwritebuf
}
ExtListView_ToggleFocusAndSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0003 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0003, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
ExtListView_ToggleFocus(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0001 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0001, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetNextItem
; Description ..: Get the next item in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row where to start the search for the next item (0-based index).
; ..............: lParam - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: LVM_GETNEXTITEM - http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetNextItem(ByRef objLV, nRow:=-1, lParam:=0x0000) {
; LVM_GETNEXTITEM = LVM_FIRST (0x1000) + 12 = 0x100C.
SendMessage, 0x100C, %nRow%, %lParam%,, % "ahk_id " objLV.hlv
Return ErrorLevel << 32 >> 32
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetItemText
; Description ..: Get the text of the desired item.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row of the desired item (0-based index).
; ..............: nCol - Column of the desired item (0-based index).
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetItemText(ByRef objLV, nRow, nCol) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0001, LVITEM, 0 ) ; mask = LVIF_TEXT = 0x0001.
NumPut( nRow, LVITEM, 4 ) ; iItem = Row to retrieve (0 = 1st row).
NumPut( nCol, LVITEM, 8 ) ; iSubItem = The column index of the item to retrieve.
NumPut( objLV.preadbuf, LVITEM, 20 + (A_PtrSize - 4) ) ; pszText = Pointer to item text string.
NumPut( objLV.szreadbuf, LVITEM, 20 + ((A_PtrSize * 2) - 4) ) ; cchTextMax = Number of TCHARs in the buffer.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf
, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
; LVM_GETITEMTEXTA = LVM_FIRST (0x1000) + 45 = 0x102D.
; LVM_GETITEMTEXTW = LVM_FIRST (0x1000) + 115 = 0x1073.
LVM_GETITEMTEXT := (objLV.senc == "UTF-8" || objLV.senc == "UTF-16") ? 0x1073 : 0x102D
SendMessage, %LVM_GETITEMTEXT%, %nRow%, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
VarSetCapacity(cRecvBuf, objLV.szreadbuf, 1)
If ( !DllCall( "ReadProcessMemory", Ptr,objLV.hproc, Ptr,objLV.preadbuf, Ptr,&cRecvBuf, UInt,objLV.szreadbuf
, Ptr,0 ) )
Throw Exception("objLV.preadbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
Return StrGet(&cRecvBuf, objLV.szreadbuf, objLV.senc)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_Initialize
; Description ..: Initialize the object containing ListView's related data.
; Parameters ...: sWnd - Title of the window containing the ListView.
; ..............: szReadBuf - Size of the buffer used for reading the target process memory. It must be capable enough
; ..............: to hold the longest cell in the ListView.
; ..............: sEnc - Target ListView's encoding. "CP0" for ANSI, "UTF-8" or "UTF-16" for Unicode.
; Return .......: objLV - External ListView initialized object with the following keys:
; ..............: objLV.swnd - Title of the window owning the ListView.
; ..............: objLV.hwnd - Handle to the window owning the ListView.
; ..............: objLV.hproc - Handle to the process owning the ListView.
; ..............: objLV.hlv - Handle to the ListView.
; ..............: objLV.hhdr - Handle to the header of the ListView.
; ..............: objLV.rows - Number of rows in the ListView.
; ..............: objLV.cols - Number of columns in the ListView.
; ..............: objLV.senc - Encoding used by the process owning the ListView.
; ..............: objLV.pwritebuf - Address to the buffer used to write the LVITEM message to the target ListView.
; ..............: objLV.szwritebuf - Size of the write buffer.
; ..............: objLV.preadbuf - Address to the buffer used to read the answer to the message sent.
; ..............: objLV.szreadbuf - Size of the read buffer.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_Initialize(sWnd, WHICHSysListView:="SysListView321", szReadBuf:=1024, sEnc:="CP0") {
objLV := Object()
objLV.swnd := sWnd
objLV.hwnd := WinExist(sWnd)
objLV.szwritebuf := (A_OSVersion == "WIN_XP") ? 52 + (A_PtrSize-4)*5 : 60 + (A_PtrSize-4)*7 ; Size of LVITEM
objLV.szreadbuf := szReadBuf
objLV.senc := sEnc
ControlGet, hLv, Hwnd,, % WHICHSysListView, % "ahk_id " objLV.hwnd
objLV.hlv := hLv
DllCall( "GetWindowThreadProcessId", Ptr,hLv, PtrP,dwProcessId )
; PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020.
If ( !(objLV.hproc := DllCall( "OpenProcess", UInt,0x0008|0x0010|0x0020, Int,0, UInt,dwProcessId )) )
Throw Exception("objLV.hproc: error opening process", "OpenProcess", "LastError: " A_LastError)
; LVM_GETITEMCOUNT = LVM_FIRST (0x1000) + 4 = 0x1004.
SendMessage, 0x1004, 0, 0,, % "ahk_id " objLV.hlv
objLV.rows := ErrorLevel
; LVM_GETHEADER = LVM_FIRST (0x1000) + 31 = 0x101F.
SendMessage, 0x101F, 0, 0,, % "ahk_id " objLV.hlv
objLV.hhdr := ErrorLevel
; HDM_GETITEMCOUNT = HDM_FIRST (0x1200) + 0 = 0x1200.
SendMessage, 0x1200, 0, 0,, % "ahk_id " objLV.hhdr
objLV.cols := ErrorLevel
; Allocate memory on the target process before returning the object.
If ( !__ExtListView_AllocateMemory(objLV) )
Throw Exception("Error allocating memory", "__ExtListView_Initialize", "LastError: " A_LastError)
Return objLV
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_DeInitialize
; Description ..: DeInitialize the object.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_DeInitialize(ByRef objLV) {
; Free the previously allocated memory on the target process.
If ( !__ExtListView_DeAllocateMemory(objLV) )
Throw Exception("Error deallocating memory", "__ExtListView_DeInitialize", "LastError: " A_LastError)
DllCall( "CloseHandle", Ptr,objLV.hproc )
objLV := ""
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_CheckInitObject
; Description ..: Check if the object is still referring to a valid ListView.
; Parameters ...: objLV - External ListView initialized object.
; Return .......: 0 if false, handle of the window containing the ListView if true.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_CheckInitObject(ByRef objLV) {
Return WinExist("ahk_id " objLV.hwnd)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
; hProcess:objLV.hproc
; lpAddress: NULL
; dwSize:UInt,objLV.szwritebuf
; flAllocationType:0x1000 ;MEM_RESET_UNDO ;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex#MEM_RESET_UNDO
; If the function succeeds, the return value is the base address of the allocated region of pages.
If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
If ( !(objLV.preadbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
; RECT is 16 bytes
If ( !(objLV.rectbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,16, UInt,0x1000
, UInt,0x4 )) )
Return 0
Return 1
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_DeAllocateMemory
; Description ..: Frees previously allocated memory.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_DeAllocateMemory(ByRef objLV) {
; MEM_RELEASE = 0x8000.
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("pwritebuf")
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.preadbuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("preadbuf")
Return 1
}
/* EXAMPLE CODE:
OnExit, QUIT
WINTITLE = Active Directory Users and Computers ahk_class MMCMainFrame
objLV := ExtListView_Initialize(WINTITLE)
HotKey, IfWinActive, %WINTITLE%
HotKey, ^!g, TOGGLESEL
Return
TOGGLESEL:
( ExtListView_CheckInitObject(objLV) ) ? objLV := ExtListView_Initialize(WINTITLE)
ExtListView_ToggleSelection(objLV, 1, 0)
Return
QUIT:
ExtListView_DeInitialize(objLV)
ExitApp
*/
; Focus and clicks last focused row || first row
ExtListView_RestoreFocus(objLV) {
focusedControl:=ExtListView_getFocusedControl(objLV)
;if not already focused
if (focusedControl!=objLV.hlv+0) {
FocusedRow:=ExtListView_GetNextItem(objLV,, 1)
if (FocusedRow==-1) {
; default to first row if no row Focused
FocusedRow:=0
}
ExtListView_EnsureVisible(objLV, FocusedRow)
ExtListView_ClickRow(objLV, FocusedRow)
}
}
ExtListView_ClickRow(objLV, Row) { ; just me -> https://www.autohotkey.com/board/topic/86490-click-listview-row/#entry550767
HLV:=objLV.hlv
rectbuf:=objLV.rectbuf
; HLV : ListView's HWND, Row : 0-based row number
SendMessage, 0x100E, % Row, % rectbuf,, % "ahk_id " HLV ; LVM_GETITEMRECT
VarSetCapacity(RECT, 16)
If ( !DllCall( "ReadProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.rectbuf, "Ptr",&RECT, UInt,16, UInt,0 ) )
Throw Exception("objLV.rectbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
short1:=NumGet(RECT, 0, "Short")
short2:=NumGet(RECT, 4, "Short")
POINT := short1 | (short2 << 16)
PostMessage, 0x0201, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONDOWN
PostMessage, 0x0202, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONUP
}
ExtListView_EnsureVisible(objLV, Row, fPartialOK:=false) { ; https://www.autohotkey.com/board/topic/8194-double-click-on-listview-selection/#post_id_51730
; fPartialOK - A value specifying whether the item must be entirely visible.
; If this parameter is TRUE, no scrolling occurs if the item is at least partially visible.
HLV:=objLV.hlv
; PostMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
SendMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
}
ExtListView_getFocusedControl(objLV) {
; https://www.autohotkey.com/boards/viewtopic.php?t=37120
static vTIDAhk := DllCall("GetCurrentThreadId", "UInt")
static GuiThreadInfo_Size:=24 + 6*A_PtrSize ;4 + 4 + 6*A_PtrSize + 16
static offset_hwndFocus := 8 + 1*A_PtrSize
; typedef struct tagGUITHREADINFO {
; DWORD cbSize; 0
; DWORD flags; 4
; HWND hwndActive; 8
; HWND hwndFocus; 8 + 1*A_PtrSize
; HWND hwndCapture; 8 + 2*A_PtrSize
; HWND hwndMenuOwner; 8 + 3*A_PtrSize
; HWND hwndMoveSize; 8 + 4*A_PtrSize
; HWND hwndCaret; 8 + 5*A_PtrSize
; RECT rcCaret; 8 + 6*A_PtrSize
; }
; DWORD is Uint
; BOOL AttachThreadInput(
; [in] DWORD idAttach,
; [in] DWORD idAttachTo,
; [in] BOOL fAttach
; );
; BOOL -> Int
vTID := DllCall("GetWindowThreadProcessId", "Ptr",objLV.hwnd, "Ptr",0, "UInt")
VarSetCapacity(GuiThreadInfo, GuiThreadInfo_Size, 0)
; GuiThreadInfo.cbSize = sizeof(GuiThreadInfo);
NumPut(GuiThreadInfo_Size, GuiThreadInfo,0,"Uint")
; GetGuiThreadInfo(vTID, &GuiThreadInfo)
DllCall("GetGUIThreadInfo", "Uint",vTID, "Ptr",&GuiThreadInfo)
hwndFocus:=NumGet(GuiThreadInfo, offset_hwndFocus, "Ptr")
return hwndFocus
}
LVwindowTitle := "Test" ; Adjust as needed
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
Loop, 50
{
LV_Add("", "test"A_Index, "mike"A_Index)
}
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
lookfor := "test42"
LV := ExtListView_Initialize(LVwindowTitle)
findText := lookfor
row := row(LV, findText)
LV := ExtListView_EnsureVisible(LVwindowTitle, row, fPartialOK:=false)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "jklff"
;~ row := row(LV, findText, 2)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "bbbbbbbbbbbbbb"
;~ row := row(LV, findText)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
select(LV, lookfor)
;~ select(LV, "jkl", COL := 2)
; select(LV, "hif")
MsgBox, %lookfor% selected - scroll down to see!
Return
select(LV, str, col := 1) { ; Select a row in a ListView, by string
(row := row(LV, str, col)) && ExtListView_ToggleSelection(LV, SELECT := True, row - 1)
}
row(LV, str, col := 1) { ; Find string in a ListView column
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; https://www.autohotkey.com/boards/viewtopic.php?p=463971#p463971
Loop {
next := ExtListView_GetNextItem(LV, row := A_Index - 1)
pos := Instr(ExtListView_GetItemText(LV, row, col - 1), str)
} Until (next < 1 || pos)
Return pos ? row + 1 : 0 ; Return the row number found, or zero
}
GuiClose:
GuiEscape:
ExitApp
Code: Select all
LV := ExtListView_EnsureVisible(LVwindowTitle, row, fPartialOK:=false)
Code: Select all
ExtListView_EnsureVisible(LV, row)
Code: Select all
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; ----------------------------------------------------------------------------------------------------------------------
; Name .........: ExtListView library
; Description ..: Collection of functions dealing with the ListViews of external processes.
; AHK Version ..: AHK_L 1.1.13.01 x32/64 ANSI/Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: May 18, 2013 - v0.1 - First revision.
; ..............: Jun. 28, 2013 - v0.2 - Added resizable buffer option.
; ..............: Feb. 04, 2014 - v0.3 - Unicode and x64 compatibility.
; ..............: Apr. 10, 2014 - v1.0 - Code refactoring. Added encoding option and simple error management.
; ..............: May 04, 2014 - v1.1 - Detached the handles and memory allocation code.
; ..............: May 05, 2014 - v1.2 - Created ExtListView_GetAllItems and ExtListView_ToggleSelection functions.
; ..............: May 06, 2014 - v2.0 - Complete rewrite of the library. Code more modular and updateable. Separated
; ..............: code for De/Initialization, GetNextItem and GetItemText.
; ..............: Jul 24, 2017 - v2.1 - Fixed LVITEM size issue.
; ----------------------------------------------------------------------------------------------------------------------
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetSingleItem
; Description ..: Get the first item with the desired state.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001 ;The item has the focus, so it is surrounded by a standard focus rectangle. Although more than one item may be selected, only one item can have the focus.
; ..............: LVNI_SELECTED - 0x0002 ;The item is selected. The appearance of a selected item depends on whether it has the focus and also on the system colors used for selection.
; ..............: LVNI_CUT - 0x0004 ;The item is marked for a cut-and-paste operation.
; ..............: LVNI_DROPHILITED - 0x0008 ;The item is highlighted as a drag-and-drop target.
; ..............: nCol - Column of the desired item (0-based index).
; Info .........: For more info on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Single item as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetSingleItem(ByRef objLV, sState, nCol) {
Try {
If ( (nRow := ExtListView_GetNextItem(objLV, -1, sState)) != -1 )
sItem := ExtListView_GetItemText(objLV, nRow, nCol)
} Catch e
Throw e
Return (sItem) ? sItem : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetAllItems
; Description ..: Get all items that share the same status on the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: For more infor on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Multidimensional array containing ListView's items. Eg: array[row][column] := "SomeString".
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetAllItems(ByRef objLV, sState:=0x0000) {
Try {
nRow := -1, objList := []
Loop
{
If ( (nRow := ExtListView_GetNextItem(objLV, nRow, sState)) == -1 )
Break
x := A_Index, objList[x] := []
Loop % objLV.cols
objList[x][A_Index] := ExtListView_GetItemText(objLV, nRow, A_Index-1)
}
} Catch e
Throw e
Return ( objList.MaxIndex() ) ? objList : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_ToggleSelection
; Description ..: Select/deselect items in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: bSelect - 1 for selection, 0 for deselection.
; ..............: nItem - -1 for all items or "n" (0-based) for a specific ListView item.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_ToggleSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0002 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0002, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.pwritebuf, "Ptr",&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv ;LVM_SETITEMSTATE
;#####, this works because it's reading from it's OWN MEMORY objLV.pwritebuf
}
ExtListView_ToggleFocusAndSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0003 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0003, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
ExtListView_ToggleFocus(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0001 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0001, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetNextItem
; Description ..: Get the next item in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row where to start the search for the next item (0-based index).
; ..............: lParam - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: LVM_GETNEXTITEM - http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetNextItem(ByRef objLV, nRow:=-1, lParam:=0x0000) {
; LVM_GETNEXTITEM = LVM_FIRST (0x1000) + 12 = 0x100C.
SendMessage, 0x100C, %nRow%, %lParam%,, % "ahk_id " objLV.hlv
Return ErrorLevel << 32 >> 32
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetItemText
; Description ..: Get the text of the desired item.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row of the desired item (0-based index).
; ..............: nCol - Column of the desired item (0-based index).
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetItemText(ByRef objLV, nRow, nCol) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0001, LVITEM, 0 ) ; mask = LVIF_TEXT = 0x0001.
NumPut( nRow, LVITEM, 4 ) ; iItem = Row to retrieve (0 = 1st row).
NumPut( nCol, LVITEM, 8 ) ; iSubItem = The column index of the item to retrieve.
NumPut( objLV.preadbuf, LVITEM, 20 + (A_PtrSize - 4) ) ; pszText = Pointer to item text string.
NumPut( objLV.szreadbuf, LVITEM, 20 + ((A_PtrSize * 2) - 4) ) ; cchTextMax = Number of TCHARs in the buffer.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf
, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
; LVM_GETITEMTEXTA = LVM_FIRST (0x1000) + 45 = 0x102D.
; LVM_GETITEMTEXTW = LVM_FIRST (0x1000) + 115 = 0x1073.
LVM_GETITEMTEXT := (objLV.senc == "UTF-8" || objLV.senc == "UTF-16") ? 0x1073 : 0x102D
SendMessage, %LVM_GETITEMTEXT%, %nRow%, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
VarSetCapacity(cRecvBuf, objLV.szreadbuf, 1)
If ( !DllCall( "ReadProcessMemory", Ptr,objLV.hproc, Ptr,objLV.preadbuf, Ptr,&cRecvBuf, UInt,objLV.szreadbuf
, Ptr,0 ) )
Throw Exception("objLV.preadbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
Return StrGet(&cRecvBuf, objLV.szreadbuf, objLV.senc)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_Initialize
; Description ..: Initialize the object containing ListView's related data.
; Parameters ...: sWnd - Title of the window containing the ListView.
; ..............: szReadBuf - Size of the buffer used for reading the target process memory. It must be capable enough
; ..............: to hold the longest cell in the ListView.
; ..............: sEnc - Target ListView's encoding. "CP0" for ANSI, "UTF-8" or "UTF-16" for Unicode.
; Return .......: objLV - External ListView initialized object with the following keys:
; ..............: objLV.swnd - Title of the window owning the ListView.
; ..............: objLV.hwnd - Handle to the window owning the ListView.
; ..............: objLV.hproc - Handle to the process owning the ListView.
; ..............: objLV.hlv - Handle to the ListView.
; ..............: objLV.hhdr - Handle to the header of the ListView.
; ..............: objLV.rows - Number of rows in the ListView.
; ..............: objLV.cols - Number of columns in the ListView.
; ..............: objLV.senc - Encoding used by the process owning the ListView.
; ..............: objLV.pwritebuf - Address to the buffer used to write the LVITEM message to the target ListView.
; ..............: objLV.szwritebuf - Size of the write buffer.
; ..............: objLV.preadbuf - Address to the buffer used to read the answer to the message sent.
; ..............: objLV.szreadbuf - Size of the read buffer.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_Initialize(sWnd, WHICHSysListView:="SysListView321", szReadBuf:=1024, sEnc:="CP0") {
objLV := Object()
objLV.swnd := sWnd
objLV.hwnd := WinExist(sWnd)
objLV.szwritebuf := (A_OSVersion == "WIN_XP") ? 52 + (A_PtrSize-4)*5 : 60 + (A_PtrSize-4)*7 ; Size of LVITEM
objLV.szreadbuf := szReadBuf
objLV.senc := sEnc
ControlGet, hLv, Hwnd,, % WHICHSysListView, % "ahk_id " objLV.hwnd
objLV.hlv := hLv
DllCall( "GetWindowThreadProcessId", Ptr,hLv, PtrP,dwProcessId )
; PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020.
If ( !(objLV.hproc := DllCall( "OpenProcess", UInt,0x0008|0x0010|0x0020, Int,0, UInt,dwProcessId )) )
Throw Exception("objLV.hproc: error opening process", "OpenProcess", "LastError: " A_LastError)
; LVM_GETITEMCOUNT = LVM_FIRST (0x1000) + 4 = 0x1004.
SendMessage, 0x1004, 0, 0,, % "ahk_id " objLV.hlv
objLV.rows := ErrorLevel
; LVM_GETHEADER = LVM_FIRST (0x1000) + 31 = 0x101F.
SendMessage, 0x101F, 0, 0,, % "ahk_id " objLV.hlv
objLV.hhdr := ErrorLevel
; HDM_GETITEMCOUNT = HDM_FIRST (0x1200) + 0 = 0x1200.
SendMessage, 0x1200, 0, 0,, % "ahk_id " objLV.hhdr
objLV.cols := ErrorLevel
; Allocate memory on the target process before returning the object.
If ( !__ExtListView_AllocateMemory(objLV) )
Throw Exception("Error allocating memory", "__ExtListView_Initialize", "LastError: " A_LastError)
Return objLV
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_DeInitialize
; Description ..: DeInitialize the object.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_DeInitialize(ByRef objLV) {
; Free the previously allocated memory on the target process.
If ( !__ExtListView_DeAllocateMemory(objLV) )
Throw Exception("Error deallocating memory", "__ExtListView_DeInitialize", "LastError: " A_LastError)
DllCall( "CloseHandle", Ptr,objLV.hproc )
objLV := ""
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_CheckInitObject
; Description ..: Check if the object is still referring to a valid ListView.
; Parameters ...: objLV - External ListView initialized object.
; Return .......: 0 if false, handle of the window containing the ListView if true.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_CheckInitObject(ByRef objLV) {
Return WinExist("ahk_id " objLV.hwnd)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
; hProcess:objLV.hproc
; lpAddress: NULL
; dwSize:UInt,objLV.szwritebuf
; flAllocationType:0x1000 ;MEM_RESET_UNDO ;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex#MEM_RESET_UNDO
; If the function succeeds, the return value is the base address of the allocated region of pages.
If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
If ( !(objLV.preadbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
; RECT is 16 bytes
If ( !(objLV.rectbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,16, UInt,0x1000
, UInt,0x4 )) )
Return 0
Return 1
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_DeAllocateMemory
; Description ..: Frees previously allocated memory.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_DeAllocateMemory(ByRef objLV) {
; MEM_RELEASE = 0x8000.
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("pwritebuf")
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.preadbuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("preadbuf")
Return 1
}
/* EXAMPLE CODE:
OnExit, QUIT
WINTITLE = Active Directory Users and Computers ahk_class MMCMainFrame
objLV := ExtListView_Initialize(WINTITLE)
HotKey, IfWinActive, %WINTITLE%
HotKey, ^!g, TOGGLESEL
Return
TOGGLESEL:
( ExtListView_CheckInitObject(objLV) ) ? objLV := ExtListView_Initialize(WINTITLE)
ExtListView_ToggleSelection(objLV, 1, 0)
Return
QUIT:
ExtListView_DeInitialize(objLV)
ExitApp
*/
; Focus and clicks last focused row || first row
ExtListView_RestoreFocus(objLV) {
focusedControl:=ExtListView_getFocusedControl(objLV)
;if not already focused
if (focusedControl!=objLV.hlv+0) {
FocusedRow:=ExtListView_GetNextItem(objLV,, 1)
if (FocusedRow==-1) {
; default to first row if no row Focused
FocusedRow:=0
}
ExtListView_EnsureVisible(objLV, FocusedRow)
ExtListView_ClickRow(objLV, FocusedRow)
}
}
ExtListView_ClickRow(objLV, Row) { ; just me -> https://www.autohotkey.com/board/topic/86490-click-listview-row/#entry550767
HLV:=objLV.hlv
rectbuf:=objLV.rectbuf
; HLV : ListView's HWND, Row : 0-based row number
SendMessage, 0x100E, % Row, % rectbuf,, % "ahk_id " HLV ; LVM_GETITEMRECT
VarSetCapacity(RECT, 16)
If ( !DllCall( "ReadProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.rectbuf, "Ptr",&RECT, UInt,16, UInt,0 ) )
Throw Exception("objLV.rectbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
short1:=NumGet(RECT, 0, "Short")
short2:=NumGet(RECT, 4, "Short")
POINT := short1 | (short2 << 16)
PostMessage, 0x0201, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONDOWN
PostMessage, 0x0202, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONUP
}
ExtListView_EnsureVisible(objLV, Row, fPartialOK:=false) { ; https://www.autohotkey.com/board/topic/8194-double-click-on-listview-selection/#post_id_51730
; fPartialOK - A value specifying whether the item must be entirely visible.
; If this parameter is TRUE, no scrolling occurs if the item is at least partially visible.
HLV:=objLV.hlv
; PostMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
SendMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
}
ExtListView_getFocusedControl(objLV) {
; https://www.autohotkey.com/boards/viewtopic.php?t=37120
static vTIDAhk := DllCall("GetCurrentThreadId", "UInt")
static GuiThreadInfo_Size:=24 + 6*A_PtrSize ;4 + 4 + 6*A_PtrSize + 16
static offset_hwndFocus := 8 + 1*A_PtrSize
; typedef struct tagGUITHREADINFO {
; DWORD cbSize; 0
; DWORD flags; 4
; HWND hwndActive; 8
; HWND hwndFocus; 8 + 1*A_PtrSize
; HWND hwndCapture; 8 + 2*A_PtrSize
; HWND hwndMenuOwner; 8 + 3*A_PtrSize
; HWND hwndMoveSize; 8 + 4*A_PtrSize
; HWND hwndCaret; 8 + 5*A_PtrSize
; RECT rcCaret; 8 + 6*A_PtrSize
; }
; DWORD is Uint
; BOOL AttachThreadInput(
; [in] DWORD idAttach,
; [in] DWORD idAttachTo,
; [in] BOOL fAttach
; );
; BOOL -> Int
vTID := DllCall("GetWindowThreadProcessId", "Ptr",objLV.hwnd, "Ptr",0, "UInt")
VarSetCapacity(GuiThreadInfo, GuiThreadInfo_Size, 0)
; GuiThreadInfo.cbSize = sizeof(GuiThreadInfo);
NumPut(GuiThreadInfo_Size, GuiThreadInfo,0,"Uint")
; GetGuiThreadInfo(vTID, &GuiThreadInfo)
DllCall("GetGUIThreadInfo", "Uint",vTID, "Ptr",&GuiThreadInfo)
hwndFocus:=NumGet(GuiThreadInfo, offset_hwndFocus, "Ptr")
return hwndFocus
}
LVwindowTitle := "Test" ; Adjust as needed
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
Loop, 50
{
LV_Add("", "test"A_Index, "mike"A_Index)
}
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
lookfor := "test42"
LV := ExtListView_Initialize(LVwindowTitle)
;~ findText := lookfor
;~ row := row(LV, findText)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "jklff"
;~ row := row(LV, findText, 2)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
;~ findText := "bbbbbbbbbbbbbb"
;~ row := row(LV, findText)
;~ MsgBox, 64, Text, Text: %findText%`n`nRow: %row%
F1::
select(LV, lookfor)
;~ select(LV, "jkl", COL := 2)
; select(LV, "hif")
Return
select(LV, str, col := 1) { ; Select a row in a ListView, by string
(row := row(LV, str, col)) && ExtListView_ToggleSelection(LV, SELECT := True, row - 1)
(row := row(LV, str, col)) && ExtListView_EnsureVisible(LV, Row)
}
row(LV, str, col := 1) { ; Find string in a ListView column
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; https://www.autohotkey.com/boards/viewtopic.php?p=463971#p463971
Loop {
next := ExtListView_GetNextItem(LV, row := A_Index - 1)
pos := Instr(ExtListView_GetItemText(LV, row, col - 1), str)
} Until (next < 1 || pos)
Return pos ? row + 1 : 0 ; Return the row number found, or zero
}
GuiClose:
GuiEscape:
ExitApp
once I saw LV_Add("", "test" A_Index, "mike" A_Index), I was like : ayt, this is runnable/reproducible code, not same random listview(on your computer) that I don't have access to, that I can't testneed help with unselect all the rows before selecting the row name "test42" ? (F1 key to select),
so only 1 row selected\focused at same time
Code: Select all
LVwindowTitle := "Test" ; Adjust as needed
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
Loop, 50
{
LV_Add("", "test"A_Index, "mike"A_Index)
}
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
Code: Select all
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance force
ListLines Off
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetBatchLines -1
#KeyHistory 0
LVwindowTitle := "Test" ; Adjust as needed
Gui, Font, s10
Gui, Add, ListView, r10, A|B
LV_Add("", "abc" , "def")
LV_Add("", "ghi" , "jkl")
Loop, 50
{
LV_Add("", "test" A_Index, "mike" A_Index)
}
LV_ModifyCol(1, 50), LV_ModifyCol(2, 50)
Gui, Show,, %LVwindowTitle%
objLV := ExtListView_Initialize(LVwindowTitle)
f1::
row:=ExtListView_findRowWithString(objLV, "test42")
if (row != -1) {
ExtListView_EnsureVisible(objLV, row)
ExtListView_ClickRow(objLV, row)
}
Return
ExtListView_findRowWithString(objLV, str, col:=0) {
row:=0
while (row < objLV.rows) {
text:=ExtListView_GetItemText(objLV, row, col)
if (text == str) { ;copy this function if you want case insensitive
return row
}
row++
}
return -1
}
GuiClose:
GuiEscape:
ExitApp
f3::Exitapp
; https://www.autohotkey.com/boards/viewtopic.php?t=3513
; ----------------------------------------------------------------------------------------------------------------------
; Name .........: ExtListView library
; Description ..: Collection of functions dealing with the ListViews of external processes.
; AHK Version ..: AHK_L 1.1.13.01 x32/64 ANSI/Unicode
; Author .......: Cyruz - http://ciroprincipe.info
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: May 18, 2013 - v0.1 - First revision.
; ..............: Jun. 28, 2013 - v0.2 - Added resizable buffer option.
; ..............: Feb. 04, 2014 - v0.3 - Unicode and x64 compatibility.
; ..............: Apr. 10, 2014 - v1.0 - Code refactoring. Added encoding option and simple error management.
; ..............: May 04, 2014 - v1.1 - Detached the handles and memory allocation code.
; ..............: May 05, 2014 - v1.2 - Created ExtListView_GetAllItems and ExtListView_ToggleSelection functions.
; ..............: May 06, 2014 - v2.0 - Complete rewrite of the library. Code more modular and updateable. Separated
; ..............: code for De/Initialization, GetNextItem and GetItemText.
; ..............: Jul 24, 2017 - v2.1 - Fixed LVITEM size issue.
; ----------------------------------------------------------------------------------------------------------------------
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetSingleItem
; Description ..: Get the first item with the desired state.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001 ;The item has the focus, so it is surrounded by a standard focus rectangle. Although more than one item may be selected, only one item can have the focus.
; ..............: LVNI_SELECTED - 0x0002 ;The item is selected. The appearance of a selected item depends on whether it has the focus and also on the system colors used for selection.
; ..............: LVNI_CUT - 0x0004 ;The item is marked for a cut-and-paste operation.
; ..............: LVNI_DROPHILITED - 0x0008 ;The item is highlighted as a drag-and-drop target.
; ..............: nCol - Column of the desired item (0-based index).
; Info .........: For more info on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Single item as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetSingleItem(ByRef objLV, sState, nCol) {
Try {
If ( (nRow := ExtListView_GetNextItem(objLV, -1, sState)) != -1 )
sItem := ExtListView_GetItemText(objLV, nRow, nCol)
} Catch e
Throw e
Return (sItem) ? sItem : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetAllItems
; Description ..: Get all items that share the same status on the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: sState - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: For more infor on the sState parameter have a look at the MSDN docs for the LVM_GETNEXTITEM message:
; ..............: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Multidimensional array containing ListView's items. Eg: array[row][column] := "SomeString".
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetAllItems(ByRef objLV, sState:=0x0000) {
Try {
nRow := -1, objList := []
Loop
{
If ( (nRow := ExtListView_GetNextItem(objLV, nRow, sState)) == -1 )
Break
x := A_Index, objList[x] := []
Loop % objLV.cols
objList[x][A_Index] := ExtListView_GetItemText(objLV, nRow, A_Index-1)
}
} Catch e
Throw e
Return ( objList.MaxIndex() ) ? objList : 0
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_ToggleSelection
; Description ..: Select/deselect items in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: bSelect - 1 for selection, 0 for deselection.
; ..............: nItem - -1 for all items or "n" (0-based) for a specific ListView item.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_ToggleSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0002 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0002, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.pwritebuf, "Ptr",&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv ;LVM_SETITEMSTATE
;#####, this works because it's reading from it's OWN MEMORY objLV.pwritebuf
}
ExtListView_ToggleFocusAndSelection(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0003 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0003, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
ExtListView_ToggleFocus(ByRef objLV, bSelect:=1, nItem:=-1) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0008, LVITEM, 0 ) ; mask = LVIF_STATE = 0x0008.
NumPut( nItem, LVITEM, 4 ) ; iItem.
NumPut( 0, LVITEM, 8 ) ; iSubItem.
NumPut( (bSelect) ? 0x0001 : 0x0000, LVITEM, 12 ) ; state = LVIS_SELECTED = 0x0002 or 0x0000 (reset mask).
NumPut( 0x0001, LVITEM, 16 ) ; stateMask = LVIS_SELECTED = 0x0002.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,20, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
SendMessage, 0x102B, % nItem, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetNextItem
; Description ..: Get the next item in the target ListView.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row where to start the search for the next item (0-based index).
; ..............: lParam - Status of the searched item. Common statuses are:
; ..............: LVNI_ALL - 0x0000
; ..............: LVNI_FOCUSED - 0x0001
; ..............: LVNI_SELECTED - 0x0002
; ..............: LVNI_CUT - 0x0004
; ..............: LVNI_DROPHILITED - 0x0008
; Info .........: LVM_GETNEXTITEM - http://msdn.microsoft.com/en-us/library/windows/desktop/bb761057%28v=vs.85%29.aspx
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetNextItem(ByRef objLV, nRow:=-1, lParam:=0x0000) {
; LVM_GETNEXTITEM = LVM_FIRST (0x1000) + 12 = 0x100C.
SendMessage, 0x100C, %nRow%, %lParam%,, % "ahk_id " objLV.hlv
Return ErrorLevel << 32 >> 32
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_GetItemText
; Description ..: Get the text of the desired item.
; Parameters ...: objLV - External ListView initialized object.
; ..............: nRow - Row of the desired item (0-based index).
; ..............: nCol - Column of the desired item (0-based index).
; Return .......: Item content as a string.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_GetItemText(ByRef objLV, nRow, nCol) {
VarSetCapacity( LVITEM, objLV.szwritebuf, 0 )
NumPut( 0x0001, LVITEM, 0 ) ; mask = LVIF_TEXT = 0x0001.
NumPut( nRow, LVITEM, 4 ) ; iItem = Row to retrieve (0 = 1st row).
NumPut( nCol, LVITEM, 8 ) ; iSubItem = The column index of the item to retrieve.
NumPut( objLV.preadbuf, LVITEM, 20 + (A_PtrSize - 4) ) ; pszText = Pointer to item text string.
NumPut( objLV.szreadbuf, LVITEM, 20 + ((A_PtrSize * 2) - 4) ) ; cchTextMax = Number of TCHARs in the buffer.
If ( !DllCall( "WriteProcessMemory", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, Ptr,&LVITEM, UInt,objLV.szwritebuf
, UInt,0 ) )
Throw Exception("objLV.pwritebuf: error writing memory", "WriteProcessMemory", "LastError: " A_LastError)
; LVM_GETITEMTEXTA = LVM_FIRST (0x1000) + 45 = 0x102D.
; LVM_GETITEMTEXTW = LVM_FIRST (0x1000) + 115 = 0x1073.
LVM_GETITEMTEXT := (objLV.senc == "UTF-8" || objLV.senc == "UTF-16") ? 0x1073 : 0x102D
SendMessage, %LVM_GETITEMTEXT%, %nRow%, % objLV.pwritebuf,, % "ahk_id " objLV.hlv
VarSetCapacity(cRecvBuf, objLV.szreadbuf, 1)
If ( !DllCall( "ReadProcessMemory", Ptr,objLV.hproc, Ptr,objLV.preadbuf, Ptr,&cRecvBuf, UInt,objLV.szreadbuf
, Ptr,0 ) )
Throw Exception("objLV.preadbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
Return StrGet(&cRecvBuf, objLV.szreadbuf, objLV.senc)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_Initialize
; Description ..: Initialize the object containing ListView's related data.
; Parameters ...: sWnd - Title of the window containing the ListView.
; ..............: szReadBuf - Size of the buffer used for reading the target process memory. It must be capable enough
; ..............: to hold the longest cell in the ListView.
; ..............: sEnc - Target ListView's encoding. "CP0" for ANSI, "UTF-8" or "UTF-16" for Unicode.
; Return .......: objLV - External ListView initialized object with the following keys:
; ..............: objLV.swnd - Title of the window owning the ListView.
; ..............: objLV.hwnd - Handle to the window owning the ListView.
; ..............: objLV.hproc - Handle to the process owning the ListView.
; ..............: objLV.hlv - Handle to the ListView.
; ..............: objLV.hhdr - Handle to the header of the ListView.
; ..............: objLV.rows - Number of rows in the ListView.
; ..............: objLV.cols - Number of columns in the ListView.
; ..............: objLV.senc - Encoding used by the process owning the ListView.
; ..............: objLV.pwritebuf - Address to the buffer used to write the LVITEM message to the target ListView.
; ..............: objLV.szwritebuf - Size of the write buffer.
; ..............: objLV.preadbuf - Address to the buffer used to read the answer to the message sent.
; ..............: objLV.szreadbuf - Size of the read buffer.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_Initialize(sWnd, WHICHSysListView:="SysListView321", szReadBuf:=1024, sEnc:="CP0") {
objLV := Object()
objLV.swnd := sWnd
objLV.hwnd := WinExist(sWnd)
objLV.szwritebuf := (A_OSVersion == "WIN_XP") ? 52 + (A_PtrSize-4)*5 : 60 + (A_PtrSize-4)*7 ; Size of LVITEM
objLV.szreadbuf := szReadBuf
objLV.senc := sEnc
ControlGet, hLv, Hwnd,, % WHICHSysListView, % "ahk_id " objLV.hwnd
objLV.hlv := hLv
DllCall( "GetWindowThreadProcessId", Ptr,hLv, PtrP,dwProcessId )
; PROCESS_VM_OPERATION = 0x0008, PROCESS_VM_READ = 0x0010, PROCESS_VM_WRITE = 0x0020.
If ( !(objLV.hproc := DllCall( "OpenProcess", UInt,0x0008|0x0010|0x0020, Int,0, UInt,dwProcessId )) )
Throw Exception("objLV.hproc: error opening process", "OpenProcess", "LastError: " A_LastError)
; LVM_GETITEMCOUNT = LVM_FIRST (0x1000) + 4 = 0x1004.
SendMessage, 0x1004, 0, 0,, % "ahk_id " objLV.hlv
objLV.rows := ErrorLevel
; LVM_GETHEADER = LVM_FIRST (0x1000) + 31 = 0x101F.
SendMessage, 0x101F, 0, 0,, % "ahk_id " objLV.hlv
objLV.hhdr := ErrorLevel
; HDM_GETITEMCOUNT = HDM_FIRST (0x1200) + 0 = 0x1200.
SendMessage, 0x1200, 0, 0,, % "ahk_id " objLV.hhdr
objLV.cols := ErrorLevel
; Allocate memory on the target process before returning the object.
If ( !__ExtListView_AllocateMemory(objLV) )
Throw Exception("Error allocating memory", "__ExtListView_Initialize", "LastError: " A_LastError)
Return objLV
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_DeInitialize
; Description ..: DeInitialize the object.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_DeInitialize(ByRef objLV) {
; Free the previously allocated memory on the target process.
If ( !__ExtListView_DeAllocateMemory(objLV) )
Throw Exception("Error deallocating memory", "__ExtListView_DeInitialize", "LastError: " A_LastError)
DllCall( "CloseHandle", Ptr,objLV.hproc )
objLV := ""
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: ExtListView_CheckInitObject
; Description ..: Check if the object is still referring to a valid ListView.
; Parameters ...: objLV - External ListView initialized object.
; Return .......: 0 if false, handle of the window containing the ListView if true.
; ----------------------------------------------------------------------------------------------------------------------
ExtListView_CheckInitObject(ByRef objLV) {
Return WinExist("ahk_id " objLV.hwnd)
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_AllocateMemory
; Description ..: Allocates memory into the target process.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_AllocateMemory(ByRef objLV) {
; MEM_COMMIT = 0x1000, PAGE_READWRITE = 0x4.
; hProcess:objLV.hproc
; lpAddress: NULL
; dwSize:UInt,objLV.szwritebuf
; flAllocationType:0x1000 ;MEM_RESET_UNDO ;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex#MEM_RESET_UNDO
; If the function succeeds, the return value is the base address of the allocated region of pages.
If ( !(objLV.pwritebuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szwritebuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
If ( !(objLV.preadbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,objLV.szreadbuf, UInt,0x1000
, UInt,0x4 )) )
Return 0
; RECT is 16 bytes
If ( !(objLV.rectbuf := DllCall( "VirtualAllocEx", Ptr,objLV.hproc, Ptr,0, UInt,16, UInt,0x1000
, UInt,0x4 )) )
Return 0
Return 1
}
; ----------------------------------------------------------------------------------------------------------------------
; Function .....: __ExtListView_DeAllocateMemory
; Description ..: Frees previously allocated memory.
; Parameters ...: objLV - External ListView initialized object.
; ----------------------------------------------------------------------------------------------------------------------
__ExtListView_DeAllocateMemory(ByRef objLV) {
; MEM_RELEASE = 0x8000.
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.pwritebuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("pwritebuf")
If ( !DllCall( "VirtualFreeEx", Ptr,objLV.hproc, Ptr,objLV.preadbuf, UInt,0, UInt,0x8000 ) )
Return 0
objLV.Remove("preadbuf")
Return 1
}
/* EXAMPLE CODE:
OnExit, QUIT
WINTITLE = Active Directory Users and Computers ahk_class MMCMainFrame
objLV := ExtListView_Initialize(WINTITLE)
HotKey, IfWinActive, %WINTITLE%
HotKey, ^!g, TOGGLESEL
Return
TOGGLESEL:
( ExtListView_CheckInitObject(objLV) ) ? objLV := ExtListView_Initialize(WINTITLE)
ExtListView_ToggleSelection(objLV, 1, 0)
Return
QUIT:
ExtListView_DeInitialize(objLV)
ExitApp
*/
; Focus and clicks last focused row || first row
ExtListView_RestoreFocus(objLV) {
focusedControl:=ExtListView_getFocusedControl(objLV)
;if not already focused
if (focusedControl!=objLV.hlv+0) {
FocusedRow:=ExtListView_GetNextItem(objLV,, 1)
if (FocusedRow==-1) {
; default to first row if no row Focused
FocusedRow:=0
}
ExtListView_EnsureVisible(objLV, FocusedRow)
ExtListView_ClickRow(objLV, FocusedRow)
}
}
ExtListView_ClickRow(objLV, Row) { ; just me -> https://www.autohotkey.com/board/topic/86490-click-listview-row/#entry550767
HLV:=objLV.hlv
rectbuf:=objLV.rectbuf
; HLV : ListView's HWND, Row : 0-based row number
SendMessage, 0x100E, % Row, % rectbuf,, % "ahk_id " HLV ; LVM_GETITEMRECT
VarSetCapacity(RECT, 16)
If ( !DllCall( "ReadProcessMemory", "Ptr",objLV.hproc, "Ptr",objLV.rectbuf, "Ptr",&RECT, UInt,16, UInt,0 ) )
Throw Exception("objLV.rectbuf: error reading memory", "ReadProcessMemory", "LastError: " A_LastError)
short1:=NumGet(RECT, 0, "Short")
short2:=NumGet(RECT, 4, "Short")
POINT := short1 | (short2 << 16)
PostMessage, 0x0201, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONDOWN
PostMessage, 0x0202, 0, POINT,, % "ahk_id " HLV ; WM_LBUTTONUP
}
ExtListView_EnsureVisible(objLV, Row, fPartialOK:=false) { ; https://www.autohotkey.com/board/topic/8194-double-click-on-listview-selection/#post_id_51730
; fPartialOK - A value specifying whether the item must be entirely visible.
; If this parameter is TRUE, no scrolling occurs if the item is at least partially visible.
HLV:=objLV.hlv
; PostMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
SendMessage, 0x1013, Row, fPartialOK,, % "ahk_id " HLV ; LVM_ENSUREVISIBLE
}
ExtListView_getFocusedControl(objLV) {
; https://www.autohotkey.com/boards/viewtopic.php?t=37120
static vTIDAhk := DllCall("GetCurrentThreadId", "UInt")
static GuiThreadInfo_Size:=24 + 6*A_PtrSize ;4 + 4 + 6*A_PtrSize + 16
static offset_hwndFocus := 8 + 1*A_PtrSize
; typedef struct tagGUITHREADINFO {
; DWORD cbSize; 0
; DWORD flags; 4
; HWND hwndActive; 8
; HWND hwndFocus; 8 + 1*A_PtrSize
; HWND hwndCapture; 8 + 2*A_PtrSize
; HWND hwndMenuOwner; 8 + 3*A_PtrSize
; HWND hwndMoveSize; 8 + 4*A_PtrSize
; HWND hwndCaret; 8 + 5*A_PtrSize
; RECT rcCaret; 8 + 6*A_PtrSize
; }
; DWORD is Uint
; BOOL AttachThreadInput(
; [in] DWORD idAttach,
; [in] DWORD idAttachTo,
; [in] BOOL fAttach
; );
; BOOL -> Int
vTID := DllCall("GetWindowThreadProcessId", "Ptr",objLV.hwnd, "Ptr",0, "UInt")
VarSetCapacity(GuiThreadInfo, GuiThreadInfo_Size, 0)
; GuiThreadInfo.cbSize = sizeof(GuiThreadInfo);
NumPut(GuiThreadInfo_Size, GuiThreadInfo,0,"Uint")
; GetGuiThreadInfo(vTID, &GuiThreadInfo)
DllCall("GetGUIThreadInfo", "Uint",vTID, "Ptr",&GuiThreadInfo)
hwndFocus:=NumGet(GuiThreadInfo, offset_hwndFocus, "Ptr")
return hwndFocus
}
https://docs.microsoft.com/en-us/windows/win32/controls/lvm-getitemtext#remarks wrote:LVM_GETITEMTEXT is not supported under the LVS_OWNERDATA style.
Code: Select all
ControlGet, OutputStyle, Style ,,, % "ahk_id " objLV.hlv
MsgBox % OutputStyle & LVS_OWNERDATA:=0x1000
Users browsing this forum: Bing [Bot], Spawnova and 273 guests