请问各位高手,如何用C++获取用户在键盘上的按住某个键的时间

请问各位高手,如何用C++获取用户在键盘上的按住某个键的时间,第1张

如果是VC++

有KeyDown

和KeyUP时间

可以在KeyDown事件里判断如果按下是某些特定键,记下当前时间,

KeyUp事件中判定如果放开的是这些特定键,记下当前时间,和前面的时间算出时间差。

Edge是微软公司开发的一款网络浏览器,支持Windows *** 作系统。在Edge浏览器中,可以通过键盘触发各种事件来方便地 *** 作浏览器。键盘事件包括按键按下事件、按键松开事件、按键按住事件等。

按键按下事件是指当用户按下一个键时,浏览器会触发该事件。我们可以通过该事件来监听用户的输入,并做出相应的响应。例如,在搜索框中输入文字时,可以通过键盘按下事件来实时搜索。

按键松开事件是指当用户释放一个键时,浏览器会触发该事件。通过该事件,我们可以实现一些特殊的功能。例如,在游戏中,当用户放开空格键时,角色可以跳起来。

按键按住事件是指当用户按住一个键时,浏览器会重复触发按键事件。通过该事件,我们可以实现一些连续的动作。例如,在游戏中,当用户按住箭头键时,角色可以持续向某个方向移动。

总之,Edge浏览器支持键盘事件,可以方便地监听用户的输入,并实现相应的功能。开发者可以根据需要选择相应的事件,并编写相应的代码实现功能。

梢允褂玫撞慵�坦匙� #include "windowsh" // 回调函数指针typedef BOOL (CALLBACK LPFNKEYBOARDPROC)(WPARAM, KBDLLHOOKSTRUCT); // 全局变量LPDWORD g_lpdwVirtualKey = NULL; // Keycode 数组的指针int g_nLength = 0; // Keycode 数组的大小BOOL g_bDisableKeyboard = FALSE; // 是否屏蔽整个键盘HINSTANCE g_hInstance = NULL; // 模块实例句柄HHOOK g_hHook = NULL; // 钩子句柄LPFNKEYBOARDPROC g_lpfnKeyboardProc; // 键盘钩子回调函数指针 // DLL 入口函数BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){ // 保存模块实例句柄 g_hInstance = (HINSTANCE)hModule; // 在进程结束或线程结束时卸载钩子 switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH: free(g_lpdwVirtualKey); if (g_hHook != NULL) UnhookWindowsHookEx(g_hHook); break; } return TRUE;} // 底层键盘钩子函数LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){ // 拦截键盘的某些按键, 如果 g_bDisableKeyboard 为 TRUE 则拦截整个键盘按键if (nCode >= HC_ACTION) { KBDLLHOOKSTRUCT pStruct = (KBDLLHOOKSTRUCT)lParam; if (g_bDisableKeyboard) if (g_lpfnKeyboardProc(wParam, pStruct)) return CallNextHookEx(g_hHook, nCode, wParam, lParam); else return true; LPDWORD tmpVirtualKey = g_lpdwVirtualKey; for (int i = 0; i < g_nLength; i++) { if (pStruct->vkCode == tmpVirtualKey++) if (g_lpfnKeyboardProc(wParam, pStruct)) return CallNextHookEx(g_hHook, nCode, wParam, lParam); else return true; } } // 调用系统中的下一个钩子 return CallNextHookEx(g_hHook, nCode, wParam, lParam);} /// 开始拦截键盘按键 // // 参数: // lpdwVirtualKey Keycode 数组的指针 // nLength Keycode 数组的大小 // bDisableKeyboard 是否拦截整个键盘 // // 返回值: TRUE 成功, FALSE 失败 ///BOOL WINAPI StartMaskKey(LPDWORD lpdwVirtualKey, int nLength, LPFNKEYBOARDPROC lpfnKeyboardProc, BOOL bDisableKeyboard = FALSE){ // 如果已经安装键盘钩子则返回 FALSE if (g_hHook != NULL || nLength == 0) return FALSE; // 将用户传来的 keycode 数组保存在全局变量中 g_lpdwVirtualKey = (LPDWORD)malloc(sizeof(DWORD) nLength); LPDWORD tmpVirtualKey = g_lpdwVirtualKey; for (int i = 0; i < nLength; i++) { tmpVirtualKey++ = lpdwVirtualKey++; } g_nLength = nLength; g_bDisableKeyboard = bDisableKeyboard; g_lpfnKeyboardProc = lpfnKeyboardProc; // 安装底层键盘钩子 g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, NULL); if (g_hHook == NULL) return FALSE; return TRUE; } /// 停止拦截键盘按键 // // 参数: (无) // // 返回值: TRUE 成功, FALSE 失败 ///BOOL WINAPI StopMaskKey(){ // 卸载钩子 if (UnhookWindowsHookEx(g_hHook) == 0) return FALSE; g_hHook = NULL; return TRUE;} 当然了,MaskKeyh头文件中也要加上: // 回调函数指针typedef BOOL (CALLBACK LPFNKEYBOARDPROC)(WPARAM, KBDLLHOOKSTRUCT); 下面是在VC中调用的例子:(两个Dialog的成员函数,对应两个按钮,再加上一个回调函数) // 全局键盘钩子回调函数// 参数: action 标识键盘消息(按下,d起), keyStruct 包含按键信息BOOL CALLBACK KeyboardProc(WPARAM action, KBDLLHOOKSTRUCT pKeyStruct){ // 判断按键动作 switch (action) { case WM_KEYDOWN: break; case WM_KEYUP: break; case WM_SYSKEYDOWN: break; case WM_SYSKEYUP: break; } // 返回 true 表示继续传递按键消息 // 返回 false 表示结束按键消息传递 return false;} void CMaskKeyAppDlg::OnStartmaskkey() { // 屏蔽 A, B, C, 上, 下, 左, 右及两个win键 DWORD dwVK[] = {'A', 'B', 'C', VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_LWIN, VK_RWIN}; int nLength = sizeof(dwVK) / sizeof(DWORD); StartMaskKey(dwVK, nLength, KeyboardProc); } void CMaskKeyAppDlg::OnStopmaskkey() { StopMaskKey(); } 呵呵,这样是不是让看到这里的你很兴奋呢?!StartMaskKey加了一个参数,是个函数指针,这是我们非常熟悉的回调函数的使用方法。DLL中的StartMaskKey函数收到这个函数指针后保存在了g_lpfnKeyboardProc变量中,然后在LowLevelKeyboardProc中一旦发现了要拦截的按键,就会通过函数指针调用回调函数,将控制权完全交回给DLL的调用程序,由回调函数KeyboardProc进一步处理(播放一小段音乐,还是执行个什么有意思的程序,亦或是重启关机什么的。呃,随你便了。:D),action参数用来标识键盘消息(按下或d起),pKeyStruct参数包含了丰富的按键信息,其实就是系统传给LowLevelKeyboardProc的lParam,我又把它原封不动地传给了KeyboardProc,呵呵。最重要的就是回调函数的返回值了,它就像阀门的开关一样,将决定这个按键消息的命运。从DLL中的LowLevelKeyboardProc函数的流程可以看出,如果回调函数KeyboardProc的返回值为true则表示把该按键消息继续传递给系统中的下一个钩子;如果为false则表示结束该按键消息的传递,此时将会起到拦截按键的效果。 用VB的人可能有些不耐烦了,别着急,上篇文章在最后给出了VB调用的例程,此篇当然不能缺少这部分了。下面是在VB中调用的例子:(在窗体上添加2个CommandButton,并分别改名为cmdStartMask和cmdStopMask) Option ExplicitPrivate Declare Function StartMaskKey Lib "MaskKey" (lpdwVirtualKey As Long, ByVal nLength As Long, ByVal lpfnKeyboarProc As Long, Optional ByVal bDisableKeyboard As Boolean = False) As LongPrivate Declare Function StopMaskKey Lib "MaskKey" () As Long Private Sub cmdStartMask_Click() ' 屏蔽 A, B, C, 上, 下, 左, 右及两个win键 Dim key(8) As Long key(0) = vbKeyA key(1) = vbKeyB key(2) = vbKeyC key(3) = vbKeyLeft key(4) = vbKeyRight key(5) = vbKeyUp key(6) = vbKeyDown key(7) = &H5B ' 左边的win键 key(8) = &H5C ' 右边的win键 StartMaskKey key(0), UBound(key) + 1, AddressOf KeyboardProcEnd Sub Private Sub cmdStopMask_Click() StopMaskKeyEnd Sub 窗体模块的代码和以前的例程几乎一样,只是在调用StartMaskKey函数时加了一个参数:AddressOf KeyboardProc。在VB中用过回调函数的人对这东西绝不会陌生,AddressOf是一个一元运算符,后面接一个函数名,它的功能就是获得指定函数的指针。但有一点必须注意,该回调函数(此例中为KeyboardProc)必须写在VB的标准模块中,标准模块的代码如下: Option Explicit Private Const WM_KEYDOWN = &H100Private Const WM_KEYUP = &H101Private Const WM_SYSKEYDOWN = &H104Private Const WM_SYSKEYUP = &H105 Public Type KBDLLHOOKSTRUCT vkCode As Long ' 虚拟按键码(1--254) scanCode As Long ' 硬件按键扫描码 flags As Long ' flags time As Long ' 消息时间戳 dwExtraInfo As Long ' 额外信息End Type Public Enum KEYACTION ACTION_KEYDOWN = WM_KEYDOWN ACTION_KEYUP = WM_KEYUP ACTION_SYSKEYDOWN = WM_SYSKEYDOWN ACTION_SYSKEYUP = WM_SYSKEYUPEnd Enum ' 全局键盘钩子回调函数' 参数: action 标识键盘消息(按下,d起), keyStruct 包含按键信息Public Function KeyboardProc(ByVal action As KEYACTION, keyStruct As KBDLLHOOKSTRUCT) As Boolean Select Case action Case ACTION_KEYDOWN DebugPrint keyStructvkCode, "按下键盘按键" Case ACTION_KEYUP DebugPrint keyStructvkCode, "d起键盘按键" Case ACTION_SYSKEYDOWN Case ACTION_SYSKEYUP End Select ' 返回 True 表示继续传递按键消息 ' 返回 False 表示结束按键消息传递 KeyboardProc = FalseEnd Function 和VC版的调用例程差不多,只是把语法翻译成了VB的,这个VB标准模块中的KeyboardProc有没有点MFC消息映射函数的味道呢?! :D需要注意的是,VB的回调函数必须写在标准模块中。细心的人还可能会发现,我对action参数作了一点小手脚,改成了一个枚举类型,这主要是为了易于理解。OK,要写的就这么多了,关于全局键盘钩子的内容我也想告一段落了。利用VC编写的DLL,VB也可以方便地实现全局键盘钩子了。当然,这不仅仅局限于键盘钩子,利用这种方法可以实现任何类型的钩子。

首先最简单的但可以后台处理的有SendMessage()PostMessage()

发送鼠标,

键盘消息,

这个百度一搜n多了

然后中等级的模拟就是keyboard_eventmouse_event了这个比较用的比较多,

给个例子你

模拟键盘点击void

Press(UINT

key)

{

keybd_event(key,MapVirtualKey(key,

0),0,0);

keybd_event(key,MapVirtualKey(key,

0),KEYEVENTF_KEYUP,0);

}

模拟

鼠标左键单击mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);

mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

这里注意调用

keyboard_event

的时候一定要用MapVirtualKey

网上大部分的代码都是没用的,

这个函数时获取

硬件扫描码

的先说下keybd_event();函数的参数keybd_event(要模拟按下的虚拟按键码,

虚拟按键码对应的硬件扫描码,0,0);网上的代码大部分都有

虚拟按键码,

当然你运行大部分都是没问题的,

因为对于一般的程序而言是没问题的但有的程序为了防止

外挂

或者

防止其他程序恶意修改什么的,会对

鼠标键盘

消息进行检测,

如果检测到没有硬件扫描码会拒绝执行的

然后还有比较高级的就是SendInput模拟了void

OnSendCharCode(unsigned

short

unicode

=

0,unsigned

short

vcode

=

0,bool

bDown

=

false,bool

bUnicode

=

true);

void

OnSendCharCode(unsigned

short

unicode,unsigned

short

vcode,bool

bDown,bool

bUnicode)

{

unsigned

short

uNum

=

0;

//

v-code

Clicked

INPUT

事件设定

KEYBDINPUT

kDown;

KEYBDINPUT

kUp;

if(!bUnicode)

{

//

'A';

(Virtual

Code

只有大写),

要输入小写

//

Enter:

13,

Backspace:

8,

Up:38

kDownwVk

=

kUpwVk

=

vcode;

kDownwScan

=

kUpwScan

=

::MapVirtualKey(kDownwVk,0);

//kDowndwFlags

=

KEYEVENTF_EXTENDEDKEY;

kUpdwFlags

=

KEYEVENTF_KEYUP;

}else{

kDownwVk

=

kUpwVk

=

0;

kDownwScan

=

kUpwScan

=

unicode;

kDowndwFlags

=

KEYEVENTF_UNICODE;

kUpdwFlags

=

KEYEVENTF_UNICODE

|

KEYEVENTF_KEYUP;

}

//

建立

KeyDown

事件

建立

KeyUP

事件

INPUT

inputKeyDown,

inputKeyUP;

inputKeyDowntype

=

inputKeyUPtype

=

INPUT_KEYBOARD;

//

指定

input

keyboard

kDowntime

=

kUptime

=

0;

//

the

system

will

provide

its

own

time

stamp

kDowndwExtraInfo

=

kUpdwExtraInfo

=

(WORD)::GetMessageExtraInfo();

inputKeyDownki

=

kDown;//

指定

键盘

属性结构

inputKeyUPki

=

kUp;

//

指定

键盘

属性结构

//

v-code

Clicked

INPUT

事件设定完成

//

INPUT

事件送到

Root

视窗,

系统会根据视窗位置,送给目标视窗

if(bDown)

{

INPUT

event[1]

=

{inputKeyDown};

uNum

=

::SendInput(1,event,

sizeof(INPUT));

}else{

INPUT

event[2]

=

{inputKeyDown,inputKeyUP};

uNum

=

::SendInput(2,event,

sizeof(INPUT));

}

}

//例子:

OnSendCharCode(0,VK_SHIFT,true,false);

OnSendCharCode(0,'A',false,false);

OnSendCharCode(0,VK_SHIFT,false,false);

OnSendCharCode(0,'A',false,false);

//KEYEVENTF_UNICODE

能区分大小写

OnSendCharCode('A');

OnSendCharCode('a');

不过还是有很多游戏,它是用

DirectX

技术去做的,这些大部分对他们没用所以还有最最最高级的模拟,

就是

对硬件驱动程序的模拟这个有个外国人写的

winioh

的头文件,

有兴趣可以去学,

一般用不到的,

以上就是关于请问各位高手,如何用C++获取用户在键盘上的按住某个键的时间全部的内容,包括:请问各位高手,如何用C++获取用户在键盘上的按住某个键的时间、edge浏览器触发键盘事件、vc下如何获取键盘任意按键并返回值等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9317209.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存