Windows 使用SendMessageAPI获取检查列表框中项目的状态
我正在使用一个软件来操作另一个软件,比如软件测试环境,目的是获取一些值并执行一些任务。为此,我使用SendMessageAPI,它在几乎所有Windows控件中都运行良好,除了在CheckListBox中。“从”软件是在Delphi中创建的,因此,我不确定该复选框是否是标准的Windows控件,无论如何,这是MS的文档:Windows 使用SendMessageAPI获取检查列表框中项目的状态,windows,delphi,winapi,sendmessage,Windows,Delphi,Winapi,Sendmessage,我正在使用一个软件来操作另一个软件,比如软件测试环境,目的是获取一些值并执行一些任务。为此,我使用SendMessageAPI,它在几乎所有Windows控件中都运行良好,除了在CheckListBox中。“从”软件是在Delphi中创建的,因此,我不确定该复选框是否是标准的Windows控件,无论如何,这是MS的文档: 在这个控件中,我可以获得项目的数量、文本、选择的文本以及许多其他信息,但我无法知道是否检查了项目。我尝试使用一些工具,如“针对Windows的辅助功能洞察”和AutoIt,但
在这个控件中,我可以获得项目的数量、文本、选择的文本以及许多其他信息,但我无法知道是否检查了项目。我尝试使用一些工具,如“针对Windows的辅助功能洞察”和AutoIt,但没有结果。
您知道如何在Delphi复选框中获取复选框的状态吗?
提前感谢。Delphi将选中的信息存储在
TCheckListBoxDataWrapper
对象中。指向该对象的指针存储在复选框项的常规“项数据”中。然后,该对象具有一个布尔属性State
,您可以在偏移量8处找到该属性
注意:如果您的程序的特定Delphi版本的偏移量与8不同,请尝试-4、12、…-它不可能走得很远
要确定是否已选中某个项目,您需要:
TCheckListBoxDataWrapper
的指针。这可以通过发送LB_GETITEMDATA
消息来完成。如果返回零,它也将被视为未检查ReadProcessMemory
。知道状态
属性位于偏移量8,您可以调用ReadProcessMemory(hProcess,itemData+8,&checked,1,NULL)
将1个字节读入变量checked
。(首先需要使用OpenProcess
打开目标进程)中检查项目的选中状态
<代码>1表示选中,代码>0表示未选中
如果以后还需要访问其他内部状态,另一个提示是:有一个窗口属性
ControlOfxxxxxxxyyyyyyyy
,其中X
是窗口所有者的HINSTANCE
(基址)(通常00400000
),而Y
是窗口所有者的(十六进制)线程ID(您可以使用GetWindowThreadProcessId
获取该属性)。您可以使用GetProp
获取该属性的值,该属性将是指向控件对象的指针(在本例中为TCheckListBox
本身)。然后,您可以使用ReadProcessMemory
来获取所需的其他数据。不过,您需要知道偏移量(但您可以使用调试器来尝试并找出它们)。使用相同的Delphi版本编译测试程序并在其中执行访问这些属性的函数非常有用,然后您可以调试自己的测试程序,并更轻松地计算偏移量
一种更高级的方法是将自定义DLL(用相同的Delphi版本编写)注入目标进程,允许访问(读和写)这类数据更直接。我很久以前就写过。Delphi将选中的信息存储在
TCheckListBoxDataWrapper
对象中。指向该对象的指针存储在checkbox item的常规“item data”中。然后该对象具有布尔属性State
,您可以在偏移量8处找到该属性
注意:如果您的程序的特定Delphi版本的偏移量与8的偏移量不同,请尝试附近的东西-4、12、…-它不会太远
要确定是否已选中某个项目,您需要:
TCheckListBoxDataWrapper
的指针。这可以通过发送LB_GETITEMDATA
消息来完成。如果返回零,则它也被视为未选中ReadProcessMemory
。知道State
属性位于偏移量8处,您可以调用ReadProcessMemory(hProcess,itemData+8,&checked,1,NULL)
要在变量中读取1个字节,请选中(首先需要使用OpenProcess
打开目标进程)
checked
!1
中检查项目的选中状态,在0
中检查项目的未选中状态
如果以后还需要访问其他内部状态,另一个提示是:有一个窗口属性
ControlOfxxxxxxxyyyyyyyy
,其中X
是窗口所有者的HINSTANCE
(基址)(通常00400000
),而Y
是窗口所有者的(十六进制)线程ID(您可以使用GetWindowThreadProcessId
获取该属性)。您可以使用GetProp
获取该属性的值,该属性将是指向控件对象的指针(在本例中为TCheckListBox
本身)。然后,您可以使用ReadProcessMemory
来获取所需的其他数据。不过,您需要知道偏移量(但您可以使用调试器来尝试并找出它们)。使用相同的Delphi版本编译测试程序并在其中执行访问这些属性的函数非常有用,然后您可以调试自己的测试程序,并更轻松地计算偏移量
一种更高级的方法是将自定义DLL(以相同的Delphi版本编写)注入目标进程,允许更直接地访问(读取和写入)此类数据。我很久以前就写过。正如@CherryDT发布的,这是访问CheckListBox状态的方法。我使用AutoIt
;------------------------------------------------------------------------------
; Retuns the state of the indicated item in the CheckListBox control.
; Parameter:
; $iPID: process ID (PID)
; $hWnd: the handle of the CheckListBox control
; $iIndex: index of the item in the list (0 based)
;------------------------------------------------------------------------------
Func CtrlListBox_GetState($iPID, $hWnd, $iIndex)
Local $hProc ; Handle of the process.
Local $pItem ; Pointer to the item.
Local $pData = DllStructCreate("byte") ; Data structure.
Local $iQty ; Size of data read.
Local Const $LB_STATE_SHIFT = 8 ; State position in the memory.
$hProc = _WinAPI_OpenProcess(0x1F0FFF, False, $iPID) ; 0x1F0FFF = PROCESS_ALL_ACCESS
$pItem = _GUICtrlListBox_GetItemData($hWnd, $iIndex) + $LB_STATE_SHIFT
_WinAPI_ReadProcessMemory($hProc, $pItem, DllStructGetPtr($pData), DllStructGetSize($pData), $iQty)
Return DllStructGetData($pData, 1)
EndFunc
;------------------------------------------------------------------------------
; Retuns the state of the indicated item in the CheckListBox control.
; Parameter:
; $iPID: process ID (PID)
; $hWnd: the handle of the CheckListBox control
; $iIndex: index of the item in the list (0 based)
; $bState: state deseired (true or false)
;------------------------------------------------------------------------------
Func CtrlListBox_SetState($iPID, $hWnd, $iIndex, $bState)
Local $hProc ; Handle of the process.
Local $pItem ; Pointer to the item.
Local $pData = DllStructCreate("byte") ; Data structure.
Local $iQty ; Size of data read.
Local Const $LB_STATE_SHIFT = 8 ; State position in the memory.
if($bState <> 0) Then
DllStructSetData($pData, 1, True)
Else
DllStructSetData($pData, 1, False)
EndIf
$hProc = _WinAPI_OpenProcess(0x1F0FFF, False, $iPID) ; 0x1F0FFF = PROCESS_ALL_ACCESS
$pItem = _GUICtrlListBox_GetItemData($hWnd, $iIndex) + $LB_STATE_SHIFT
_WinAPI_WriteProcessMemory($hProc, $pItem, DllStructGetPtr($pData), DllStructGetSize($pData), $iQty)
Return DllStructGetData($pData, 1)
EndFunc