BOOL RegisterHotKey( HWND hWnd, // handle to window int id, // hot key identifier UINT fsModifiers, // key-modifier options UINT vk // virtual-key code );其中 fsModifiers MOD_ALT Either ALT key must be held down. MOD_CONTROL Either CTRL key must be held down. MOD_SHIFT Either SHIFT key must be held down. MOD_WIN Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. vk [in] Specifies the virtual-key code of the hot key. 来自MSDN
RegisterHotKey注册的热键确实是全局的。 但如果是在Windows 9x中,热键在某些程序中(例如游戏等)会失效,而且焦点在MS-DOS窗口时也会失效。 Windows NT/2000/XP下面没有这个问题,但如果焦点在Console窗口,热键按下以后只会发送一次WM_HOTKEY,而不像平时那样不断发送。
HWND hWnd, // handle to window
int id, // hot key identifier
UINT fsModifiers, // key-modifier options
UINT vk // virtual-key code
);其中
fsModifiers
MOD_ALT Either ALT key must be held down.
MOD_CONTROL Either CTRL key must be held down.
MOD_SHIFT Either SHIFT key must be held down.
MOD_WIN Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. vk
[in] Specifies the virtual-key code of the hot key. 来自MSDN
WM_HOTKEY消息。所以你要在你的程序中处理这个消息。
谁都知道怎么用HOTKEY,热键只有在对应的窗口有键盘的焦点的时候才起作用。
你的说法根本 解决不了问题!
这是系统级的,
在程序中也容易实现。
2.reg hotkey
3.agent wait for hotkey msg
4.agent run winamp
类似这样的格式吧,因为我以前写的钩子是Win32ASM的,所以翻译过来可以有点错误,不过也应该差不多。To Robert2001(Robert2001):
其实钩子并不神秘,只是你自己觉得很难罢了,用过就觉得很简单。
窗口不要焦点也可以接受,一定可以做到这个要求的
http://myhotsoft.yeah.net 有个系统热键的程序就是用这个做的
但如果是在Windows 9x中,热键在某些程序中(例如游戏等)会失效,而且焦点在MS-DOS窗口时也会失效。
Windows NT/2000/XP下面没有这个问题,但如果焦点在Console窗口,热键按下以后只会发送一次WM_HOTKEY,而不像平时那样不断发送。
钩子我上学的时候就会了,只是我不喜欢钩子,现在这里的人动不动就说用钩子,我不认为钩子很稳定,我见过不少软件都是因为钩子出错的。
我来这里是来听课的,我希望能看到一写更有水平的见解!但是到现在为止,我还没有看到。
你说的对,看来我对RegisterHotKey理解是错误的!
hook.asm.386
.model flat, stdcall
option casemap:noneinclude \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include HookDll.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib HookDll.lib.const
IDD_MAINDLG equ 101
IDC_HOOK equ 1004
IDC_EXIT equ 1005
WM_KBHOOK equ 2000DlgFunc proto :HWND, :UINT, :WPARAM, :LPARAM.data
Text db "just test", 0
Caption db "test", 0
HookFlag BOOL FALSE
HookText db "&Hook", 0
UnhookText db "&Unhook", 0.data?
hInstance HINSTANCE ?
hHook dd ?.code
main:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, IDD_MAINDLG, NULL, addr DlgFunc, NULL
invoke ExitProcess, NULL
DlgFunc proc hDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hLib:DWORD
LOCAL rect:RECT.if uMsg == WM_CLOSE
.if HookFlag == TRUE
;卸载钩子
invoke UninstallHook
.endif
invoke EndDialog, hDlg, NULL.elseif uMsg == WM_INITDIALOG
;窗口设为最前面:
invoke GetWindowRect, hDlg, addr rect
invoke SetWindowPos, hDlg, HWND_TOPMOST, rect.left, rect.top, rect.right, rect.bottom, SWP_NOSIZE.elseif uMsg == WM_KBHOOK
;键盘钩子处理:
.if wParam == VK_ESCAPE
invoke MessageBox, NULL, addr Text, addr Caption, MB_OK
.endif.elseif uMsg == WM_COMMAND
.if lParam != 0
mov eax, wParam
mov edx, eax
shr edx, 16
.if dx == BN_CLICKED
.if ax == IDC_EXIT
invoke SendMessage, hDlg, WM_CLOSE, 0, 0
.else
.if HookFlag == FALSE
invoke InstallHook, hDlg
.if eax != NULL
mov HookFlag, TRUE
invoke SetDlgItemText, hDlg, IDC_HOOK, addr UnhookText
.endif
.else
invoke UninstallHook
invoke SetDlgItemText, hDlg, IDC_HOOK, addr HookText
mov HookFlag, FALSE
.endif
.endif
.endif
.endif
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
retDlgFunc endpend main;资源文件:
hook.rc#include "resource.h"
#define IDD_MAINDLG 101
#define IDC_HOOK 1004
#define IDC_EXIT 1005IDD_MAINDLG DIALOG DISCARDABLE 0, 0, 229, 85
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Mouse Hook Demo"
FONT 8, "MS Sans Serif"
{
DEFPUSHBUTTON "&Hook",IDC_HOOK,159,35,50,14
PUSHBUTTON "E&xit",IDC_EXIT,159,50,50,14
};DLL文件:
hookdll.asm.386
.model flat, stdcall
option casemap:noneinclude \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib.const
WM_KBHOOK equ 2000.data?
hHook dd ?
hWnd dd ?.data
hInstance HINSTANCE 0.code
DllMain proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason == DLL_PROCESS_ATTACH
push hInst
pop hInstance
.endif
mov eax, TRUE
ret
DllMain endpKBProc proc nCode:DWORD, wParam:WPARAM, lParam:LPARAM
;钩子处理函数:
invoke CallNextHookEx, hHook, nCode, wParam, lParam
invoke PostMessage, hWnd, WM_KBHOOK, wParam, 0
xor eax, eax
ret
KBProc endpInstallHook proc hwnd:HWND
push hwnd
pop hWnd
;装载钩子:
invoke SetWindowsHookEx, WH_KEYBOARD, addr KBProc, hInstance, NULL
mov hHook, eax
ret
InstallHook endpUninstallHook proc
invoke UnhookWindowsHookEx, hHook
ret
UninstallHook endpend DllMain
;DEF文件,用来输出DLL里面的函数:
hookdll.defLIBRARY HookDll
EXPORTS KBProc
InstallHook
UninstallHook
;INC文件:
hookdll.incKBProc proto :DWORD, :WPARAM, :LPARAM
InstallHook proto :HWND
UninstallHook proto注意事项:编译的时候要这样做:
1、编译DLL文件:
ml /coff /c hookdll.asm
link /dll /section:.bss,S /subsystem:windows /def:hookdll.def hookdll.obj
其中关键的是link /section:.bss,S 这项,意思是把hookdll.asm文件里面的.data?这个数据段共享出去2、编译主程序:
ml /coff /c hook.asm
rc hook.rc
link /subsystem:windows hook.obj hook.res
1、Win32ASM其实完全是用SDK的方式来编程,完全可以一句句翻译成对应的C文件。
2、Robert2001(Robert2001)老兄所谓的钩子不稳定其实是可以避免的,就是用日志钩子,而不用键盘钩子。我这里用了键盘钩子,主要是以前做的用途并不是用来截获密码,所以就只用一般的键盘钩子。
3、一般的键盘钩子和日志钩子的区别在于:键盘钩子是系统先处理了,然后才被钩子钩住,日志钩子是先被钩子钩住,然后才给系统处理。由此会造成一个后果:如果用键盘钩子,就无法截获屏幕保护程序之类的程序的密码,因为系统会先处理;而用日志钩子就没有这个麻烦了。因此所谓的“不稳定”,很有可能是用了键盘钩子。抛砖引玉之谈,希望看到更多高手的妙招!!