如何在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
相关产品推荐
相关产品推荐

