在Windows操作系统中,当用户按下"PrintScreen"按钮后,Windows自动将当前屏幕的图像拷贝到系统剪贴板中,这时可以通过"画笔"这个小程序将剪贴板中的内容保存成图像文件,可以看出,如果需要将当前屏幕保存下来还是比较麻烦的,能否可以自己编写一个应用程序,自动将当前屏幕的内容保存到一个图像文件中去呢?这个答案是肯定的,本实例应用程序就是利用通用的热键管理DLL库实现的热键功能,在收到热键通知后截取屏幕的内容并保存到bmp文件中。例如我们设置图片保存路径为c:\,热键为F9 + Control,然后按Change按钮设置好热键,那么当我们按下CTRL+F9后,当前界面将以BMP图像文件的格式被保存在C:\目录下。程序编译运行后的界面效果如图一所示:
^ZV xBQKg
KYeA= 一、实现方法
A7sej EdU3k'z$ 热键管理DLL实际上是一个键盘钩子,由它来监视系统的键盘事件。如果有和程序登记符合的按键组合就通知该程序的窗口。为了应用方便,本实例把它做成了一个标准的管理库来为其它的程序通过热键服务,它有两个输出函数:AddHotkey()和DeleteHotkey(),程序只需要调用这两个函数就可以了,如果编译之后不用改变热键,则只需要AddHotkey就可以了。DLL中的所有的全局变量都放在一个共享段中,定义如下:
6Qo6T][ iffU}ce #pragma data_seg("shareddata")
"=RB
# HHOOK hHook =NULL; //钩子句柄
p3Gj=G UINT nHookCount =0; //挂接的程序数目
N[mOJa: static UCHAR HotKey[MAX_KEY] = {0}; //热键虚拟键码
Ea3tF0{ static UCHAR HotKeyMask[MAX_KEY] = {0}; //组合掩码, control=4,alt=2,shift=1
G{s ,Y^ static HWND hCallWnd[MAX_KEY] = {0}; //window handle associated with hotkey
M0]fh5O static int KeyCount =0;
11)~!in static UCHAR MaskBits =0; //00000 Ctrl=4 & Alt=2 & Shift=1
vi=yR #pragma data_seg()
IAtZ-cM< H;Bj\-Pa 关于共享段,有几点重要的说明:一是必须在链接选项里指定该段为共享:一种方法是在project->settings->link->object/library中加上/section:shareddata,rws;第二种方法是在def文件的sections里加上一句shareddata read write shared;第三种指定共享段的方法在程序里加上一句#pragma comment(linker,"section:shareddata,rws")。二是所有的变量必须初始化,否则链接程序会把它放到普通数据段。三是如果不初始化变量,需要在段外用"__declspec(allocate("shareddata")) 变量类型 变量名"的方式定义。
bM!`C|,[s mki=.l$O DLL中的两个输出函数分别用来添加/删除热键,函数代码如下:
Kp99y EZ=M^0=Hpf BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR
?e ~* ,6 cKey,UCHAR cMask)
gF:wdcO {
A^m hPBT_ BOOL bAdded=FALSE;
ROfmAc for(int index=0;index<MAX_KEY;index++){
.Kv@p jOr if(hCallWnd[index]==0){
x~mXtqg hCallWnd[index]=hWnd;
%?cPqRHJ ~ HotKey[index]=cKey;
"JGaw_o HotKeyMask[index]=cMask;
NR3IeTd bAdded=TRUE;
)-sEm`(`I9 KeyCount++;
eygyVhJ break;
ES+&e/G"ds }
>0m-S :lk }
.)o5o7H return bAdded;
nd?m+C&W }
.p5*&i7 //删除热键
< ^&'r5H BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
sO*6F`eiZ {
HY42G#^ BOOL bRemoved=FALSE;
SHaZ-d for(int index=0;index<MAX_KEY;index++){
vuK 5DG4 if(hCallWnd[index]==hWnd){
QO%LSRw if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
ar{e<&Bny hCallWnd[index]=NULL;
>Te{a*`"m: HotKey[index]=0;
Comuc HotKeyMask[index]=0;
i<T`]g bRemoved=TRUE;
eFx*lYjA KeyCount--;
k{;:KW| break;
44]ae~@a }
zZy>XHR
H }
M\]E;C'"U }
DnTM#i: return bRemoved;
[C&c;YNp }
I/(`<s p [R~HhM ZWFH5#= DLL中的钩子函数如下:
J d`NS3;*p *"4ltWS LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
b_LzG_n! {
%GIla* BOOL bProcessed=FALSE;
N
Lo>"<Xb if(HC_ACTION==nCode)
Z,2uN!6 {
Wi|.Z/ if((lParam&0xc0000000)==0xc0000000){// 有键松开
CUtk4;^y# switch(wParam)
?,!qh {
O=mJ8W@ case VK_MENU:
:r6
bw MaskBits&=~ALTBIT;
>,y QG+ break;
6D+9f{~r case VK_CONTROL:
t2E_y6 MaskBits&=~CTRLBIT;
K>q,?x b break;
$@<