在Windows操作系统中,当用户按下"PrintScreen"按钮后,Windows自动将当前屏幕的图像拷贝到系统剪贴板中,这时可以通过"画笔"这个小程序将剪贴板中的内容保存成图像文件,可以看出,如果需要将当前屏幕保存下来还是比较麻烦的,能否可以自己编写一个应用程序,自动将当前屏幕的内容保存到一个图像文件中去呢?这个答案是肯定的,本实例应用程序就是利用通用的热键管理DLL库实现的热键功能,在收到热键通知后截取屏幕的内容并保存到bmp文件中。例如我们设置图片保存路径为c:\,热键为F9 + Control,然后按Change按钮设置好热键,那么当我们按下CTRL+F9后,当前界面将以BMP图像文件的格式被保存在C:\目录下。程序编译运行后的界面效果如图一所示:
=/QU$[7X(
7O9hn2?e 一、实现方法
Sc$8tLDLj ?&<o_/`-H5 热键管理DLL实际上是一个键盘钩子,由它来监视系统的键盘事件。如果有和程序登记符合的按键组合就通知该程序的窗口。为了应用方便,本实例把它做成了一个标准的管理库来为其它的程序通过热键服务,它有两个输出函数:AddHotkey()和DeleteHotkey(),程序只需要调用这两个函数就可以了,如果编译之后不用改变热键,则只需要AddHotkey就可以了。DLL中的所有的全局变量都放在一个共享段中,定义如下:
IgR"euU p vQK6r #pragma data_seg("shareddata")
<6O_t,K] HHOOK hHook =NULL; //钩子句柄
bb/?02*)H UINT nHookCount =0; //挂接的程序数目
grxl{uIC8 static UCHAR HotKey[MAX_KEY] = {0}; //热键虚拟键码
S O:V|Tfj static UCHAR HotKeyMask[MAX_KEY] = {0}; //组合掩码, control=4,alt=2,shift=1
m5em<P!G static HWND hCallWnd[MAX_KEY] = {0}; //window handle associated with hotkey
9C)3
b3 static int KeyCount =0;
SM#S/|.] static UCHAR MaskBits =0; //00000 Ctrl=4 & Alt=2 & Shift=1
FJ(B]n[> #pragma data_seg()
m":SE? {{& X*9N[#wu6 关于共享段,有几点重要的说明:一是必须在链接选项里指定该段为共享:一种方法是在project->settings->link->object/library中加上/section:shareddata,rws;第二种方法是在def文件的sections里加上一句shareddata read write shared;第三种指定共享段的方法在程序里加上一句#pragma comment(linker,"section:shareddata,rws")。二是所有的变量必须初始化,否则链接程序会把它放到普通数据段。三是如果不初始化变量,需要在段外用"__declspec(allocate("shareddata")) 变量类型 变量名"的方式定义。
8u'O`j W
aGcoj DLL中的两个输出函数分别用来添加/删除热键,函数代码如下:
P&%eIgAOL hN_f h J BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR
#W%)$kc cKey,UCHAR cMask)
c(V=.+J {
%w8GGm8^/ BOOL bAdded=FALSE;
uQu/(5 for(int index=0;index<MAX_KEY;index++){
)o9Q5Lq if(hCallWnd[index]==0){
v"~Do+*+ hCallWnd[index]=hWnd;
6vgBqn[ HotKey[index]=cKey;
Zv| p>q`R2 HotKeyMask[index]=cMask;
Z<ajET`) bAdded=TRUE;
4g7ja KeyCount++;
%h" qMs S break;
cZgMA8
F }
7Y32p' }
4N~+G ` return bAdded;
Lvi[*une| }
+:> J Z$
//删除热键
JvfQib BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
3duG.iUlL {
,jRcl!n` BOOL bRemoved=FALSE;
LZM,QQ for(int index=0;index<MAX_KEY;index++){
iUI y,Y if(hCallWnd[index]==hWnd){
a#+>w5 if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
6x_T@ hCallWnd[index]=NULL;
20UqJM8Ot HotKey[index]=0;
q]6_rY. HotKeyMask[index]=0;
?0rOcaTY bRemoved=TRUE;
>*dQqJI KeyCount--;
!TP6=ks break;
)?w&oIj5 }
4E=0qbt8 }
4K9Rpm }
N%9h~G return bRemoved;
~->Hlxze'K }
G HD^%)T5^ |l|_dn $ph0ag+ DLL中的钩子函数如下:
#B @X x*.Ye5Jb LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
j2|XDOf {
"~u_\STn < BOOL bProcessed=FALSE;
~~PgF"v if(HC_ACTION==nCode)
:GQUM 6 {
u8Y~_)\MA if((lParam&0xc0000000)==0xc0000000){// 有键松开
ZCm1+Y$ switch(wParam)
Wk@
eV\H71 {
&Hv;< case VK_MENU:
$ye^uu;Z MaskBits&=~ALTBIT;
;}LJh8_ break;
VS?dvZ1cC case VK_CONTROL:
81Z4>F: MaskBits&=~CTRLBIT;
B4Q79gEh= break;
EMLx?JnP case VK_SHIFT:
9"~9hOEct MaskBits&=~SHIFTBIT;
D%-{q>F!gf break;
j"5Pe default: //judge the key and send message
<}d/v_+pnh break;
R1}IeeZO?& }
yI8 SQ$w0y for(int index=0;index<MAX_KEY;index++){
OR]T`meO if(hCallWnd[index]==NULL)
E*BSfn&i continue;
L?!$EPr if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
Q uB+vL {
Q:mZ" i5 SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);
lr WLN bProcessed=TRUE;
Jy9bY }
l^P#kQA }
lX"b N=E?! }
+@0TMK,P else if((lParam&0xc000ffff)==1){ //有键按下
\^LWCp,C" switch(wParam)
Km,*)X.-5 {
8W;2oQN7 case VK_MENU:
=L"^.c@ MaskBits|=ALTBIT;
=`-|& break;
ZRnL_z~ case VK_CONTROL:
[(|^O>k8c MaskBits|=CTRLBIT;
UFe(4]^ break;
i}B;+0<drx case VK_SHIFT:
Lj8)'[K" MaskBits|=SHIFTBIT;
ZHCr2^w6
break;
Ea4_Qmn default: //judge the key and send message
2U}m RgJu break;
kh3<V'k] }
|g<* Rk0
for(int index=0;index<MAX_KEY;index++){
! RPb|1Y}+ if(hCallWnd[index]==NULL)
Iq^if> continue;
@DuK#W"E u if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
A " S/^< {
\gItZ}+c4} SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);
i.y=8GxY bProcessed=TRUE;
_ij$f< }
EY=FDl V }
7)^:8I( }
i)8N(HN if(!bProcessed){ //一般按键事件,为监视键盘的程序留出余地
#f*g]p{ for(int index=0;index<MAX_KEY;index++){
>&WhQhZ3kg if(hCallWnd[index]==NULL)
,."b3wR[w continue;
F\:(*1C if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
/ZW&0E SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
wzh]97b //lParam的意义可看MSDN中WM_KEYDOWN部分
L\e>B>u }
f8'MP9Lv }
FRZs[\I|iT }
'e@=^FC return CallNextHookEx( hHook, nCode, wParam, lParam );
Yp1bH+/u }
*5OCqU+g c2 *`2qK# 抓图程序是一个基于对话框的程序,它在建立对话框的时候调用前面的DLL,登记热键,因此需要将hook.lib添加到工程里,在程序里给出两个DLL函数的定义,也可以写个头文件,再包含进来以下代码:
qaVy. !VP %v&jKm BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);
T5|c$doQ BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);
r&%.z*q ^$-Ye]< 为了添加应用程序对热键通知事件的响应,程序中用的办法是重载WindowProc()函数,该函数代码如下:
s+Q;pRZW{ k6(r !mc LRESULT CCaptureDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
y&oNv
xG- {
g%a|q~) if(message==WM_HOTKEY&&lParam==WM_KEYDOWN)
ys'T~Cs {
g=l:cVr8y //lParam表示是按下还是松开,如果有多个热键,由wParam来区分
iiG f'@/ SaveBmp();
syPWs57pH return FALSE;
QI}E4-s8 }
aWy]9F&C: …… //其它处理及默认处理
JObMZA$ }
uD9|.P} 7dOyxr"H- zt=0o|k 将屏幕图像保存到BMP文件中的任务是由函数SaveBmp()来完成的,具体实现参见代码部分。另外为了顺利实现屏幕抓图,程序中还实现了"托盘"功能,由于这一部分本书在实例中已经专门介绍过了,所以不再赘述,读者朋友可以参考相关实例。
%Dig)<yx <>Y?vC 最后需要提醒读者朋友们注意的是,源程序的编译与使用时要先编译hook.dll并将其放在系统目录(win2000/NT是system32,98/ME是system),然后编译对话框程序运行即可。
&dR=?bz-A iv&v8;B 二、编程步骤
q,%:h`t\ cz/Q/%j$/ 1、 启动Visual C++,生成一个DLL项目和一个基于对话框的应用程序项目,并将两个项目分别命名为"Hook"和"Capture";
z[EFQ^*> yT8=l"-[G 2、 在"Hook"项目中导出AddHotkey()、DeleteHotkey()函数;
+jP~s WYrI |^[> 3、 在"Capture"项目中按照图一所示设置对话框的界面,具体设置参见代码部分;
6#e::GD lfN~A"X 4、 使用Class Wizard在"Capture"项目中添加按钮的鼠标单击消息响应函数,并重载对话框的WindowProc()函数;
JC#>Td .S?pG_n]f 5、 添加代码,编译运行程序。
p'94SXO_ RA O`i>@ 三、程序代码
&miexSNeF +iO/m ///////////////////////////////////// Hook.h : main header file for the HOOK DLL
!>z:m!MlQ #if !defined(AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_)
beXNrf=bG #define AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_
:6{`~= #if _MSC_VER > 1000
)ChqATKg #pragma once
^U[D4UM #endif // _MSC_VER > 1000
*|#T8t,}n #ifndef __AFXWIN_H__
Vz=auM1xZ #error include 'stdafx.h' before including this file for PCH
TX [%(ft #endif
^dm!)4W #include "resource.h" // main symbols
u3 0s_\ class CHookApp : public CWinApp
xiblPF_n3 {
Jc6R{C public:
{eS|j= CHookApp();
dt}_D={Be // Overrides
9W ^xlid6 // ClassWizard generated virtual function overrides
Ro(Zmk\t //{{AFX_VIRTUAL(CHookApp)
6NWn(pZ]p public:
pah'>dAL virtual BOOL InitInstance();
|>^JRx virtual int ExitInstance();
\*?~Yj# //}}AFX_VIRTUAL
G~a ZJ, //{{AFX_MSG(CHookApp)
]s'as9s9 // NOTE - the ClassWizard will add and remove member functions here.
Q3~H{)[Kq // DO NOT EDIT what you see in these blocks of generated code !
Nh|uO?&C6 //}}AFX_MSG
; DR$iH-F DECLARE_MESSAGE_MAP()
t{9GVLZ };
#zs~," dRv LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam);
;igIZ$& BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);
c)85=T6*aA BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);
^{`exCwMx BOOL InitHotkey();
.~;\eW [ BOOL UnInit();
Sz`,X0a #endif
RtS+<^2a; ? OM!+O //////////////////////////////////////// Hook.cpp : Defines the initialization routines for the DLL.
!f[_+CD #include "stdafx.h"
@,+5y\]C #include "hook.h"
H*R"ntI?w #include <windowsx.h>
q54]1TQ #ifdef _DEBUG
tDcT%D {: #define new DEBUG_NEW
90rol~M& #undef THIS_FILE
=UQ3HQD static char THIS_FILE[] = __FILE__;
Btn?N #endif
7n<{tM #define MAX_KEY 100
!Ai@$tl[S #define CTRLBIT 0x04
j,eo2HaL #define ALTBIT 0x02
Zu[su>\ #define SHIFTBIT 0x01
_V6ukd"B~ #pragma data_seg("shareddata")
b8UO,fY q HHOOK hHook =NULL;
wn%A4-%{ UINT nHookCount =0;
p6V0`5@t static UCHAR HotKey[MAX_KEY] = {0}; //hotkey
$6 f3F?y7 static UCHAR HotKeyMask[MAX_KEY] = {0}; //flag for hotkey, value is VK_CONTRL or VK_NEMU or VK_SHIFT
^ZcGY+/~ static HWND hCallWnd[MAX_KEY] = {0}; //window associated with hotkey
{!L~@r static int KeyCount =0;
/([kh~a static UCHAR MaskBits =0; //00000 Ctrl Alt Shift
;)*eo_tQ #pragma data_seg()
%tGO?JMkd HINSTANCE hins;
^yp{32 void VerifyWindow();
N4!O.POP BEGIN_MESSAGE_MAP(CHookApp, CWinApp)
Ti5-6%~& //{{AFX_MSG_MAP(CHookApp)
6H$FhJF // NOTE - the ClassWizard will add and remove mapping macros here.
-Q*gW2KmV // DO NOT EDIT what you see in these blocks of generated code!
O^
yG?b //}}AFX_MSG_MAP
24eLB?H END_MESSAGE_MAP()
q0vQa ,f>k%_U} CHookApp::CHookApp()
Y:[u1~a {
*GPiOA
a // TODO: add construction code here,
Vc Z3
X4/ // Place all significant initialization in InitInstance
#X1ND }
|Rk@hzM2S 0GeTSFj CHookApp theApp;
WOap+ LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
TC*g|d @b {
#*Ctwl,T BOOL bProcessed=FALSE;
3s#N2X;Bc if(HC_ACTION==nCode)
y<Ot)fa$ {
F]&*ow if((lParam&0xc0000000)==0xc0000000){// Key up
+mn[5Y} : switch(wParam)
q/,O\, {
X \/#@T case VK_MENU:
NBGH_6DROw MaskBits&=~ALTBIT;
kuP(r break;
sXPe/fWo case VK_CONTROL:
)SGq[B6@I MaskBits&=~CTRLBIT;
{`@G+JV~Jw break;
|CyE5i0 case VK_SHIFT:
4kx
N<] MaskBits&=~SHIFTBIT;
[4f{w%~^ break;
j\M?~=*w default: //judge the key and send message
@o`AmC.
8 break;
> ~O.@| }
Gd85kY@w7 for(int index=0;index<MAX_KEY;index++){
JWxwJex if(hCallWnd[index]==NULL)
gPPkT" continue;
RA
L~!"W if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
@q)d {
lThB2/tV\ SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);
[7y]n;Fy bProcessed=TRUE;
8":Q)9;% }
SmO~,2= }
K}Qa~_ }
WpvhTX else if((lParam&0xc000ffff)==1){ //Key down
%pCTN P switch(wParam)
es7=%!0 {
&oMh]Z*: case VK_MENU:
"w<#^d_6 MaskBits|=ALTBIT;
kAUymds;O break;
ef4 i:. case VK_CONTROL:
~P-mC@C MaskBits|=CTRLBIT;
CrTw@AW9) break;
p!%pP}I case VK_SHIFT:
G3T]`Atf MaskBits|=SHIFTBIT;
|[8Th4*n break;
9\(|
D# default: //judge the key and send message
Q3?F(ER@ break;
p]c%f2E>d }
;O,jUiQ for(int index=0;index<MAX_KEY;index++)
hhvyf^o {
4*;MJ[| if(hCallWnd[index]==NULL)
%?/X=}sE continue;
dWBA1p if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
m1A J{cs {
om>KU$g SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);
Y'X%Aw;` bProcessed=TRUE;
E]r?{t`] }
H\[W/" }
1$ {SRU7l }
Tlr v={ if(!bProcessed){
f|(M.U- for(int index=0;index<MAX_KEY;index++){
(/]
J3 if(hCallWnd[index]==NULL)
u ^RxD^=L continue;
klhtKp_p if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
TA~{1_l SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
<~=Vg }
],].zlN }
%&bY]w }
e+K^Aq return CallNextHookEx( hHook, nCode, wParam, lParam );
*Pg2c(Vg }
93hxSRw 2:ylv<\$ BOOL InitHotkey()
ybUaTD@?}b {
e96k{C`j0 if(hHook!=NULL){
TL#3;l^ nHookCount++;
NGW xN8P6 return TRUE;
R G`1en }
;A[Q2(w+ else
jz0T_\8D` hHook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
U/BR*Zn]* if(hHook!=NULL)
#e5\j\#. nHookCount++;
T[j,UkgGo return (hHook!=NULL);
u#SWj,X }
F6dP,( BOOL UnInit()
ct}9i"H#1 {
"zy7C*)>r if(nHookCount>1){
LreP4dRe nHookCount--;
`9.r`&T6K return TRUE;
.%QXzIa3F }
uW3!Yg@ BOOL unhooked = UnhookWindowsHookEx(hHook);
v*yuE5{ if(unhooked==TRUE){
7VI*N)OZ8 nHookCount=0;
$,'*f?d hHook=NULL;
5/z/>D; }
{1
94!S4z return unhooked;
}o{(S%% }
&
ZB s"?3]P BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
3oG,E;( {
{FTqu. BOOL bAdded=FALSE;
ws^ np for(int index=0;index<MAX_KEY;index++){
PnG-h~Y3N if(hCallWnd[index]==0){
GvlS% hCallWnd[index]=hWnd;
;6hOx(>`= HotKey[index]=cKey;
$u6
3]rypm HotKeyMask[index]=cMask;
gltBC${7wZ bAdded=TRUE;
YT8F#t8 KeyCount++;
ua `RJ break;
1g~R/*Jo }
Nl1Do:PY }
kz7(Z'pw return bAdded;
'$QB$2~V }
K 'I#W
lg pcI uN BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
;IM}|2zuN {
qb` \)X]9 BOOL bRemoved=FALSE;
:T(|&F[( for(int index=0;index<MAX_KEY;index++){
,wdD8ZT'Ip if(hCallWnd[index]==hWnd){
Lq!>kT<]! if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
m9}P9? hCallWnd[index]=NULL;
B^jc3 VsR HotKey[index]=0;
@gXx1hEg HotKeyMask[index]=0;
8qu6. bRemoved=TRUE;
^L&iR0 KeyCount--;
lCHO;7YHX break;
5d!-G$@ }
&XUiKnNW }
1 I",L&S1 }
% +\."eC return bRemoved;
VTHH&$ZNq }
(0kK_k'T sds"%]rg void VerifyWindow()
@49S` {
6Sn .I1Wy for(int i=0;i<MAX_KEY;i++){
`,*5wBC if(hCallWnd
!=NULL){ 8BNi1Qn$
if(!IsWindow(hCallWnd)){ hqkz^!rp
hCallWnd=NULL; _``=cc
HotKey=0; I4?5K@a
HotKeyMask=0; r^ ZEImjc
KeyCount--; GF=g<H
M
} \mlqO[ S
} T:W4$P
} Jma1N;d
} S#}
KIy
fZA4q0
BOOL CHookApp::InitInstance() fXQNHZ|4
{ FH+s s!
AFX_MANAGE_STATE(AfxGetStaticModuleState()); 1|-Dj|
hins=AfxGetInstanceHandle(); by/jYg)+
InitHotkey(); "wh ,Ue
return CWinApp::InitInstance(); XACm[NY_
} 'F#KM1s
lQkQ9##*
int CHookApp::ExitInstance() n^6j9FQ7
{ 0b(N^$js'
VerifyWindow(); Z!X0U7&U
UnInit(); dL
)<%
o
return CWinApp::ExitInstance(); t |A-9^t'!
} j]/RC(;?
"o}+Ciul
////////////////////////////////////////////////////////////////////// CaptureDlg.h : header file 3
xp)a%=7
#if !defined(AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_) I83<r 9
#define AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_ ]yPqLJ
#if _MSC_VER > 1000 QbpFE)TYJ|
#pragma once X1vd'>
#endif // _MSC_VER > 1000 ]1pIj
i[
+pn
N!:q
class CCaptureDlg : public CDialog 0T5L_%c
{ B%+T2=&$7
// Construction /HRFAqep
public: )iK6:s#
BOOL bTray; bYQRBi
BOOL bRegistered; 9.B
KI/
BOOL RegisterHotkey(); ':m,)G5&
UCHAR cKey; 8k1Dj1@0z
UCHAR cMask; JQHvz9Yg
void DeleteIcon(); gi
_ 5?$
void AddIcon(); `
3K)GA
UINT nCount; :^3LvPM
void SaveBmp(); g0ly
CCaptureDlg(CWnd* pParent = NULL); // standard constructor i3'9>"`
// Dialog Data T\>a!
//{{AFX_DATA(CCaptureDlg) k%QpegN
enum { IDD = IDD_CAPTURE_DIALOG }; l u%}h7ng
CComboBox m_Key; 9kS^Abtk
BOOL m_bControl; &t:Gx<]
BOOL m_bAlt; :I^;jdL
BOOL m_bShift; x-.?HS[
CString m_Path; <.izVD4/Gg
CString m_Number; t+T4-1 3a
//}}AFX_DATA 2/=l|!JKLz
// ClassWizard generated virtual function overrides 6 EC*
//{{AFX_VIRTUAL(CCaptureDlg) @;?p&.W`D
public: J B]q
virtual BOOL PreTranslateMessage(MSG* pMsg); '|p$)yx2
protected: Bj-:#P@
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support @x'"~"%7b
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); y0.8A-2:
//}}AFX_VIRTUAL c*L\_Vx+
// Implementation 6){]1h"
protected: Tl[!=S
HICON m_hIcon; Vi]W |bP
// Generated message map functions 3L}!RB
//{{AFX_MSG(CCaptureDlg) 'yG4
LF
virtual BOOL OnInitDialog(); }"PU%+J
afx_msg void OnSysCommand(UINT nID, LPARAM lParam); yS(fILV
afx_msg void OnPaint(); usK*s$ns
afx_msg HCURSOR OnQueryDragIcon(); /-+xQn]
virtual void OnCancel(); r@t9Ci=}
afx_msg void OnAbout(); jiS_G%G
afx_msg void OnBrowse(); bITPQ7+
afx_msg void OnChange(); g<f <Ip=
//}}AFX_MSG ?+W9az]+
DECLARE_MESSAGE_MAP() VZymM<