Visual Basic 6 ListView 的自动化支持

2024-03-18

I need to get value/text of control via automation interface (coding with C++/C#). I tried with UI Automation API https://msdn.microsoft.com/en-us/library/ms747327(v=vs.110).aspx and this is some result captured by the Inspect https://msdn.microsoft.com/en-us/library/windows/desktop/dd318521(v=vs.85).aspx: Inspect Listview

Inspect slider UI Automation recognize these control as pane and I can't get list view text item or get/set slider value as normal.
Tried with other tool like MSAA https://msdn.microsoft.com/en-us/library/windows/desktop/dd373592(v=vs.85).aspx, Automation Spy http://www.automationspy.com/ give the same result.

After researching, I found that control with class name like ListView20WndClass, Slider20WndClass, ... belong to Visual Basic 6 control.
So, Is there any API can support these type of control as well?

Remark 1: There is a tool named Ranorex http://www.ranorex.com/ can support these control (sadly, it is €3490 commercial license), and I don't know which underlying API was used:
enter image description here


Remark 2在测试的应用程序中使用了一些其他控件类型,UI 自动化仍然可以获得价值:

  • 雷霆RT6FormDC: 识别为窗口
  • ThunderRT6命令按钮:识别为按钮
  • ThunderRT6复选框: 识别为复选框
  • etc...
  • 可悲的是,他们嵌入ListView20Wnd类 and Slider20Wnd类但两者都识别为窗格


Update 1我创建了一个简单的程序来获取文本,但仍然无法正常工作(编译为 Unicode 字符集):

#include <iostream>
using namespace std;

#include <UIAutomation.h>
#include <atlstr.h>
#include <Commctrl.h>

CString getListViewItemText(HWND hwnd, int nItem, int nSubItem) {
    LVITEM item;
    memset(&item, 0, sizeof(LVITEM));
    item.iSubItem = nSubItem;
    CString string;
    int Length = 64; //initial reasonable string length
    int ReturnCode;

    do {
        Length *= 2; //resize the string buffer
        item.cchTextMax = Length;
        item.pszText = string.GetBufferSetLength(Length);

        ReturnCode = (int)::SendMessage(hwnd, LVM_GETITEMTEXT,
            (WPARAM)nItem, (LPARAM)&item);
        printf("len = %d \n", ReturnCode);

    } while (ReturnCode == Length - 1); //if could not get all chars, try again

    string.ReleaseBuffer();
    return string;
}

void UI_Spy() {

    // Init COM
    CoInitialize(NULL);

    // Init UIAutomation instance
    IUIAutomation *pAuto;
    CoCreateInstance(CLSID_CUIAutomation, NULL,
        CLSCTX_INPROC_SERVER, IID_IUIAutomation, reinterpret_cast<void**>(&pAuto));

    if (pAuto) {

        IUIAutomationElement *pElm;
        POINT p;

        for (int i = 0; i < 10; i++) {
            for (int j = 5; j > 0; j--) {
                Sleep(1000);
                printf("%d ", j);
            }
            GetCursorPos(&p);
            if (pAuto->ElementFromPoint(p, &pElm) == S_OK) {
                wprintf(L"\nPOSITION x = %d, y = %d\n", p.x, p.y);

                BSTR str;
                pElm->get_CurrentName(&str);
                wprintf(L"-Name = %s\n", str);
                SysFreeString(str);

                pElm->get_CurrentLocalizedControlType(&str);
                wprintf(L"-Type = %s\n", str);
                SysFreeString(str);

                CONTROLTYPEID typeId;
                pElm->get_CurrentControlType(&typeId);

                switch (typeId) {

                    // Process checkbox
                case UIA_CheckBoxControlTypeId:
                    IUIAutomationTogglePattern  *toggle;
                    pElm->GetCurrentPattern(UIA_TogglePatternId, (IUnknown**)&toggle);
                    ToggleState state;
                    toggle->get_CurrentToggleState(&state);
                    printf("-Checkbox = %s\n", state == ToggleState::ToggleState_On ? "TRUE"
                        : (state == ToggleState::ToggleState_Off ? "FALSE" : "INTER"));
                    break;

                    // Process VB6 listview
                case UIA_PaneControlTypeId:
                    pElm->get_CurrentClassName(&str);
                    if (str != nullptr && wcscmp(str, L"ListView20WndClass") == 0) {
                        HWND hwnd;
                        pElm->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
                        printf("-VB6 Listview: %p\n", hwnd);

                        CString txt = getListViewItemText(hwnd, 0, 0);
                        //txt = "Test";
                        printf("-[0,0] = %S\n", (const wchar_t*)txt);
                    }
                    SysFreeString(str);
                    break;

                    // Process normal listview
                case UIA_ListControlTypeId:
                    HWND hwnd;
                    pElm->get_CurrentNativeWindowHandle((UIA_HWND*)&hwnd);
                    printf("-Normal Listview: %p\n", hwnd);

                    CString txt = getListViewItemText(hwnd, 0, 0);
                    //txt = "Test";
                    printf("-[0,0] = %S\n", (const wchar_t*)txt);
                    break;
                }

                wprintf(L"\n");
                pElm->Release();
            }
            printf("\n");
        }

        // Release UIAutomation instance
        pAuto->Release();
    }

    // Release COM
    CoUninitialize();
}

int main()
{
    UI_Spy();

    cin.get();
    return 0;
}


当计数到 5..4..3..2..1 时,只需将鼠标悬停在屏幕上的某个元素上即可进行检查。
但是当我将鼠标悬停在列表视图上时:

  • VB6列表视图(ListView20WndClass):它返回一个空字符串(预期是101以我为例)
  • MFC/Winform列表视图(SysListView32):鼠标下的应用程序停止工作(控制台应用程序仍在运行)

您可以使用pywinauto http://pywinauto.github.io/它可以在底层使用 Win32 API 自动化 VB6 应用程序(所有细节都被隐藏,包括LVM_GETITEM消息等)。大多数控件都可以被识别为按钮、复选框甚至列表视图!看支持的类名 https://github.com/pywinauto/pywinauto/blob/master/pywinauto/controls/common_controls.py#L666对于列表视图。您的案例都在这里。

如果使用的话,Win32 API 应该比 UI 自动化运行得更快灵活的等待 https://pywinauto.readthedocs.io/en/latest/wait_long_operations.html。尽管 UI 自动化也受底层支持(如果有的话)。

The 入门指南 https://pywinauto.readthedocs.io/en/latest/getting_started.html将帮助您迈出第一步并学习高级概念。也可以用标签随意提问pywinauto。我是图书馆的维护者。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Visual Basic 6 ListView 的自动化支持 的相关文章

  • Watir 更改 Mozilla Firefox 首选项

    我正在使用 Watir 运行 Ruby 脚本来自动执行一些操作 我正在尝试自动将一些文件保存到某个目录 因此 在我的 Mozilla 设置中 我将默认下载目录设置为桌面并选择自动保存文件 然而 当我开始运行脚本时 这些更改并未反映出来 似乎
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 如何在 C# / .NET 中创建内存泄漏[重复]

    这个问题在这里已经有答案了 可能的重复 托管代码中是否可能存在内存泄漏 特别是 C 3 0 https stackoverflow com questions 6436620 is it possible to have a memory
  • EF Core 通过完全替换断开集合导航属性的更新

    使用 EF Core 5 0 我有一个 SPA 页面 可以加载Group实体及其集合Employee来自 API 的实体 var groupToUpdate await context Groups Include g gt g Emplo
  • 根据 N 个值中最小的一个返回不同的结果

    不确定如何使标题更具描述性 所以我只是从一个例子开始 我使用下面的代码位 它从枚举中选择一个方向 具体取决于四个轴中哪一个与给定方向相比形成最小角度 static Direction VectorToDirection Vector2 di
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • 为什么这个没有特殊字符的正则表达式会匹配更长的字符串?

    我正在使用此方法来尝试查找匹配项 例如 Regex Match A2 TS OIL TS OIL RegexOptions IgnoreCase Success 我得到了真实的结果 我很困惑 我认为这应该返回 false 因为模式中没有特殊
  • 时间:2019-03-17 标签:c#ThreadSafeDeepCopy

    我一直在阅读很多其他问题以及大量谷歌搜索 但我一直无法找到明确的解决方案 根据我读过的一些最佳实践 类的静态方法应该创建线程安全的 并且实例成员应该将线程安全留给消费者 我想为该类实现深度复制方法 该类本身还有其他引用类型成员 有没有什么方
  • 如何在 QTabWidget Qt 中展开选项卡

    我有一个QTabWidget像这个 但我想展开选项卡以 填充 整个小部件宽度 如下所示 我怎样才能做到这一点 我在用Qt 5 3 2 and Qt 创建者 3 2 1 Update 我尝试使用setExpanding功能 ui gt myT
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 从 WebBrowser 控件 C# 获取滚动值

    我试图在 WebBrowser 控件中获取网页的 Y 滚动索引 但无法访问内置滚动条的值 有任何想法吗 对于标准模式下的 IE 使用文档类型 正如你所说 scrollTop是的财产元素 而不是 HtmlDocument htmlDoc th
  • C# 构建一个 webservice 方法,它接受 POST 方法,如 HttpWebRequest 方法

    我需要一个接受 POST 方法的 Web 服务 访问我的服务器正在使用 POST 方法 它向我发送了一个 xml 我应该用一些 xml 进行响应 另一方面 当我访问他时 我已经使用 HttpWebRequest 类进行了管理 并且工作正常
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 跨多个域的 ASP.NET 会话

    是否有合适的 NET 解决方案来在多个域上提供持久服务器会话 即 如果该网站的用户在 www site1 com 下登录 他们也将在 www site2 com 下登录 安全是我们正在开发的程序的一个问题 Thanks 它是否需要在会话中
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • xsi:type 属性搞乱了 C# XML 反序列化

    我使用 XSD exe 根据 XML 架构 xsd 文件 自动生成 C 对象 我正在反序列化 OpenCover 输出 但其中一个部分类未正确生成 这是导致异常的行
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐