如何通过Win32 API获取第三方应用ListBox控件的多行列表项内容
读取第三方应用多行ListBox完整内容问题
我目前正在尝试读取第三方应用的ListBox控件中的列表项内容,寻找解决方案已有一周仍无进展。
问题更新
目前无法获取ListBox红框标注的完整详细信息,使用LB_GETTEXT消息仅能读取到每个列表项的第一行内容,需要获取多行ListBox项的全部行内容。
现有实现代码
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr Sub windows_API_Test() Const LB_GETCOUNT = &H18B Const LB_GETTOPINDEX = &H18E Const LB_GETTEXTLEN = &H18A Const LB_GETTEXT = &H189 Do DoEvents Main_window = FindWindow(vbNullString, "Select passes to be exported") Listbox_window = FindWindowEx(Main_window, 0&, "Listbox", vbNullString) Loop Until Listbox_window > 0 numberofindex = SendMessage(Listbox_window, LB_GETCOUNT, 0, ByVal 0&) TopIndex = SendMessage(Listbox_window, LB_GETTOPINDEX, 0, 0) For i = TopIndex To numberofindex - 1 textcount = SendMessage(Listbox_window, LB_GETTEXTLEN, i, 0) 'space for null terminating string '\0' will be automatically added by VB buffer$ = Space$(textcount) ' pass string byval not byref ' also make sure that lParam of SendMessage is declared as ANY Call SendMessage(Listbox_window, LB_GETTEXT, i, ByVal buffer$) Debug.Print buffer$ Next i End Sub
参考信息
- Spy++获取的控件信息
- 第三方应用的ListBox界面
- 红圈标注的待获取详细信息位置
解决思路
出现LB_GETTEXT仅能读取第一行的核心原因是目标ListBox为自绘(Owner-drawn)控件,控件默认存储区仅保存第一行文本,剩余多行内容是程序运行时从内部数据源读取后动态绘制到界面上,不会通过标准ListBox消息暴露。
方案1:读取目标进程内存获取完整数据
自绘ListBox的每个Item一般会绑定自定义数据指针,可通过以下步骤获取:
- 调用
SendMessage发送LB_GETITEMDATA消息,获取对应Item的自定义数据指针 - 调用
OpenProcess打开目标进程,获取内存读取权限 - 调用
ReadProcessMemory读取指针指向的内存区域,逆向分析出该程序自定义结构体的字段布局,即可提取完整多行内容
方案2:使用UI自动化接口读取
Windows自带的UI Automation框架原生支持跨进程读取UI内容,适配绝大多数控件:
- VBA中引用
UIAutomationClient库,定位到目标ListBox控件 - 遍历所有Item节点,调用
GetCurrentPropertyValue方法获取对应Item的完整文本属性,只要目标程序做了无障碍适配即可直接拿到全部内容 - 若无障碍适配缺失,可改用截图+OCR方案:定位每个Item的坐标范围,截图后调用本地OCR工具(如Tesseract)识别多行内容,该方案兼容性最强,无需逆向分析
方案3:注入Hook获取绘制内容
若以上方案均不生效,可向目标进程注入DLL,Hook ListBox的DrawItem方法或窗口过程,在控件触发绘制逻辑时直接拦截拿到要渲染的全部文本内容,该方案难度最高但适配性最好。
内容的提问来源于stack exchange,提问作者Vegard Leithe
相关产品推荐
相关产品推荐

