onestone01 发表于 2020-7-3 09:40:29

截获 WIN 键如何保留其组合键[已解决]

本帖最后由 onestone01 于 2020-7-6 21:56 编辑

参考帮助文档和论坛的帖子,可以截获 win 键,阻止弹出开始菜单。
阻止了win 键传递结果导致 win组合键失效(如WIN+R;WIN+D...)
希望截获 win 键又保留组合键作用,应该怎么做?
#include <WinAPI.au3>
#include <WindowsConstants.au3>
Global $g_hHook, $g_hStub_KeyProc, $g_sBuffer = ""
Example()
Func Example()
      OnAutoItExitRegister("Cleanup")
      Local $hMod
      $g_hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
      $hMod = _WinAPI_GetModuleHandle(0)
      $g_hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($g_hStub_KeyProc), $hMod)
      While 1
                Sleep(10)
      WEnd
EndFunc   ;==>Example
; ===========================================================
; callback function
; ===========================================================
Func _KeyProc($nCode, $wParam, $lParam)
      Local $tKEYHOOKS
      $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
      If $nCode < 0 Then
                Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
      EndIf
      $wVKey = DllStructGetData($tKEYHOOKS, "vkCode")
      If ($wVKey = 27) Then ; Esc 键
                Exit
      ElseIf ($wVKey = 91) Then ;lwin
                If $wParam = $WM_KEYDOWN Or $wParam = $WM_SYSKEYDOWN Then ;按下
                        ToolTip("{win}DOWN.")
                        Return 1 ;如果按下不截获导致 WIN 键不弹起
                ElseIf $wParam = $WM_KEYUP Or $wParam = $WM_SYSKEYUP Then ;弹起
                        ToolTip("{win}up." )
                        Return 1
                EndIf
      EndIf
      Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>_KeyProc

Func Cleanup()
      _WinAPI_UnhookWindowsHookEx($g_hHook)
      DllCallbackFree($g_hStub_KeyProc)
EndFunc   ;==>Cleanup

guland 发表于 2020-7-3 10:44:32

ToolTip("{win}DOWN.")
Return 1 ;如果按下不截获导致 WIN 键不弹起

把这两行去掉就行了

onestone01 发表于 2020-7-3 10:54:14

guland 发表于 2020-7-3 10:44
ToolTip("{win}DOWN.")
Return 1 ;如果按下不截获导致 WIN 键不弹起



感谢回复,Return 1 去掉 导致 WIN 键不能弹起,比如按下win键释放后,单按D会显示桌面(win+d)也就是说弹起时拦截导致 WIN 键没弹起

afan 发表于 2020-7-4 15:06:17

按下win时不要 Return 1。如果返回1,不需要拦截的组合键就不容易处理响应了。
如果不返回,那就只需要处理win键弹起事件了。跟踪下在win按下到弹起期间有无其它键的消息,如果有则不处理,那样就可放过组合键;如果没有则send一些无意义的组合键即可。
仅给思路,无代码~

onestone01 发表于 2020-7-4 19:47:02

afan 发表于 2020-7-4 15:06
按下win时不要 Return 1。如果返回1,不需要拦截的组合键就不容易处理响应了。
如果不返回,那就只需要处 ...

非常感谢,高手思路就是开阔。我只考虑到按下或弹起有无其它键的消息,各种方法测试无果。
按照您的思路 按下win时不 Return 1,即使不使用组合键的情况下。也就是说按下到弹起期间无其它键的消息。
send一些无意义的组合键并不能阻止win弹起信息的传递。开始菜单仍然会弹出。
Return 1 拦截,系统又收不到弹起信息。
按照您的思路我再研究看看。

onestone01 发表于 2020-7-6 09:00:25

本帖最后由 onestone01 于 2020-7-6 09:01 编辑

一个比较笨的方法,基本上够用。效果不理想。缺点长按组合键,会不停的执行。希望有更好的方法#include <WinAPI.au3>
#include <WindowsConstants.au3>
Global $g_hHook, $g_hStub_KeyProc, $g_sBuffer = "", $WinDOWN = 0
Example()
Func Example()
      OnAutoItExitRegister("Cleanup") ;退出时移除钩子
      Local $hMod
      $g_hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
      $hMod = _WinAPI_GetModuleHandle(0)
      $g_hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($g_hStub_KeyProc), $hMod)
      While 1
                Sleep(10)
      WEnd
EndFunc   ;==>Example
; ===========================================================
; callback function
; ===========================================================
Func _KeyProc($nCode, $wParam, $lParam)
      Local $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam)
      If $nCode < 0 Then
                Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
      EndIf
      $wVKey = DllStructGetData($tKEYHOOKS, "vkCode")
      Switch $wVKey
                Case 27 ; Esc 键
                        Exit
                Case 91, 92 ;左右 Win 键
                        If $wParam = $WM_KEYDOWN Then ;按下
                              $WinDOWN = 1
                              ToolTip('WINDOWN')
                        ElseIf $wParam = $WM_KEYUP Then ;弹起
                              $WinDOWN = 0
                              ToolTip('WINUP')
                        EndIf
                        Return 1
                Case 9, 19, 48 To 57, 65 To 90
                        If $WinDOWN = 1 AND $wParam = $WM_KEYDOWN Then
                              Send('#' & _KEYChr($wVKey))
                              $keyDOWN = 1
                              Return 1
                        EndIf
      EndSwitch
      Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>_KeyProc

Func _KEYChr($Key)
      Switch $Key
                Case 9
                        Return ('{TAB}')
                Case 19
                        Return ('{PAUSE}')
                Case 48 To 90 ;48 To 57 => 0 - 9 键 |65 To 90 => a - z 键
                        Return StringLower(Chr($Key)) ;返回 ASCII 码 并转换为小写
      EndSwitch
      Return ''
EndFunc   ;==>_KEYChr
Func Cleanup()
      _WinAPI_UnhookWindowsHookEx($g_hHook)
      DllCallbackFree($g_hStub_KeyProc)
EndFunc   ;==>Cleanup



afan 发表于 2020-7-6 20:46:24

这个就属于我上面说的“就不容易处理响应了”。
1,Ctrl、Shift、Alt 这些辅助键参与的组合键无效,因为它们几个被无视了。你可以 Case 160 to 165 ,处理需添加的 Send的辅助键
2,只处理了一些字母数字快捷键,然而还有很多都可以作为组合键的也被无视了,比如方向键、PageUp等。Case 48 To 90 ;48 To 57 => 0 - 9 键 |65 To 90 => a - z 键 可以改为 Case Else 处理
3,第38行Send,实际会被执行N次,你在下面添加一行ConsoleWrite调试看看便知。(但这里与你的“缺点长按组合键,会不停的执行”无关)

onestone01 发表于 2020-7-6 21:55:24

afan 发表于 2020-7-6 20:46
这个就属于我上面说的“就不容易处理响应了”。
1,Ctrl、Shift、Alt 这些辅助键参与的组合键无效,因为它 ...

非常感谢指点,这种方法弊端很大,正如你所说确实不容易处理响应。我再试试你说的 SEND 一些无意义的组合键,先结贴吧。这种方法凑合也能用(要求不高自己用知道它的缺点)。
页: [1]
查看完整版本: 截获 WIN 键如何保留其组合键[已解决]