QT/C++应用调用Windows原生屏幕键盘失败求助
解决Qt/C++唤起Windows原生屏幕键盘的问题
我之前也踩过类似的坑,尤其是32位程序在64位Windows上调用osk.exe的情况,先给你几个能跑通的方案,再拆解你之前代码的问题~
核心问题:文件系统重定向
你的Attempt 5提示找不到文件,大概率是32位程序的文件系统重定向搞的鬼。64位Windows里,32位程序访问C:\Windows\System32时,会被系统自动重定向到C:\Windows\SysWOW64,而真正的osk.exe在64位系统的System32目录下,SysWOW64里没有这个文件,所以才会提示找不到。
方案1:关闭重定向后调用(Windows API方式)
用Windows原生API临时关闭重定向,调用完键盘再恢复,完美适配32/64位系统:
#include <windows.h> void MainWindow::showOnScreenKeyboard() { PVOID oldValue = nullptr; // 关闭32位程序的文件系统重定向 if (Wow64DisableWow64FsRedirection(&oldValue)) { ShellExecuteW(nullptr, L"open", L"C:\\Windows\\System32\\osk.exe", nullptr, nullptr, SW_SHOWNORMAL); // 调用完成后恢复重定向 Wow64RevertWow64FsRedirection(oldValue); } else { // 如果是32位系统,直接调用即可 ShellExecuteW(nullptr, L"open", L"C:\\Windows\\System32\\osk.exe", nullptr, nullptr, SW_SHOWNORMAL); } }
方案2:用Qt的QProcess调用(更贴合Qt风格)
同样处理重定向问题,也可以用系统环境变量获取正确路径,避免硬编码:
#include <QProcess> #include <QEnvironmentVariable> void MainWindow::showOnScreenKeyboard() { QString oskPath = QEnvironmentVariable::value("WINDIR") + "\\System32\\osk.exe"; QProcess *process = new QProcess(this); // 针对32位程序处理重定向 #if defined(_WIN32) && !defined(_WIN64) PVOID oldValue = nullptr; if (Wow64DisableWow64FsRedirection(&oldValue)) { process->start(oskPath); Wow64RevertWow64FsRedirection(oldValue); } else { process->start(oskPath); } #else // 64位程序直接调用 process->start(oskPath); #endif // 进程结束后自动释放内存 connect(process, &QProcess::finished, process, &QObject::deleteLater); }
实现输入框获焦自动唤起键盘
接下来要实现输入框(比如QLineEdit、QTextEdit)获焦时自动弹出键盘,用事件过滤器是最方便的方式:
- 在
MainWindow构造函数里给需要的输入框安装过滤器:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 给目标输入框安装事件过滤器 ui->lineEdit->installEventFilter(this); ui->textEdit->installEventFilter(this); }
- 重写
eventFilter函数,监听焦点进入事件:
bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusIn) { // 判断当前控件是输入框时,唤起键盘 if (qobject_cast<QLineEdit*>(obj) || qobject_cast<QTextEdit*>(obj)) { showOnScreenKeyboard(); } } // 把事件传递给父类处理 return QMainWindow::eventFilter(obj, event); }
你之前代码的问题拆解
- Attempt 1:没处理32位程序的重定向问题,导致64位系统下找不到文件
- Attempt 2:用了相对路径
./osk.exe,系统键盘根本不在当前程序目录里 - Attempt 3:
QDir::homepath拼写错误(应该是QDir::homePath()),而且tabtip.exe是平板触摸键盘,和osk.exe不是同一个程序 - Attempt 4:
QProcess::execute("start ...")需要指定cmd.exe /c来执行cmd命令,同样存在重定向问题 - Attempt 5:
system()调用同样因为重定向,32位程序下cmd会去SysWOW64找osk.exe,自然找不到
如果是Qt Creator编译,注意一下项目的构建架构(32位/64位),64位程序可以省略重定向的处理步骤~
内容的提问来源于stack exchange,提问作者Kristina Gauthier
相关产品推荐
相关产品推荐

