改自“Delphi下深入Windows核心编程”56页HookKey程序。原来的Delphi代码使用DEMO控件来显示键盘输入,采用VC后改用多行编辑EDIT控件来显示。程序的思路是当DLL截获键盘消息后,向主程序发送一条自定义的消息,然后主程序将键盘输入显示在对话框中的编辑控件里。关键是采用共享节保存主程序的窗口句柄,并且在DLL中导出该句柄,这样主程序可以在初始化的时候给该句柄赋值,而DLL获得该句柄后,就可以向主程序窗口发送消息了;另外还有EDIT控件用作显示时,要设为只读属性,防止回显键盘输入;采用向该控件发送EM_REPLACESEL消息来连续显示字符。
代码虽然简单,但是我是在参考了WINDOWS核心编程和罗云彬WIN32汇编教程之后费了不少劲才实现了,汗。编程环境是VC2003,使用了JEFFREY大牛同志推荐的MESSAGE CRACKER宏。
Dll部分
//Key.h
//下列 ifdef 块是创建使从 DLL 导出更简单的
//宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 KEY_EXPORTS
// 符号编译的。在使用此 DLL 的
//任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// KEY_API 函数视为是从此 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef KEY_EXPORTS
#define KEY_API extern "C" __declspec(dllexport)
#else
#define KEY_API extern "C" __declspec(dllimport)
#endif
#define WM_HooKKEY (WM_USER+1000)
KEY_API void HookOn();
KEY_API void HookOff();
KEY_API HWND ViewInteger;
// Key.cpp : 定义 DLL 应用程序的入口点。
#include <windows.h>
#include "Key.h"
//#include <stdio.h>
//#define KEY_EXPORTS
// 定义共享数据段
#pragma data_seg("shared")
HWND ViewInteger= HWND(0); // 主程序句柄
#pragma data_seg()
#pragma comment(linker, "/section:shared,rws")
HHOOK HookDeTeclado = NULL; //钩子句柄
HINSTANCE hInstDLL = NULL; // DLL句柄
HWND hWndKey = NULL; // 主窗口句柄
// DLL主函数
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
hInstDLL = hinstDLL;
return TRUE;
}
// 钩子过程,监视键盘消息
LRESULT CALLBACK CallBackDelHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
hWndKey = ViewInteger;
PostMessage(hWndKey,WM_HooKKEY,wParam,lParam);
return CallNextHookEx(HookDeTeclado,nCode,wParam,lParam);
}
//
void HookOn(void)
{
HookDeTeclado = SetWindowsHookEx(WH_KEYBOARD,CallBackDelHook,hInstDLL,0);
//return 0;
}
//
void HookOff(void)
{
UnhookWindowsHookEx(HookDeTeclado);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
主程序部分
// stdafx.h : 标准系统包含文件的包含文件,
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// TODO: 在此处引用程序要求的附加头文件a
#include <commctrl.h>
#include <windowsx.h>
#define chHANDLE_MSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, msg, HANDLE_##message((hwnd), (wParam), (lParam), (fn))))
// This macro evaluates to the number of elements in an array.
#define chDIMOF(Array) (sizeof(Array) / sizeof(Array[0]))
// TestKeyHook.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "TestKeyHook.h"
#include <stdarg.h> //va_list
//#include <tchar.h>
#include <stdio.h> //_vstprintf
#include "Key\Key.h"
//#pragma comment(lib, "Key.lib")
//该函数改自Windows核心编程第四章
void AddText(HWND hwnd, PCTSTR pszFormat, ...) {
va_list argList;
va_start(argList, pszFormat);
TCHAR sz[20 * 1024];
// Edit_GetText(hwnd, sz, chDIMOF(sz));
// _vstprintf(_tcschr(sz, 0), pszFormat, argList);
_vstprintf(sz, pszFormat, argList);
// Edit_SetText(hwnd, sz);
SendMessage(hwnd, EM_REPLACESEL,0, (LPARAM)sz);
//SendMessage(hwnd, WM_VSCROLL,SB_BOTTOM, 0);
va_end(argList);
}
// 此代码模块中包含的函数的前向声明:
BOOL CALLBACK Dlg_DlgProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,Dlg_DlgProc);
return 0;
}
//
// Process WM_COMMAND message for window/dialog: Dlg
//
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
// TODO: Add your message processing code here...
switch(id){
case IDCANCEL:
if(HookOff!=NULL)
HookOff();
EndDialog(hwnd,id);
break;
}
}
//
// Process WM_INITDIALOG message for window/dialog: Dlg
//
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
MessageBox(hwnd,"1",0,0);
// TODO: Add your message processing code here...
ViewInteger=hwnd;
HookOn();
return(TRUE);
}
void Dlg_HooKKEY(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam)
{
HWND hEdit=GetDlgItem(hwnd,IDC_EDIT1);
char KeyName[101];
// char* Accion;
GetKeyNameText(lParam,KeyName,100);
if((lParam >> 31)&&1==1)
AddText(hEdit,"%s %s\r\n","Key up",KeyName);
else if ((lParam >> 30)&&1==1)
AddText(hEdit,"%s %s\r\n","ReKeyDown",KeyName);
else
AddText(hEdit,"%s %s\r\n","KeyDown",KeyName);
//MessageBox(hwnd,Accion,0,0);
//Edit_SetText(GetDlgItem(hwnd,IDC_EDIT1),(LPSTR)Accion);
}
//
// Dlg Dialog Procedure
//
BOOL CALLBACK Dlg_DlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
chHANDLE_MSG (hwndDlg, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_MSG (hwndDlg, WM_COMMAND, Dlg_OnCommand);
//// TODO: Add dialog message crackers here...
case WM_HooKKEY:
Dlg_HooKKEY(hwndDlg,msg,wParam,lParam);
default: return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(中华人民共和国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_TESTKEYHOOK ICON "TestKeyHook.ico"
IDI_SMALL ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_TESTKEYHOOK ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOGEX 0, 0, 267, 161
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_EDIT1,7,7,253,147,ES_MULTILINE | ES_READONLY |
WS_VSCROLL | NOT WS_TABSTOP
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 260
TOPMARGIN, 7
BOTTOMMARGIN, 154
END
END
#endif // APSTUDIO_INVOKED
#endif // 中文(中华人民共和国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED