使用 SendMessage API 获取 CheckListBox 中项目的状态
Get the state of the items in a CheckListBox using SendMessage API
我正在使用一个软件来操纵另一个软件,例如软件测试环境,objective 获取一些值并执行一些任务。为此,我使用了 SendMessage API,它在几乎所有 Windows 控件中都运行良好,CheckListBox 除外。 "slave" 软件是在 Delphi 中创建的,所以,我不确定 CheckListBox 是否是标准 Windows 控件,无论如何,这是 MS 的文档:
https://docs.microsoft.com/en-us/windows/win32/controls/list-boxes
在这个控件中,我可以获得项目的数量、文本、选择了哪个以及许多其他信息,但我无法知道项目是否被选中。我尝试使用一些工具,如 "Accessibility Insights for Windows" 和 AutoIt,但没有结果。
关于如何获取 Delphi CheckListBox 中的复选框状态的任何想法?
提前致谢。
Delphi 将检查的信息存储在 TCheckListBoxDataWrapper
对象中。指向该对象的指针存储在复选框项的常规 "item data" 中。然后这个对象有一个布尔值 属性 State
,你会在偏移量 8.
处找到它
注意:如果发现您的程序的特定 Delphi 版本的偏移量不同于 8,请尝试附近的值 - 4、12,... - 它可以'没走多远...
要了解某项是否已选中,您需要:
- 获取指向该项目
TCheckListBoxDataWrapper
的指针。这可以通过发送 LB_GETITEMDATA
消息来完成。如果返回零,也算未检查。
- 因为这个指针指向另一个进程中的内存而不是你的,你不能简单地取消引用它。相反,您需要使用
ReadProcessMemory
。知道 State
属性 位于偏移量 8,您可以调用 ReadProcessMemory(hProcess, itemData + 8, &checked, 1, NULL)
将 1 个字节读入变量 checked
。 (您首先需要使用OpenProcess
打开目标进程。)
然后您将在 checked
中看到项目的选中状态! 1
表示选中,0
表示未选中。
如果您以后还需要访问其他一些内部状态,另一个提示:有一个 window 属性 ControlOfsXXXXXXXXYYYYYYYY
,其中 X
是 [= window 所有者(通常是 00400000
)的 24=](基址)和 Y
是 window 所有者的(十六进制)线程 ID(您可以使用 GetWindowThreadProcessId
来获得它)。您可以使用 GetProp
获取 属性 的值,它将是指向控制对象(在本例中为 TCheckListBox
本身)的指针。然后,您可以根据需要使用 ReadProcessMemory
来获取其他数据。你需要知道偏移量(但你可以使用调试器来尝试找出它们)。编译具有相同 Delphi 版本的测试程序并在其中执行访问这些属性的函数非常有帮助,然后您可以调试自己的测试程序并更轻松地找出偏移量。
一种更高级的方法,涉及将自定义 DLL(以相同 Delphi 版本编写)注入目标进程,允许更直接地访问(读取和写入)此类数据。我很久以前就写过an article about that
如@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
我在尝试获取 VB.Net 开发的 UI 的 CheckedListBox 中的复选框状态时遇到了类似的问题。我想获得状态(check/Uncheck),以便我可以在 Python + Winium 中执行我的测试自动化框架开发人员所需的事件。这是特别需要的,以免不小心取消选中已选中的项目。
在研究过程中,我了解到使用 Winium 并不容易,因此我在 UI 上添加了一个按钮,用于在选中所需的复选框之前重置所有复选框。
希望对您有所帮助。
我正在使用一个软件来操纵另一个软件,例如软件测试环境,objective 获取一些值并执行一些任务。为此,我使用了 SendMessage API,它在几乎所有 Windows 控件中都运行良好,CheckListBox 除外。 "slave" 软件是在 Delphi 中创建的,所以,我不确定 CheckListBox 是否是标准 Windows 控件,无论如何,这是 MS 的文档:
https://docs.microsoft.com/en-us/windows/win32/controls/list-boxes
在这个控件中,我可以获得项目的数量、文本、选择了哪个以及许多其他信息,但我无法知道项目是否被选中。我尝试使用一些工具,如 "Accessibility Insights for Windows" 和 AutoIt,但没有结果。
关于如何获取 Delphi CheckListBox 中的复选框状态的任何想法?
提前致谢。
Delphi 将检查的信息存储在 TCheckListBoxDataWrapper
对象中。指向该对象的指针存储在复选框项的常规 "item data" 中。然后这个对象有一个布尔值 属性 State
,你会在偏移量 8.
注意:如果发现您的程序的特定 Delphi 版本的偏移量不同于 8,请尝试附近的值 - 4、12,... - 它可以'没走多远...
要了解某项是否已选中,您需要:
- 获取指向该项目
TCheckListBoxDataWrapper
的指针。这可以通过发送LB_GETITEMDATA
消息来完成。如果返回零,也算未检查。 - 因为这个指针指向另一个进程中的内存而不是你的,你不能简单地取消引用它。相反,您需要使用
ReadProcessMemory
。知道State
属性 位于偏移量 8,您可以调用ReadProcessMemory(hProcess, itemData + 8, &checked, 1, NULL)
将 1 个字节读入变量checked
。 (您首先需要使用OpenProcess
打开目标进程。)
然后您将在 checked
中看到项目的选中状态! 1
表示选中,0
表示未选中。
如果您以后还需要访问其他一些内部状态,另一个提示:有一个 window 属性 ControlOfsXXXXXXXXYYYYYYYY
,其中 X
是 [= window 所有者(通常是 00400000
)的 24=](基址)和 Y
是 window 所有者的(十六进制)线程 ID(您可以使用 GetWindowThreadProcessId
来获得它)。您可以使用 GetProp
获取 属性 的值,它将是指向控制对象(在本例中为 TCheckListBox
本身)的指针。然后,您可以根据需要使用 ReadProcessMemory
来获取其他数据。你需要知道偏移量(但你可以使用调试器来尝试找出它们)。编译具有相同 Delphi 版本的测试程序并在其中执行访问这些属性的函数非常有帮助,然后您可以调试自己的测试程序并更轻松地找出偏移量。
一种更高级的方法,涉及将自定义 DLL(以相同 Delphi 版本编写)注入目标进程,允许更直接地访问(读取和写入)此类数据。我很久以前就写过an article about that
如@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
我在尝试获取 VB.Net 开发的 UI 的 CheckedListBox 中的复选框状态时遇到了类似的问题。我想获得状态(check/Uncheck),以便我可以在 Python + Winium 中执行我的测试自动化框架开发人员所需的事件。这是特别需要的,以免不小心取消选中已选中的项目。
在研究过程中,我了解到使用 Winium 并不容易,因此我在 UI 上添加了一个按钮,用于在选中所需的复选框之前重置所有复选框。
希望对您有所帮助。