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

如何在Qt(C++)中获取其他应用活动窗口的选中文本?

获取其他程序活动窗口选中文本的跨平台方案(Qt)

针对你的需求,我来补充Windows下的完整实现,同时提供更优雅的替代方案,避免依赖剪贴板操作:

方案一:完善SendInput模拟Ctrl+C的实现

你之前的代码只处理了按键按下,缺少释放步骤,而且Sleep的时机也需要调整,完整的实现应该是这样的:

#include <windows.h>
#include <thread>
#include <chrono>

void simulateCtrlC() {
    INPUT inputs[4] = {0};
    // 按下Ctrl键
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = VK_CONTROL;
    inputs[0].ki.dwFlags = 0;

    // 按下C键
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = 'C';
    inputs[1].ki.dwFlags = 0;

    // 释放C键
    inputs[2].type = INPUT_KEYBOARD;
    inputs[2].ki.wVk = 'C';
    inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;

    // 释放Ctrl键
    inputs[3].type = INPUT_KEYBOARD;
    inputs[3].ki.wVk = VK_CONTROL;
    inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;

    // 发送所有输入事件
    SendInput(4, inputs, sizeof(INPUT));

    // 等待系统处理剪贴板更新,用std::chrono代替Sleep更现代
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
}

// 在Qt中调用获取剪贴板内容
QString getSelectedTextWindows() {
    simulateCtrlC();
    QClipboard* clipboard = QApplication::clipboard();
    return clipboard->text();
}

注意事项:

  • 必须确保目标窗口是活动窗口,否则Ctrl+C会发送到当前Qt窗口,你可以先用SetForegroundWindow切换到目标窗口(需要获取对应窗口句柄)。
  • 这种方法会覆盖用户剪贴板的原有内容,体验不太友好,适合对剪贴板内容不敏感的场景。

方案二:使用Windows UI Automation API(更优雅)

如果不想干扰剪贴板,可以用Windows的UI Automation框架直接获取目标窗口的选中文本,不需要模拟按键:

#include <windows.h>
#include <uiautomation.h>
#include <QString>

#pragma comment(lib, "uiautomation.lib")

QString getSelectedTextViaUIA() {
    IUIAutomation* pAutomation = nullptr;
    IUIAutomationElement* pForegroundElement = nullptr;
    IUIAutomationTextPattern* pTextPattern = nullptr;
    QString selectedText;

    // 初始化UI Automation
    if (SUCCEEDED(CoInitialize(nullptr)) && SUCCEEDED(CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER, IID_IUIAutomation, (void**)&pAutomation))) {
        // 获取前台窗口元素
        if (SUCCEEDED(pAutomation->GetFocusedElement(&pForegroundElement))) {
            // 获取文本模式
            if (SUCCEEDED(pForegroundElement->GetCurrentPattern(UIA_TextPatternId, (IUnknown**)&pTextPattern))) {
                IUIAutomationTextRangeArray* pSelectionRanges = nullptr;
                if (SUCCEEDED(pTextPattern->GetSelection(&pSelectionRanges))) {
                    int count = 0;
                    pSelectionRanges->get_Length(&count);
                    if (count > 0) {
                        IUIAutomationTextRange* pRange = nullptr;
                        if (SUCCEEDED(pSelectionRanges->GetElement(0, &pRange))) {
                            BSTR bstrText = nullptr;
                            if (SUCCEEDED(pRange->GetText(-1, &bstrText))) {
                                selectedText = QString::fromWCharArray(bstrText);
                                SysFreeString(bstrText);
                            }
                            pRange->Release();
                        }
                    }
                    pSelectionRanges->Release();
                }
                pTextPattern->Release();
            }
            pForegroundElement->Release();
        }
        pAutomation->Release();
        CoUninitialize();
    }

    return selectedText;
}

这个方法的优势:

  • 不会修改用户剪贴板内容,体验更好。
  • 直接获取选中文本,不需要依赖窗口切换和按键模拟。

跨平台封装

在Qt中你可以用预处理指令区分平台,统一接口:

#include <QString>
#include <QClipboard>
#include <QApplication>

QString getSelectedText() {
#ifdef Q_OS_LINUX
    // Linux下用Selection模式
    QClipboard* clipboard = QApplication::clipboard();
    return clipboard->text(QClipboard::Selection);
#elif defined(Q_OS_WIN)
    // Windows下选择上面的一种方案
    return getSelectedTextViaUIA(); // 或者getSelectedTextWindows()
#else
    return QString();
#endif
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:44:31