if(hCallWnd[index]==NULL)
continue;
if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
//lParam的意义可看MSDN中WM_KEYDOWN部分
}
}
}
returnCallNextHookEx(hHook,nCode,wParam,lParam);
}
抓图程序是一个基于对话框的程序,它在建立对话框的时候调用前面的DLL,登记热键,因此需要将hook.lib添加到工程里,在程序里给出两个DLL函数的定义,也可以写个头文件,再包含进来以下代码:
BOOL__declspec(dllexport)__stdcallAddHotkey(HWND,UCHARkey,UCHARmask);
BOOL__declspec(dllexport)__stdcallDeleteHotkey(HWND,UCHARkey,UCHARmask);
为了添加应用程序对热键通知事件的响应,程序中用的办法是重载WindowProc()函数,该函数代码如下:
LRESULTCCaptureDlg:
:
WindowProc(UINTmessage,WPARAMwParam,LPARAMlParam)
{
if(message==WM_HOTKEY&&lParam==WM_KEYDOWN)
{//lParam表示是按下还是松开,如果有多个热键,由wParam来区分
SaveBmp();
returnFALSE;
}
……//其它处理及默认处理
}
将屏幕图像保存到BMP文件中的任务是由函数SaveBmp()来完成的,具体实现参见代码部分。
另外为了顺利实现屏幕抓图,程序中还实现了"托盘"功能,由于这一部分本书在实例中已经专门介绍过了,所以不再赘述,读者朋友可以参考相关实例。
最后需要提醒读者朋友们注意的是,源程序的编译与使用时要先编译hook.dll并将其放在系统目录(win2000/NT是system32,98/ME是system),然后编译对话框程序运行即可。
二、编程步骤
1、启动VisualC++,生成一个DLL项目和一个基于对话框的应用程序项目,并将两个项目分别命名为"Hook"和"Capture";
2、在"Hook"项目中导出AddHotkey()、DeleteHotkey()函数;
3、在"Capture"项目中按照图一所示设置对话框的界面,具体设置参见代码部分;
4、使用ClassWizard在"Capture"项目中添加按钮的鼠标单击消息响应函数,并重载对话框的WindowProc()函数;
5、添加代码,编译运行程序。
三、程序代码
///////////////////////////////////////////////////////////Hook.h:
mainheaderfilefortheHOOKDLL
#if!
defined(AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_)
#defineAFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#ifndef__AFXWIN_H__
#errorinclude''stdafx.h''beforeincludingthisfileforPCH
#endif
#include"resource.h"//mainsymbols
classCHookApp:
publicCWinApp
{
public:
CHookApp();
//Overrides
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CHookApp)
public:
virtualBOOLInitInstance();
virtualintExitInstance();
//}}AFX_VIRTUAL
//{{AFX_MSG(CHookApp)
//NOTE-theClassWizardwilladdandremovememberfunctionshere.
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
LRESULTCALLBACKKeyboardProc(intnCode,WPARAMwParam,LPARAMlParam);
BOOL__declspec(dllexport)__stdcallAddHotkey(HWND,UCHARkey,UCHARmask);
BOOL__declspec(dllexport)__stdcallDeleteHotkey(HWND,UCHARkey,UCHARmask);
BOOLInitHotkey();
BOOLUnInit();
#endif
//////////Hook.cpp:
DefinestheinitializationroutinesfortheDLL.
#include"stdafx.h"
#include"hook.h"
#include
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
#defineMAX_KEY100
#defineCTRLBIT0x04
#defineALTBIT0x02
#defineSHIFTBIT0x01
#pragmadata_seg("shareddata")
HHOOKhHook=NULL;
UINTnHookCount=0;
staticUCHARHotKey[MAX_KEY]={0};//hotkey
staticUCHARHotKeyMask[MAX_KEY]={0};//flagforhotkey,valueisVK_CONTRLorVK_NEMUorVK_SHIFT
staticHWNDhCallWnd[MAX_KEY]={0};//windowassociatedwithhotkey
staticintKeyCount=0;
staticUCHARMaskBits=0;//00000CtrlAltShift
#pragmadata_seg()
HINSTANCEhins;
voidVerifyWindow();
BEGIN_MESSAGE_MAP(CHookApp,CWinApp)
//{{AFX_MSG_MAP(CHookApp)
//NOTE-theClassWizardwilladdandremovemappingmacroshere.
//DONOTEDITwhatyouseeintheseblocksofgeneratedcode!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CHookApp:
:
CHookApp()
{
//TODO:
addconstructioncodehere,
//PlaceallsignificantinitializationinInitInstance
}
CHookApptheApp;
LRESULTCALLBACKKeyboardProc(intnCode,WPARAMwParam,LPARAMlParam)
{
BOOLbProcessed=FALSE;
if(HC_ACTION==nCode)
{
if((lParam&0xc0000000)==0xc0000000){//Keyup
switch(wParam)
{
caseVK_MENU:
MaskBits&=~ALTBIT;
break;
caseVK_CONTROL:
MaskBits&=~CTRLBIT;
break;
caseVK_SHIFT:
MaskBits&=~SHIFTBIT;
break;
default:
//judgethekeyandsendmessage
break;
}
for(intindex=0;index if(hCallWnd[index]==NULL)
continue;
if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
{
SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);
bProcessed=TRUE;
}
}
}
elseif((lParam&0xc000ffff)==1){//Keydown
switch(wParam)
{
caseVK_MENU:
MaskBits|=ALTBIT;
break;
caseVK_CONTROL:
MaskBits|=CTRLBIT;
break;
caseVK_SHIFT:
MaskBits|=SHIFTBIT;
break;
default:
//judgethekeyandsendmessage
break;
}
for(intindex=0;index {
if(hCallWnd[index]==NULL)
continue;
if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
{
SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);
bProcessed=TRUE;
}
}
}
if(!
bProcessed){
for(intindex=0;index if(hCallWnd[index]==NULL)
continue;
if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
}
}
}
returnCallNextHookEx(hHook,nCode,wParam,lParam);
}
BOOLInitHotkey()
{
if(hHook!
=NULL){
nHookCount++;
returnTRUE;
}
else
hHook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
if(hHook!
=NULL)
nHookCount++;
return(hHook!
=NULL);
}
BOOLUnInit()
{
if(nHookCount>1){
nHookCount--;
returnTRUE;
}
BOOLunhooked=UnhookWindowsHookEx(hHook);
if(unhooked==TRUE){
nHookCount=0;
hHook=NULL;
}
returnunhooked;
}
BOOL__declspec(dllexport)__stdcallAddHotkey(HWNDhWnd,UCHARcKey,UCHARcMask)
{
BOOLbAdded=FALSE;
for(intindex=0;index if(hCallWnd[index]==0){
hCallWnd[index]=hWnd;
HotKey[index]=cKey;
HotKeyMask[index]=cMask;
bAdded=TRUE;
KeyCount++;
break;
}
}
returnbAdded;
}
BOOL__declspec(dllexport)__stdcallDeleteHotkey(HWNDhWnd,UCHARcKey,UCHARcMask)
{
BOOLbRemoved=FALSE;
for(intindex=0;index if(hCallWnd[index]==hWnd){
if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
hCallWnd[index]=NULL;
HotKey[index]=0;
HotKeyMask[index]=0;
bRemoved=TRUE;
KeyCount--;
break;
}
}
}
returnbRemoved;
}
void