You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinAppDriver扩展支持Win32 MFC自定义UI元素可行性问询

扩展WinAppDriver支持自定义MFC GUI元素的方案

核心思路:基于Windows自动化API(UIA)扩展识别能力

WinAppDriver底层依赖UIA框架,对于MFC自定义控件,核心是让你的自定义网格类被UIA识别并暴露交互能力,有两种可行路径:

路径1:修改MFC源码,添加UIA提供者支持

如果能拿到MFC程序的源码,这是最规范的方案:

  • 为自定义网格类实现UIA的对应模式接口,比如IGridProvider(暴露行列数)、ITableItemProvider(定位单元格)、IValueProvider(读写单元格内容)
  • 继承CUIAutomationProvider基类,实现接口里的方法,把网格的内部数据(行列数、单元格值)通过UIA暴露出来
  • 在网格控件的初始化方法(比如OnCreate)里,调用UiaRegisterProvider将控件和你的UIA提供者绑定

示例代码片段(MFC环境):

// 自定义网格的UIA提供者类
class CMyGridUIAProvider : public CUIAutomationProvider, public IGridProvider, public IValueProvider
{
private:
    CMyGrid* m_pGrid;
public:
    CMyGridUIAProvider(CMyGrid* pGrid) : m_pGrid(pGrid) {}

    // 实现IGridProvider接口,返回行数
    STDMETHODIMP get_RowCount(int* pRetVal) override {
        *pRetVal = m_pGrid->GetRowCount();
        return S_OK;
    }

    // 实现IGridProvider接口,返回列数
    STDMETHODIMP get_ColumnCount(int* pRetVal) override {
        *pRetVal = m_pGrid->GetColumnCount();
        return S_OK;
    }

    // 实现IValueProvider接口,读取单元格值
    STDMETHODIMP get_Value(BSTR* pRetVal) override {
        // 这里需要根据当前单元格位置获取值,可结合ITableItemProvider的定位逻辑
        CString cellValue = m_pGrid->GetCellValue(m_currentRow, m_currentCol);
        *pRetVal = cellValue.AllocSysString();
        return S_OK;
    }

    // 其他接口方法按需实现...
};

// 在网格控件中注册UIA提供者
BOOL CMyGrid::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CStatic::OnCreate(lpCreateStruct) == -1)
        return FALSE;

    CMyGridUIAProvider* pProvider = new CMyGridUIAProvider(this);
    UiaRegisterProvider(reinterpret_cast<IRawElementProviderSimple*>(pProvider));
    return TRUE;
}

完成后,WinAppDriver就能识别网格的UIA模式,你可以通过Appium客户端API直接调用:

  • 获取行列数:driver.findElement(By.xpath("//[contains(@ClassName,'你的网格类名')]")).getAttribute("RowCount")
  • 读写单元格:定位到具体单元格元素后,调用getValue()或setValue()方法

路径2:不修改源码,通过Win32 API直接交互

如果无法修改MFC程序源码,可通过原生Win32 API绕开UIA直接操作控件:

  • 用FindWindowEx找到网格控件的句柄
  • 发送程序内部约定的自定义消息(比如WM_USER + XXX)来获取行列数、读写单元格(需要确认程序是否预留了这类消息接口)
  • 极端情况下,可通过读取控件内存的方式获取数据(风险较高,需了解控件内存结构)

示例Python代码(结合pywin32):

import win32api
import win32gui
import win32con

# 获取主窗口句柄
main_handle = win32gui.FindWindow(None, "你的MFC程序窗口标题")
# 获取网格控件句柄
grid_handle = win32gui.FindWindowEx(main_handle, 0, "你的自定义网格类名", None)

# 发送自定义消息获取行数(假设程序预留了WM_GET_ROWCOUNT消息)
row_count = win32api.SendMessage(grid_handle, win32con.WM_USER + 100, 0, 0)
# 发送自定义消息读取指定单元格内容
cell_value = win32api.SendMessage(grid_handle, win32con.WM_USER + 101, (row, col), 0)

关键验证工具

用Windows SDK自带的Inspect.exe检查UIA提供者是否生效:打开Inspect.exe后定位到网格控件,查看是否能识别到Grid或GridItem模式,以及对应的属性值是否正确。

内容的提问来源于stack exchange,提问作者Sergey Alikin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 11:52:43