1 捕获键盘
(1) 在头文件中声明
typedef struct HOTKEYINFORMATION {
int identification; //标识
unsigned long childevent; //事件子程序
int normalkey; //普通键
int functionkey; //功能键
int otherkey; //其他键
BYTE keystate; //键状态
bool state; //状态
bool directlytrigger;//直接触发
}HKI;
void MonitorHotkeyThreads();
int MonitorTheHotkey(DWORD Event, int keycode, int functionstate = 0, int otherkey = 0, int period = 10, bool directlytrigger = false);
(2) 在cpp中定义
vector<HKI> HotKeyInformation;
void MonitorHotkeyThreads()
{
DWORD TempEvent;
int tempidentification, tempvalue, BYTETemp;
short cachstate[256];
for (int i = 0; i < 255; ++i)
{
cachstate[i] = 251; //防检测
cachstate[i] = GetAsyncKeyState(i);
}
for (vector<HKI>::iterator it = HotKeyInformation.begin(); it != HotKeyInformation.end(); ++it)
{
if (it->identification)
{
BYTETemp = (BYTE)it->normalkey;
BYTETemp = cachstate[BYTETemp];
if (BYTETemp == 0) //无状态
{
if (it->keystate == 1)
{
it->keystate = 2;
}
else
{
it->keystate = 0;
continue; //如果啥键也没有按一直做状态判断循环
}
}
if (BYTETemp < 0) //按下状态
{
if (it->keystate == 0)
{
it->keystate = 1;
}
if (it->normalkey < 0)
{
continue;
}
}
/*监视热键_信息 [i].功能键 = 选择 (缓存键状态 [18] < 0, 1, 0) + 选择 (缓存键状态 [17] < 0, 2, 0) + 选择 (缓存键状态 [16] < 0, 4, 0) + 选择 (缓存键状态 [91] < 0, 8, 0))*/
if (it->keystate > 0 && it->keystate != 88)
{
it->keystate = 88;
tempvalue = (cachstate[18] < 0 ? 1 : 0) + (cachstate[17] < 0 ? 2 : 0) + (cachstate[16] < 0 ? 4 : 0) + (cachstate[91] < 0 ? 8 : 0);
if (tempvalue == it->functionkey)
{
if (it->otherkey != 0)
{
BYTETemp = (BYTE)abs(it->otherkey);
if (cachstate[BYTETemp] >= 0)
{
continue;
}
}
TempEvent = it->childevent;
tempidentification = it->identification;
if (it->directlytrigger)
{
CallWindowProc((WNDPROC)TempEvent, (HWND)tempidentification, 0, 0, 0);
}
else
{
HANDLE handle = (HANDLE)_beginthreadex(nullptr, 0, (_beginthreadex_proc_type)TempEvent, nullptr, 0, nullptr);
CloseHandle(handle);
}
}
}
}
}
}
int MonitorTheHotkey(DWORD Event, int keycode, int functionstate /*= 0*/, int otherkey /*= 0*/, int period /*= 10*/, bool directlytrigger /*= false*/)
{
HKI TempHotKeyInformation;
if ((BYTE)keycode <= 0)
{
return 0;
}
for (vector<HKI>::iterator it = HotKeyInformation.begin(); it != HotKeyInformation.end(); ++it)
{
if (it->normalkey == keycode && it->functionkey == functionstate && it->otherkey == otherkey)
{
it->childevent = Event;
it->directlytrigger = directlytrigger;
if (it->identification != 0)
{
return it->identification;
}
it->identification = (it - HotKeyInformation.begin()) + 1000001;
return it->identification;
}
}
TempHotKeyInformation.childevent = Event;
TempHotKeyInformation.normalkey = keycode;
TempHotKeyInformation.functionkey = functionstate;
TempHotKeyInformation.otherkey = otherkey;
TempHotKeyInformation.directlytrigger = directlytrigger;
TempHotKeyInformation.identification = HotKeyInformation.size() + 1000001;
HotKeyInformation.push_back(TempHotKeyInformation);//将临时的加入里面
if (TempHotKeyInformation.identification == 1000001)
{
SetTimer(NULL, 661, period, (TIMERPROC)MonitorHotkeyThreads);
}
return TempHotKeyInformation.identification;
}
(3) 在窗口构造函数中加入
MonitorTheHotkey((DWORD)HTK_RUN_Event, VK_HOME); // 捕获HOME热键
2 Qt注册全局热键
(注: 如果用的是静态编绎的Qt库, 则注册的热键无效)
1 添加user32.lib(用Vs时可跳过此步, 用Qt Creator需要在pro中加入)
2 注册全局热键
3 添加nativeEvent函数来接收系统消息
4 扩展, 更改热键
connect(ui.HTKE_RUN, &QKeySequenceEdit::keySequenceChanged, [=](const QKeySequence &keySequence) {
QKeySequence Key_RUN = ui.HTKE_RUN->keySequence();
qDebug() << Key_RUN;
QString str = Key_RUN.toString();
qDebug() << str;
QStringList strLst = str.split('+');
QString str_MOD, str_VK = NULL;
if (strLst[0].compare("Ctrl") == 0)
{
str_MOD = MOD_CONTROL;
str_VK = strLst[1];
}
});
5 扩展,添加热键事件
bool KingHonor::nativeEvent(const QByteArray & eventType, void * message, long * result)
{
if (eventType == "windows_generic_MSG")
{
MSG* pMsg = reinterpret_cast<MSG*>(message);
if (pMsg->message == WM_HOTKEY)
{
if (pMsg->wParam == HTK_RUN)
{
qDebug() << "------------HTK_RUN 被按下-----------";
HTK_RUN_Event();
}
else if (pMsg->wParam == HTK_STOP)
{
qDebug() << "------------HTK_STOP 被按下------------";
HTK_STOP_Event();
}
else if (pMsg->wParam == HTK_END)
{
qDebug() << "------------HTK_END 被按下------------";
HTK_END_Event();
}
}
}
return QWidget::nativeEvent(eventType, message, result);
}
3 pyqt注册全局热键
import win32con
import ctypes
import ctypes.wintypes
from threading import Thread,activeCount, enumerate
from time import sleep,time
class Hotkey(Thread):
user32 = ctypes.windll.user32
hkey_list = {}
hkey_flags = {} #按下
hkey_running = {} #启停
_reg_list = {} #待注册热键信息
def regiskey(self, hwnd=None, flagid=0, fnkey=win32con.MOD_ALT, vkey=win32con.VK_F9): # 注册热键,默认一个alt+F9
return self.user32.RegisterHotKey(hwnd, flagid, fnkey, vkey)
def get_reginfo(self):
return self._reg_list
def get_id(self,func):
self_id = None
for id in self.get_reginfo():
if self.get_reginfo()[id]["func"] == func:
self_id = id
break
if self_id:
self.hkey_running[self_id] = True
return self_id
def get_running_state(self,self_id):
if self.hkey_running.get(self_id):
return self.hkey_running[self_id]
else:
return False
def reg(self,key,func,args=None):
id = int(str(round(time()*10))[-6:])
fnkey = key[0]
vkey = key[1]
info = {
"fnkey":fnkey,
"vkey":vkey,
"func":func,
"args":args
}
self._reg_list[id] = info
# print(info) #这里待注册的信息
sleep(0.1)
return id
def fast_reg(self,id,key = (0,win32con.VK_HOME),func = lambda:print('热键注册开始')):
if not self.regiskey(None, id, key[0], key[1]):
print("热键注册失败")
return None
self.hkey_list[id] = func
self.hkey_flags[id] = False
return id
def callback(self):
def inner(self = self):
for flag in self.hkey_flags:
self.hkey_flags[flag] = False
while True:
for id, func in self.hkey_list.items():
if self.hkey_flags[id]:
args = self._reg_list[id]["args"]
if args:
# print(args) #这里打印传入给注册函数的参数
thread_it(func,*args)
else:
thread_it(func)
self.hkey_flags[id] = False
return inner
def run(self):
for id in self._reg_list:
reg_info = self._reg_list[id]
fnkey = reg_info["fnkey"]
vkey = reg_info["vkey"]
func = reg_info["func"]
self.fast_reg(id,(fnkey, vkey), func)
fn = self.callback()
thread_it(fn) # 启动监听热键按下线程
try:
msg = ctypes.wintypes.MSG()
while True:
if self.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
if msg.message == win32con.WM_HOTKEY:
if msg.wParam in self.hkey_list:
self.hkey_flags[msg.wParam] = True
self.user32.TranslateMessage(ctypes.byref(msg))
self.user32.DispatchMessageA(ctypes.byref(msg))
finally:
for id in self.hkey_list:
self.user32.UnregisterHotKey(None, id)
def thread_it(func, *args):
t = Thread(target=func, args=args)
t.setDaemon(True)
t.start()
def jump(func,hotkey):
self_id = hotkey.get_id(func)
while hotkey.get_running_state(self_id):
print(f"{self_id : } 你正在1秒1次的跳动")
sleep(1)
def stop_jump(start_id,hotkey):
hotkey.hkey_running[start_id] = False
print(f"{start_id} 即将停止")
sleep(1)
print(f'当前线程列表:{activeCount()}', enumerate())
def main():
hotkey = Hotkey()
start_id = hotkey.reg(key = (win32con.MOD_ALT,win32con.VK_HOME),func=jump,args=(jump,hotkey)) #alt home键 开始
hotkey.reg(key = (0,win32con.VK_END),func=stop_jump,args=(start_id,hotkey)) #alt end键 结束
hotkey.start() #启动热键主线程
print(f"当前总线程数量:{activeCount()}")
print('当前线程列表:', enumerate())
print('热键注册初始化完毕,尝试按组合键alt+Home 或者单键END看效果')
if __name__ == '__main__':
main()