[有偿] 小白, Windows UI Automation TextPattern 检测问题求助 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ck125s
V2EX    C++

[有偿] 小白, Windows UI Automation TextPattern 检测问题求助

  •  
  •   ck125s 102 天前 1813 次点击
    这是一个创建于 102 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位 V 友,最近在用 UI Automation (UIA) 时遇到了一个很奇怪的问题,卡了好几天了。

    若方法有效感谢200RMB

    目标: 获取记事本( Notepad )编辑框的 TextPattern 。

    现象:

    我用 Accessibility Insightsfor Windows 去看,明明确确显示记事本的编辑框是支持 TextPattern 的。

    Accessibility Insights for windows

    问题:

    我自己的代码,无论用哪种方式,都检测不到 TextPattern 。

    我试过的两种方法:

    C++ 原生 COM 接口:

    通过 GetFocusedElement 拿到元素,然后 GetCurrentPattern(TextPattern.Pattern),结果是拿不到。

    C# + Axe.Windows (Accessibility Insights 核心库):

    我以为是我的姿势不对,[找到源码]( GitHub - microsoft/accessibility-insights-windows: Accessibility Insights for Windows),引用 Axe.Windows 库,完全模拟 AI 的工作流程,调用 PopulateAllPropertiesWithLiveData() 等方法,结果依然检测不到 TextPattern 。

    已排除的常规问题:

    UIAccess 权限、COM 线程模型( STA )、元素句柄有效性等都检查过了,没问题。其他 Pattern 比如 ValuePattern 是可以正常获取的。

    核心疑问:

    Accessibility Insights 到底用了什么魔法? 为什么它能看到 TextPattern ,而我直接调用 UIA API 或者用它的核心库都复现不了?是不是需要什么特殊的初始化步骤,或者 Windows 对记事本这个“亲儿子”有什么特殊的处理? 有大佬了解其中机制吗?或者有其他调试思路也行。


    如果能提供解决方案或关键思路,可有偿指导,感谢!

    微信:Delightpl

    10 条回复    2025-09-04 21:19:32 +08:00
    dandycheung
        1
    dandycheung  
       102 天前 via Android
    看你这过程,不像是小白啊。你要是能把你说的那个软件自己编译成功,逐步调试的话,会不会好点?还有就是有没可能是人家的 manifest 里向系统申请了什么权限之类的,而你自己的落下了?好久不玩 Windows 编程了, 纯属瞎蒙啊。主要是拒绝 0 回复……
    dereklu4
        2
    dereklu4  
       102 天前
    请问是要这种效果吗
    ![image]( https://imgur.com/a/sP1z8VF)
    dereklu4
        3
    dereklu4  
       102 天前
    ck125s
        4
    ck125s  
    OP
       102 天前
    @dereklu4 是的,方便加你微信咨询吗
    ck125s
        5
    ck125s  
    OP
       102 天前
    @dandycheung 好的 谢谢老哥
    dereklu4
        6
    dereklu4  
       102 天前
    penzi
        7
    penzi  
       102 天前


    让 AI 写的,好像一次过

    ```
    #include <iostream>
    #include <windows.h>
    #include <comdef.h>
    #include <UIAutomation.h>
    #include <atlbase.h>
    #include <thread>
    #include <chrono>

    #pragma comment(lib, "ole32.lib")
    #pragma comment(lib, "oleaut32.lib")

    HWND cOnsoleWindow= nullptr;
    std::wstring lastSelectedText;

    HRESULT GetTextFromActiveWindow(IUIAutomation* automation, std::wstring& selectedText) {
    HWND foregroundWindow = GetForegroundWindow();
    if (!foregroundWindow || foregroundWindow == consoleWindow) {
    return E_FAIL;
    }

    CComPtr<IUIAutomationElement> windowElement;
    HRESULT hr = automation->ElementFromHandle(foregroundWindow, &windowElement);
    if (FAILED(hr) || !windowElement) {
    return hr;
    }

    CComPtr<IUIAutomationTextPattern> textPattern;
    hr = windowElement->GetCurrentPatternAs(UIA_TextPatternId, IID_PPV_ARGS(&textPattern));
    if (FAILED(hr) || !textPattern) {
    CComPtr<IUIAutomationElement> focusedElement;
    hr = automation->GetFocusedElement(&focusedElement);
    if (FAILED(hr) || !focusedElement) {
    return hr;
    }
    hr = focusedElement->GetCurrentPatternAs(UIA_TextPatternId, IID_PPV_ARGS(&textPattern));
    if (FAILED(hr) || !textPattern) {
    return hr;
    }
    }

    CComPtr<IUIAutomationTextRangeArray> textRangeArray;
    hr = textPattern->GetSelection(&textRangeArray);
    if (FAILED(hr) || !textRangeArray) {
    return hr;
    }

    int length = 0;
    hr = textRangeArray->get_Length(&length);
    if (FAILED(hr) || length == 0) {
    return hr;
    }

    selectedText.clear();
    for (int i = 0; i < length; i++) {
    CComPtr<IUIAutomationTextRange> textRange;
    hr = textRangeArray->GetElement(i, &textRange);
    if (SUCCEEDED(hr) && textRange) {
    BSTR text = nullptr;
    hr = textRange->GetText(-1, &text);
    if (SUCCEEDED(hr) && text) {
    selectedText += text;
    SysFreeString(text);
    }
    }
    }
    return S_OK;
    }

    void MonitorSelectedText(IUIAutomation* automation) {
    while (true) {
    std::wstring currentSelectedText;
    HRESULT hr = GetTextFromActiveWindow(automation, currentSelectedText);

    if (SUCCEEDED(hr) && !currentSelectedText.empty() && currentSelectedText != lastSelectedText) {
    lastSelectedText = currentSelectedText;

    HWND foregroundWindow = GetForegroundWindow();
    wchar_t windowTitle[256];
    GetWindowTextW(foregroundWindow, windowTitle, 256);

    std::wcout << L"\n=== 检测到新的选中文本 ===" << std::endl;
    std::wcout << L"窗口: " << windowTitle << std::endl;
    std::wcout << L"选中内容: " << currentSelectedText << std::endl;
    std::wcout << L"========================\n" << std::endl;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
    }

    int main() {
    CoInitializeEx(NULL, COINIT_MULTITHREADED);

    cOnsoleWindow= GetConsoleWindow();

    CComPtr<IUIAutomation> automation;
    HRESULT hr = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&automation));

    if (FAILED(hr)) {
    std::wcout << L"无法创建 UI Automation 对象" << std::endl;
    CoUninitialize();
    return -1;
    }

    std::wcout << L"文本选择监控程序已启动..." << std::endl;
    std::wcout << L"程序将在后台监控其他窗口中的文本选择" << std::endl;
    std::wcout << L"按 Ctrl+C 退出程序\n" << std::endl;

    std::thread monitorThread(MonitorSelectedText, automation.p);
    monitorThread.detach();

    std::wcin.get();

    CoUninitialize();
    return 0;
    }

    ```
    spritecn
        8
    spritecn  
       102 天前
    太久不折腾 win 编辑了,记忆中 ahk/au3 带的工具不错
    iorilu
        9
    iorilu  
       101 天前
    这个框架能捕获微信内容, 做到自动化操作微信码
    ck125s
        10
    ck125s  
    OP
       101 天前
    已解决,感谢大家。

    结论是这样的,希望能帮助有需要的人:

    Interop.UIAutomation 或 C++ COM UIA 的原生方式,无法让传统 Win32 Edit 控件支持 TextPattern ,因为底层的 MSAA/IAccessible 本身并不提供足够的文本访问接口,UIA 也不会自动合成该模式。只有 System.Windows.Automation 这种托管客户端,在其背后的 UIAutomationClientsideProviders.dll 中,才能通过与 MSAA 进行通信,将 Edit 控件“模拟”成支持 TextPattern 的 Document 类型。这个过程本质上是依赖客户端增强( Proxy ),而并非 Edit 控件原生能力。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3152 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 11:33 PVG 19:33 LAX 03:33 JFK 06:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86