Reputation: 103
I'm trying to get selected text from active window of another app in my Qt application.
On Linux I just use QClipboard
in Selection
mode.
On Windows I'm trying to send Ctrl + C to system:
INPUT copyText;
copyText.type = INPUT_KEYBOARD;
copyText.ki.wScan = 0;
copyText.ki.time = 0;
copyText.ki.dwExtraInfo = 0;
Sleep(200);
// Press the "Ctrl" key
copyText.ki.wVk = VK_CONTROL;
copyText.ki.dwFlags = 0; // 0 for key press
SendInput(1, ©Text, sizeof(INPUT));
// Press the "C" key
copyText.ki.wVk = 'C';
copyText.ki.dwFlags = 0; // 0 for key press
SendInput(1, ©Text, sizeof(INPUT));
Sleep(50);
// Release the "C" key
copyText.ki.wVk = 'C';
copyText.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, ©Text, sizeof(INPUT));
// Release the "Ctrl" key
copyText.ki.wVk = VK_CONTROL;
copyText.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, ©Text, sizeof(INPUT));
Sleep(50);
But this hack doesn't work properly - sometimes I don't get selection. I think it can be caused by a hot key that calls function with this code and some keys are still pressed while this code is running. How can I check if every key isn't pressed from QKeySequenceEdit? Or how can I check if no one key pressed? Or is there an easier way to get the selected text from the active window on Windows?
Upvotes: 1
Views: 1474
Reputation: 103
My solution to get selected text:
QString MainWindow::selectedText()
{
QString selectedText;
#if defined(Q_OS_LINUX)
selectedText = QApplication::clipboard()->text(QClipboard::Selection);
#elif defined(Q_OS_WIN) // Send Ctrl + C to get selected text
// Save original clipboard data
QVariant originalClipboard;
if (QApplication::clipboard()->mimeData()->hasImage())
originalClipboard = QApplication::clipboard()->image();
else
originalClipboard = QApplication::clipboard()->text();
// Wait until the hot key is pressed
while (GetAsyncKeyState(translateSelectedHotkey->currentNativeShortcut().key) || GetAsyncKeyState(VK_CONTROL)
|| GetAsyncKeyState(VK_MENU) || GetAsyncKeyState(VK_SHIFT))
Sleep(50);
// Generate key sequence
INPUT copyText[4];
// Set the press of the "Ctrl" key
copyText[0].ki.wVk = VK_CONTROL;
copyText[0].ki.dwFlags = 0; // 0 for key press
copyText[0].type = INPUT_KEYBOARD;
// Set the press of the "C" key
copyText[1].ki.wVk = 'C';
copyText[1].ki.dwFlags = 0;
copyText[1].type = INPUT_KEYBOARD;
// Set the release of the "C" key
copyText[2].ki.wVk = 'C';
copyText[2].ki.dwFlags = KEYEVENTF_KEYUP;
copyText[2].type = INPUT_KEYBOARD;
// Set the release of the "Ctrl" key
copyText[3].ki.wVk = VK_CONTROL;
copyText[3].ki.dwFlags = KEYEVENTF_KEYUP;
copyText[3].type = INPUT_KEYBOARD;
// Send key sequence to system
SendInput(4, copyText, sizeof(INPUT));
// Wait for the clipboard to change
QEventLoop loop;
QTimer timer; // Add a timer for the case where the text is not selected
loop.connect(QApplication::clipboard(), &QClipboard::changed, &loop, &QEventLoop::quit);
loop.connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.start(1000);
loop.exec();
// Translate the text from the clipboard if the selected text was not copied
if (timer.isActive())
return QApplication::clipboard()->text();
else
timer.stop();
// Get clipboard data
selectedText = QApplication::clipboard()->text();
// Return original clipboard
if (originalClipboard.type() == QVariant::Image)
QApplication::clipboard()->setImage(originalClipboard.value<QImage>());
else
QApplication::clipboard()->setText(originalClipboard.toString());
#endif
return selectedText;
}
To set global shortcuts I used QHotkey. From QHotkey I get native keycodes using the currentNativeShortcut().key
method.
Upvotes: 2