我试过谷歌搜索,并在这个网站上搜索这个但无济于事。
我正在使用 Qt 为 Windows 构建一个与剪贴板相关的应用程序,它正常工作的要求之一是能够在我的 Qt 应用程序之外注册键盘事件,例如 ctrl + c、ctrl + v。(复制/粘贴) . 我在网上发现的唯一一件事是使用 Qt 的外部插件,但整个概念没有得到正确解释,所以我走到了死胡同。
有谁知道我该怎么做?同样,我想为我的应用程序注册快捷方式,这些快捷方式将出现在应用程序本身之外。
提前致谢!
正如我所发现的,绑定剪贴板快捷方式和绑定快捷方式通常是两种不同的东西。与剪贴板事件相关,Qt 通过其QClipboard类提供对dataChanged()信号的访问。使用它,您可以知道剪贴板数据何时更改,并采取相应措施,并且应该消除对复制/粘贴快捷方式执行系统范围绑定的需要。
为了注册一个全局快捷方式(在这种情况下需要 ctrl + v),这是平台特定的,就像我的需要一样,可以在 Windows 下使用RegisterHotKey函数。作为第一个参数请求的 HWND 可以从 QWidget 提供的winId函数中获取。
为了接受 WM_HOTKEY 事件,必须在 Qt <= 5.0 和nativeEvent on >= 5.0下实现winEvent虚拟保护功能。
这取决于应用程序运行的桌面环境,并且是特定于操作系统的。如果您打算在 KDE 中运行应用程序,您可以通过在应用程序中部署 .desktop文件或向 /usr/share/kde4/apps/khotkeys 添加内容来轻松注册全局热键。
在 Windows 中,最简单的方法可能是将注册表项添加到注册表中以注册全局热键。见MSDN
我认为您只是对剪贴板的工作方式感到困惑。您永远不需要在应用程序之外注册与剪贴板相关的热键。这些由其他应用程序处理。这些应用程序所做的是与系统范围的剪贴板交互。您的应用程序需要与同一个剪贴板进行交互,并获得有关新剪贴板数据可用等的通知。
如果您告诉我们“剪贴板相关”应用程序的含义,您可能会得到更多有用的答案。它是用来卖木制剪贴板的吗?或者校准剪贴板弹簧?或者管理剪贴板的库存?还是在数字剪贴板上运行?叹。
这应该可以让您在 Windows+Qt 和 HotKeys 中快速启动并运行。
我还没有尝试过使用 QxtGlobalShortcut 的 Qt eXTension 库,但听起来它可能是针对更多平台的更优雅的完整解决方案。(就像@TimMeyer 对您的问题的评论一样)
https://stackoverflow.com/a/3154652/808151
我编写了这个函数来监听 Windows 中的单个系统范围的热键。
#ifndef HOTKEYTHREAD_H
#define HOTKEYTHREAD_H
#include <QThread>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
class HotKeyThread : public QThread
{
Q_OBJECT
public:
HotKeyThread(QObject *parent);
~HotKeyThread();
signals:
void hot_key_event(int);
public slots:
void run();
void stop();
private:
volatile bool m_stopped;
DWORD m_thread_id;
};
#endif // HOTKEYTHREAD_H
.cpp 文件
#include "hotkeythread.h"
#include <QDebug>
#include <process.h>
#define WM_END_THREAD (WM_USER+2)
HotKeyThread::HotKeyThread(QObject *parent)
: QThread(parent)
{
this->m_thread_id = 0;
}
HotKeyThread::~HotKeyThread()
{
}
void HotKeyThread::stop()
{
if(this->m_thread_id != 0)
::PostThreadMessage(this->m_thread_id, WM_END_THREAD, 0, 0);
}
//
void HotKeyThread::run()
{
// store a thread id so we can exit later
m_thread_id = ::GetCurrentThreadId();
qDebug() << "ThreadIDs" << QString::number(m_thread_id, 16) << QString::number((int) this->currentThreadId(), 16);
// register an atom, and a hotkey
BOOL retVal;
int counter = 0;
int magic_num = 1128;
ATOM id = ::GlobalAddAtom(MAKEINTATOM(magic_num + counter++));
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
int modifier = 0x0;// modify this line
int key = VK_NUMPAD0;// modify this line
if(QSysInfo::windowsVersion() > QSysInfo::WV_VISTA)
{
retVal = ::RegisterHotKey(NULL, id, modifier | MOD_NOREPEAT, key);
}
else
{
// No repeat is only supported in 7 and later
retVal = ::RegisterHotKey(NULL, id, modifier, key);
}
if(retVal)
{
qDebug() << "Successfully added a HotKey!";
}
else
{
qDebug() << "Failed to add a hotkey!";
return;
}
// wait on hotkeys
MSG msg = {0};
while (0 < ::GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == WM_HOTKEY)
{
bool control = LOWORD(msg.lParam) & MOD_CONTROL;
bool shift = LOWORD(msg.lParam) & MOD_SHIFT;
bool alt = LOWORD(msg.lParam) & MOD_ALT;
bool win = LOWORD(msg.lParam) & MOD_WIN;
qDebug() << "HotKey!" << (control ? "Ctrl +": "")
<< (alt ? "Alt +": "")
<< (shift ? "Shift +":"")
<< (win ? "Win +":"") << QString::number(HIWORD(msg.lParam),16);
// TODO Notify MainWindow of the event
emit hot_key_event(msg.lParam);
}
else if(msg.message == WM_END_THREAD)
{
// exit
break;
}
}
// Clean up Hotkey
::UnregisterHotKey(NULL, id);
::GlobalDeleteAtom(id);
}
在您的 GUI 中使用
// Start HotKey Thread!
m_hot_key_thread = new HotKeyThread(this);
QObject::connect(m_hot_key_thread, SIGNAL(hot_key_event(int)),
this, SLOT(handle_hot_key_event(int)), Qt::QueuedConnection);
m_hot_key_thread->start();
当你的程序关闭使用
m_hot_key_thread->stop();
希望有帮助。