控制的window8, window8.1,window10系统中的虚拟键盘。通过分析虚拟键盘,发现TabTip.exe就是虚拟键盘服务,所以只要启动这个程序,就实现了键盘的显示。该功能中也实现了通过active插件来控制键盘,但在实际测试中发现,该控制不是很精准。
待改进,通过active插件控制键盘,如果你有好的方法,欢迎拍砖!
头文件 VirtualKeyboard.h:
#ifndef VIRTUALKEYBOARD_H
#define VIRTUALKEYBOARD_H
#include <QAxObject>
class VirtualKeyboard
{
public:
/// Shows on-screen keyboard. Implementation is different for each platform.
/// @warning Currently works only in windows 8,win8.1 win10
static void show();
static void close();
private:
static void showWindowsKeyboard();
static void showTapTip();
static void showByCom();
static bool isVisible(int style);
static bool isOpened();
static bool closeWindowKeyboard();
static QAxObject *kbaxObject();
// static const int GWL_STYLE = -16;
// static const int WM_SYSCOMMAND = 0x0112;
// static const int SC_CLOSE = 0xF060;
// static const int WS_DISABLED = 0x08000000;
// static const int WS_VISIBLE = 0x10000000;
static QAxObject *axObject;
class VkbAxGarbage
{
~VkbAxGarbage() {
if (VirtualKeyboard::axObject != NULL) {
delete VirtualKeyboard::axObject;
}
}
};
static VkbAxGarbage vkbAxGarbage;
};
#endif // VIRTUALKEYBOARD_H
代码实现VirtualKeyboard.cpp
#include "virtualkeyboard.h"
#include <QtCore/QSysInfo>
#include <QtCore/QFileInfo>
#include <QtCore/QUrl>
#include <QDesktopServices>
#include <QMessageBox>
#include <QVariant>
#include <QDebug>
#include <QThread>
#include <QUuid>
#ifdef Q_OS_WIN
#include <qt_windows.h>
struct ITipInvocation //: public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Toggle(HWND hwnd) = 0;
};
#endif
QAxObject *VirtualKeyboard::axObject = NULL;//new QAxObject("{4ce576fa-83dc-4f88-951c-9d0782b4e376}");
void VirtualKeyboard::show()
{
#ifdef Q_OS_WIN
switch (QSysInfo::windowsVersion()) {
case QSysInfo::WV_WINDOWS8:
case QSysInfo::WV_WINDOWS8_1:
case QSysInfo::WV_WINDOWS10:
showWindowsKeyboard();
break;
default:
break;
}
#endif
}
void VirtualKeyboard::close()
{
#ifdef Q_OS_WIN
switch (QSysInfo::windowsVersion()) {
case QSysInfo::WV_WINDOWS8:
case QSysInfo::WV_WINDOWS8_1:
case QSysInfo::WV_WINDOWS10:
closeWindowKeyboard();
break;
default:
break;
}
#endif
}
void VirtualKeyboard::showWindowsKeyboard()
{
//if (isOpened()) {
// return;
//}
// show every time
showTapTip();
//showByCom();
return;
//HWND handle = ::FindWindow("IPTIP_Main_Window", NULL);
//if (handle > 0 && !kbaxObject()->isNull()) {
// LONG style = ::GetWindowLong(handle, GWL_STYLE);
// if (!isVisible(style)) {
// showByCom();
// }
//}
//else {
// showTapTip();
// if (!isOpened()) {
// showByCom();
// }
//}
}
void VirtualKeyboard::showTapTip()
{
static const QString programFilesPath(qgetenv("PROGRAMFILES").replace("\\", "/"));
static const QString tabTipPath = QString("%1/Common Files/microsoft shared/ink/TabTip.exe").arg(programFilesPath);
if (QFileInfo(tabTipPath).exists()) {
QDesktopServices::openUrl(QUrl("file:///" + tabTipPath));
}
else {
const QString windowsDirectoryPath(qgetenv("WINDIR").replace("\\", "/"));
const QString oskPath = QString("%1/system32/osk.exe").arg(windowsDirectoryPath);
if (QFileInfo(oskPath).exists()) {
QDesktopServices::openUrl(QUrl("file:///" + oskPath));
}
}
HWND handle = 0;
while ((handle = ::FindWindow("IPTIP_Main_Window", NULL)) <= 0) {
QThread::msleep(500);
}
}
void VirtualKeyboard::showByCom()
{
ITipInvocation *tipInvocation = NULL;
kbaxObject()->queryInterface(QUuid("37c994e7-432b-4834-a2f7-dce1f13b834b"), (void **)&tipInvocation);
if (NULL != tipInvocation) {
tipInvocation->Toggle(GetDesktopWindow());
}
}
bool VirtualKeyboard::isVisible(int style)
{
if ((style & WS_DISABLED) != 0) {
return false;
}
if ((style & WS_VISIBLE) != 0) {
return true;
}
return false;
}
bool VirtualKeyboard::isOpened()
{
HWND handle = ::FindWindow("IPTIP_Main_Window", NULL);
if (handle <= 0) {
return false;
}
LONG style = ::GetWindowLong(handle, GWL_STYLE);
return isVisible(style);
}
bool VirtualKeyboard::closeWindowKeyboard()
{
HWND handle = ::FindWindow("IPTIP_Main_Window", NULL);
bool active = handle > 0;
if (active)
{
// don't check style - just close
::SendMessage(handle, WM_SYSCOMMAND, SC_CLOSE, 0);
}
return active;
}
QAxObject *VirtualKeyboard::kbaxObject()
{
if (NULL == axObject) {
axObject = new QAxObject();
if (!axObject->setControl("{4CE576FA-83DC-4f88-951C-9D0782B4E376}")) {
QMessageBox::warning(NULL, "keyboard com error", QStringLiteral("虚拟键盘com加载失败"));
}
}
return axObject;
}