在Windows操作系统中,当用户按下"PrintScreen"按钮后,Windows自动将当前屏幕的图像拷贝到系统剪贴板中,这时可以通过"画笔"这个小程序将剪贴板中的内容保存成图像文件,可以看出,如果需要将当前屏幕保存下来还是比较麻烦的,能否可以自己编写一个应用程序,自动将当前屏幕的内容保存到一个图像文件中去呢?这个答案是肯定的,本实例应用程序就是利用通用的热键管理DLL库实现的热键功能,在收到热键通知后截取屏幕的内容并保存到bmp文件中。例如我们设置图片保存路径为c:\,热键为F9 + Control,然后按Change按钮设置好热键,那么当我们按下CTRL+F9后,当前界面将以BMP图像文件的格式被保存在C:\目录下。程序编译运行后的界面效果如图一所示:
TG?brgW
]BZA:dd.G 一、实现方法
f=Gg9bnm3 &|ex`nwc0 热键管理DLL实际上是一个键盘钩子,由它来监视系统的键盘事件。如果有和程序登记符合的按键组合就通知该程序的窗口。为了应用方便,本实例把它做成了一个标准的管理库来为其它的程序通过热键服务,它有两个输出函数:AddHotkey()和DeleteHotkey(),程序只需要调用这两个函数就可以了,如果编译之后不用改变热键,则只需要AddHotkey就可以了。DLL中的所有的全局变量都放在一个共享段中,定义如下:
rgv?gaQ> l
-m fFN #pragma data_seg("shareddata")
w"|L:8 HHOOK hHook =NULL; //钩子句柄
!cLo>,4 UINT nHookCount =0; //挂接的程序数目
a=1@*ID static UCHAR HotKey[MAX_KEY] = {0}; //热键虚拟键码
8.=BaNU static UCHAR HotKeyMask[MAX_KEY] = {0}; //组合掩码, control=4,alt=2,shift=1
=.U[$~3q% static HWND hCallWnd[MAX_KEY] = {0}; //window handle associated with hotkey
q=m'^
,gPS static int KeyCount =0;
<C iSK! static UCHAR MaskBits =0; //00000 Ctrl=4 & Alt=2 & Shift=1
]t,BMu=% #pragma data_seg()
O`\;e>!t @6sqMw} 关于共享段,有几点重要的说明:一是必须在链接选项里指定该段为共享:一种方法是在project->settings->link->object/library中加上/section:shareddata,rws;第二种方法是在def文件的sections里加上一句shareddata read write shared;第三种指定共享段的方法在程序里加上一句#pragma comment(linker,"section:shareddata,rws")。二是所有的变量必须初始化,否则链接程序会把它放到普通数据段。三是如果不初始化变量,需要在段外用"__declspec(allocate("shareddata")) 变量类型 变量名"的方式定义。
|\t-g"~sN 7~p@0)'' DLL中的两个输出函数分别用来添加/删除热键,函数代码如下:
b<ZIWfs PO^ij2eS BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR
'<xXK@=KEI cKey,UCHAR cMask)
"ycJ:Xv49 {
P%VSAh\|n BOOL bAdded=FALSE;
({)+3]x for(int index=0;index<MAX_KEY;index++){
mb3"U"ohs if(hCallWnd[index]==0){
|4zIfAO hCallWnd[index]=hWnd;
cn3\kT* HotKey[index]=cKey;
su(1<S} HotKeyMask[index]=cMask;
rJTa bAdded=TRUE;
F6|]4H.3Q KeyCount++;
1D7`YKI9h break;
[Ek7b* }
o5GcpbZ3k }
(@VMH !3 return bAdded;
LEf^cM=> }
vF+7V*< //删除热键
n\D&!y[]F BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
vX"*4m>b?+ {
uym*a4J BOOL bRemoved=FALSE;
"|
g>'wM* for(int index=0;index<MAX_KEY;index++){
9YyLf ; if(hCallWnd[index]==hWnd){
At>DjKx]O if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
vWv" hCallWnd[index]=NULL;
T2W eE@o HotKey[index]=0;
g2ixx+`?|: HotKeyMask[index]=0;
,V m
< rK bRemoved=TRUE;
hH3RP{'= KeyCount--;
{9pZ)tB break;
L}b.ulkMD }
!hy-L_wL] }
! E5HN :# }
Vwf$JdK%&l return bRemoved;
3M7/?TMw{6 }
Tv=mgH=b uyWunpT W,n!3:7s DLL中的钩子函数如下:
qgHWUwr+n AKfDXy LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
((;!<5-`s {
Eyqa?$R BOOL bProcessed=FALSE;
@n /nH?L if(HC_ACTION==nCode)
b\!_cb~ "@ {
$( kF# if((lParam&0xc0000000)==0xc0000000){// 有键松开
]:- mbgW switch(wParam)
M"Hf :9Rk {
k%#EEMh case VK_MENU:
"Gzz4D MaskBits&=~ALTBIT;
+ GN(Ug'R break;
*OsQ}onv case VK_CONTROL:
_6hQ %hv8 MaskBits&=~CTRLBIT;
;`{H!w[D break;
'GWN~5 case VK_SHIFT:
|aS.a&vwR MaskBits&=~SHIFTBIT;
b. '-?Nn break;
P3=G1=47U default: //judge the key and send message
RSRS wkC break;
3jU&zw9 }
-d/
=5yxL for(int index=0;index<MAX_KEY;index++){
d&Zpkbh" if(hCallWnd[index]==NULL)
yx[/|nZDC4 continue;
7xlkZF if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
Mb}QD~=M {
8kIksy SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);
2@],ZLa bProcessed=TRUE;
ML
9' | }
)2o?#8J }
O8r|8]o }
pah'>dAL else if((lParam&0xc000ffff)==1){ //有键按下
t!l&iVWs switch(wParam)
^[`%&uj!g {
SKN`2[ahD case VK_MENU:
/36:ms A MaskBits|=ALTBIT;
G~a ZJ, break;
{}przrU^c case VK_CONTROL:
&Z@o Q MaskBits|=CTRLBIT;
RbnVL$c break;
N>`Aw^ _@& case VK_SHIFT:
+Kc MaskBits|=SHIFTBIT;
vh%B[brUJ break;
nR~@#P\ default: //judge the key and send message
;igIZ$& break;
c)85=T6*aA }
^{`exCwMx for(int index=0;index<MAX_KEY;index++){
q.bSIV| if(hCallWnd[index]==NULL)
="H`V V_ continue;
:3Ox~o if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
4pF*"B {
!;A\.~-!G SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);
.p[ux vp
bProcessed=TRUE;
"&u@d~`-n }
Wn2NMXK }
^^$s%{ep" }
U7F!Z(
9 if(!bProcessed){ //一般按键事件,为监视键盘的程序留出余地
.`eN8Dl1 for(int index=0;index<MAX_KEY;index++){
C<tl/NC if(hCallWnd[index]==NULL)
!Ai@$tl[S continue;
(w3YvG. if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
qEOhwrh SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
\M^bD4';> //lParam的意义可看MSDN中WM_KEYDOWN部分
~36!?&eA8 }
^ZcGY+/~ }
H7n>Vx:L- }
:5<UkN)R( return CallNextHookEx( hHook, nCode, wParam, lParam );
Bwxd&;E }
oG\Vxg* P=
NDS2 抓图程序是一个基于对话框的程序,它在建立对话框的时候调用前面的DLL,登记热键,因此需要将hook.lib添加到工程里,在程序里给出两个DLL函数的定义,也可以写个头文件,再包含进来以下代码:
O^
yG?b T8$y[W-c BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);
Y:[u1~a BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);
Xx:"4l.w. Y$_B1_ 为了添加应用程序对热键通知事件的响应,程序中用的办法是重载WindowProc()函数,该函数代码如下:
TvbE2Q;/UL rV#ch( LRESULT CCaptureDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
)y$(AJx$ {
k9!{IScq if(message==WM_HOTKEY&&lParam==WM_KEYDOWN)
YS0<qSN {
UCj ld //lParam表示是按下还是松开,如果有多个热键,由wParam来区分
B]tQ(s~ SaveBmp();
e9B064 return FALSE;
26h21Z16q }
b\2
ds, …… //其它处理及默认处理
.Q2V}D85 }
a:w#s}bL &^jXEz; ` Sz}`+E 将屏幕图像保存到BMP文件中的任务是由函数SaveBmp()来完成的,具体实现参见代码部分。另外为了顺利实现屏幕抓图,程序中还实现了"托盘"功能,由于这一部分本书在实例中已经专门介绍过了,所以不再赘述,读者朋友可以参考相关实例。
1yhDrpm ?Ir:g=RP* 最后需要提醒读者朋友们注意的是,源程序的编译与使用时要先编译hook.dll并将其放在系统目录(win2000/NT是system32,98/ME是system),然后编译对话框程序运行即可。
zO6oT1I ]/L0,^RI 二、编程步骤
3Y$GsN4ln D0f] $ 1、 启动Visual C++,生成一个DLL项目和一个基于对话框的应用程序项目,并将两个项目分别命名为"Hook"和"Capture";
=I_'.b ]Y&VT7+Z 2、 在"Hook"项目中导出AddHotkey()、DeleteHotkey()函数;
nxFBI D ?:0Jav 3、 在"Capture"项目中按照图一所示设置对话框的界面,具体设置参见代码部分;
~D>p0+-c >m\(6x8RE 4、 使用Class Wizard在"Capture"项目中添加按钮的鼠标单击消息响应函数,并重载对话框的WindowProc()函数;
8}:nGK|kx -QNh 5、 添加代码,编译运行程序。
]`WJOx4 1'8YkhQ2a 三、程序代码
;O,jUiQ J{G?-+` ///////////////////////////////////// Hook.h : main header file for the HOOK DLL
WcGS9`m/ #if !defined(AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_)
!&E-}}< #define AFX_HOOK_H__AEBFF705_C93A_11D5_B7D6_0080C82BE86B__INCLUDED_
mt.))#1 #if _MSC_VER > 1000
<#4h}_xA% #pragma once
J'r^/ #endif // _MSC_VER > 1000
H\[W/" #ifndef __AFXWIN_H__
Tid a a #error include 'stdafx.h' before including this file for PCH
u*9V&>o #endif
U6s[`H3I{ #include "resource.h" // main symbols
)+Pus~w class CHookApp : public CWinApp
uyx 2;f {
d0>
zS public:
GC'O[q+ CHookApp();
8 Fbo3 // Overrides
\fe]c : // ClassWizard generated virtual function overrides
k9F=8q //{{AFX_VIRTUAL(CHookApp)
\'j|BJ~L f public:
Dvln/SBk virtual BOOL InitInstance();
c:.eGH_f virtual int ExitInstance();
OZ;*JR: //}}AFX_VIRTUAL
/qw.p# //{{AFX_MSG(CHookApp)
RD&PDXT4 // NOTE - the ClassWizard will add and remove member functions here.
m#p'iU*va, // DO NOT EDIT what you see in these blocks of generated code !
9N3eN //}}AFX_MSG
|ENh)M8}r DECLARE_MESSAGE_MAP()
}ad|g6i` };
2J;g{95z LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam);
FN73+-:n:j BOOL __declspec(dllexport)__stdcall AddHotkey(HWND,UCHAR key,UCHAR mask);
$ME)#( BOOL __declspec(dllexport)__stdcall DeleteHotkey(HWND,UCHAR key,UCHAR mask);
3;Fhg!ZO BOOL InitHotkey();
9cm#56 BOOL UnInit();
T[j,UkgGo #endif
5kXYeP3: D1;QC //////////////////////////////////////// Hook.cpp : Defines the initialization routines for the DLL.
?z
u8)U #include "stdafx.h"
Y6d@h? ht #include "hook.h"
{VoHh_[5% #include <windowsx.h>
Y
nZiTe@ #ifdef _DEBUG
<0?W{3NqI #define new DEBUG_NEW
EJ@ ~/)< #undef THIS_FILE
;*&-C9b static char THIS_FILE[] = __FILE__;
7 xa> #endif
#3d(M #define MAX_KEY 100
)\^-2[; #define CTRLBIT 0x04
~u+9J} #define ALTBIT 0x02
L j$;:/G #define SHIFTBIT 0x01
FC"8#*x #pragma data_seg("shareddata")
Wo,?+I HHOOK hHook =NULL;
&
ZB UINT nHookCount =0;
^sg,\zD 'X static UCHAR HotKey[MAX_KEY] = {0}; //hotkey
3oG,E;( static UCHAR HotKeyMask[MAX_KEY] = {0}; //flag for hotkey, value is VK_CONTRL or VK_NEMU or VK_SHIFT
{FTqu. static HWND hCallWnd[MAX_KEY] = {0}; //window associated with hotkey
HUO j0T static int KeyCount =0;
C{wEzM: static UCHAR MaskBits =0; //00000 Ctrl Alt Shift
61
~upQaR #pragma data_seg()
yR.Ong HINSTANCE hins;
Dn }Jxu'( void VerifyWindow();
H 7
^/q7 BEGIN_MESSAGE_MAP(CHookApp, CWinApp)
z&^&K} //{{AFX_MSG_MAP(CHookApp)
c6/=Gq{. // NOTE - the ClassWizard will add and remove mapping macros here.
P
L+sR3bR // DO NOT EDIT what you see in these blocks of generated code!
r!{Up7uL //}}AFX_MSG_MAP
/|#fejPh END_MESSAGE_MAP()
dGTsc/$ Fea(zJ_ CHookApp::CHookApp()
G9@0@2aY8 {
wn)W
?P;k // TODO: add construction code here,
BDZ?Ez\Sg // Place all significant initialization in InitInstance
RY*U"G0#w }
F1Bq$*'N$w O%HHYV%[m CHookApp theApp;
b\+`e b8_ LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
vgN&K@hJ {
w.-!UD9/.x BOOL bProcessed=FALSE;
J!7MZLb if(HC_ACTION==nCode)
b*Q&CL {
LB?u8>a' I if((lParam&0xc0000000)==0xc0000000){// Key up
, SnSW-P switch(wParam)
*siFj
CN< {
wo5
case VK_MENU:
'(jG[ry&T MaskBits&=~ALTBIT;
1 I",L&S1 break;
8|58 H case VK_CONTROL:
TrR8?- MaskBits&=~CTRLBIT;
57'4ljvYi break;
4]}'Hln*U case VK_SHIFT:
d4z/5Oa MaskBits&=~SHIFTBIT;
&~U ] ~;@ break;
"`1bA"E default: //judge the key and send message
;@E$}*3[>V break;
k~FRD?[u }
l0i^uMS for(int index=0;index<MAX_KEY;index++){
5rZ if(hCallWnd[index]==NULL)
4x[S\,20 continue;
.y:U&Rw4 if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
jsi!fx2Rm {
T:W4$P SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYUP);
)p%E%6p bProcessed=TRUE;
w$-6-rE]d }
S#}
KIy }
)q3p-)@kQ }
6<(.4a? else if((lParam&0xc000ffff)==1){ //Key down
fXQNHZ|4 switch(wParam)
}U5yQ%N {
'K,:j 388 case VK_MENU:
UU0,!?o4 MaskBits|=ALTBIT;
8E]F$.6U break;
RhLVg~x case VK_CONTROL:
3I-MdApT MaskBits|=CTRLBIT;
q;)JISf. break;
0v$~90) case VK_SHIFT:
K0Fh%Y4)QH MaskBits|=SHIFTBIT;
s.NGA.]$ break;
WaR`Kp+> default: //judge the key and send message
#$qTFN break;
\6*I'|5d }
hTi$.y!k for(int index=0;index<MAX_KEY;index++)
#|PS&}6wU {
Z!X0U7&U if(hCallWnd[index]==NULL)
KRDmY+ continue;
m$T-s|SY if(IsWindow(hCallWnd[index])&&(HotKey[index]==wParam)&&(HotKeyMask[index]==MaskBits))
&H:(z4/ {
3n}?bY8@5_ SendMessage(hCallWnd[index],WM_HOTKEY,wParam,WM_KEYDOWN);
Bh]P{H% bProcessed=TRUE;
'$zIbQ: }
SQt4v" }
]}2ZttQ? }
!H>R%g#28_ if(!bProcessed){
:1KpGj*F for(int index=0;index<MAX_KEY;index++){
9|CN8x- if(hCallWnd[index]==NULL)
LOV)3{m continue;
.];=Pu^ if(IsWindow(hCallWnd[index])&&(HotKey[index]==0)&&(HotKeyMask[index]==0))
(n9gkO&8" SendMessage(hCallWnd[index],WM_HOTKEY,WM_HOTKEY,lParam);
`~CQU }
HJYScwjQ;` }
]1pIj
i[ }
3fQuoQuD"} return CallNextHookEx( hHook, nCode, wParam, lParam );
Dy8r 9 }
cY. bO/&l ><HE;cVg? BOOL InitHotkey()
l}sjD[2 {
K1!j fp if(hHook!=NULL){
ax5<#3__ nHookCount++;
ur7q [n return TRUE;
ut/=R !(K }
=D#bb<o else
:$BCRQ hHook=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hins,0);
um>6z_" if(hHook!=NULL)
^\&e:Nkh nHookCount++;
_&ks1cw return (hHook!=NULL);
"y/?WQ>,3 }
7CTFOAx# BOOL UnInit()
|3yL&" {
oJ|j#+Ft if(nHookCount>1){
SPmq4 nHookCount--;
a8Nh=^Py return TRUE;
mmRJ9OhS }
=k`Cr0aPF BOOL unhooked = UnhookWindowsHookEx(hHook);
h6`6tk if(unhooked==TRUE){
UVIKQpA]A nHookCount=0;
d-r@E3 hHook=NULL;
1 \6D '/G }
KE3;V2Ym f return unhooked;
eHNyNVz }
\%N!5>cZ{ 6- B|Y3)B BOOL __declspec(dllexport) __stdcall AddHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
):_\;.L {
_1 !OlQ BOOL bAdded=FALSE;
HLaRGN3, for(int index=0;index<MAX_KEY;index++){
(7=!+'T" if(hCallWnd[index]==0){
RxWVe-Dg hCallWnd[index]=hWnd;
K':;%~I HotKey[index]=cKey;
dNL(G%Qj+" HotKeyMask[index]=cMask;
3/W'V,5G6 bAdded=TRUE;
3c6b6 KeyCount++;
4s{~r break;
(uZ&V7l }
wLJ:\_Jaf }
"J8vjr1/ return bAdded;
ZO$m["| }
@Y<bwv ;{tj2m, BOOL __declspec(dllexport) __stdcall DeleteHotkey(HWND hWnd,UCHAR cKey,UCHAR cMask)
x%!s:LVX {
f-G:uI_ BOOL bRemoved=FALSE;
h2J/c#Qvh for(int index=0;index<MAX_KEY;index++){
q0R -7O( if(hCallWnd[index]==hWnd){
.-oxb,/ if(HotKey[index]==cKey&&HotKeyMask[index]==cMask){
?FF4zI~ hCallWnd[index]=NULL;
kw%};; HotKey[index]=0;
mtmjZP(w HotKeyMask[index]=0;
Y^}Z> bRemoved=TRUE;
3L}!RB KeyCount--;
`q*M4, break;
k=JrLfD4 }
T1Z;r*} }
={d>iB yq }
O5kz5b>Z return bRemoved;
8sM|%<$=j }
EL 8<U l@+7:n4K0 void VerifyWindow()
JJ2_hVU {
:hFIl0$,"3 for(int i=0;i<MAX_KEY;i++){
4V i`* ! if(hCallWnd
!=NULL){ _Wq
if(!IsWindow(hCallWnd)){ cacr=iX
hCallWnd=NULL; %'7lbpy,f
HotKey=0; WR yaKM
HotKeyMask=0; yiC^aY=-
KeyCount--; "h a L
} dj7hx"BI
} 7gvnl~C(
} se>8 Z4
} Cdu4U}^H
Za3]d+qm
BOOL CHookApp::InitInstance() Zrk4*/
VY
{ :xv!N*Le
AFX_MANAGE_STATE(AfxGetStaticModuleState()); vK\%%H
hins=AfxGetInstanceHandle(); Y^7$t^&
InitHotkey(); ]X5 9
return CWinApp::InitInstance(); au+kNF|Q
} vV6I0
EwC{R`
int CHookApp::ExitInstance() 33ef/MElD$
{ 6dN7_v)
VerifyWindow(); T| V:$D'
UnInit(); IsM}'.
return CWinApp::ExitInstance(); ]#l/2V1
} o(LFh[
%gyLCTw
////////////////////////////////////////////////////////////////////// CaptureDlg.h : header file {/(D$"j(S
#if !defined(AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_) _c*=4y
#define AFX_CAPTUREDLG_H__97B51708_C928_11D5_B7D6_0080C82BE86B__INCLUDED_ s{S4J'VW
#if _MSC_VER > 1000 M&@b><B
#pragma once f'-i o<.
#endif // _MSC_VER > 1000 aM2l2
;q:zT\A
class CCaptureDlg : public CDialog $M lW4&a|
{ Ax?y
// Construction
$.PuK~}
public: 'y2nN=CN
BOOL bTray; PQnF
BOOL bRegistered; !^=*Jq>
BOOL RegisterHotkey(); ,dov<U[ia
UCHAR cKey; (-xS?8x$
UCHAR cMask; Gh}LlX!w
void DeleteIcon(); Y*>#T
void AddIcon(); =Ja] T~0A
UINT nCount; (\a]"g,]v
void SaveBmp(); W<$Z=(_v
CCaptureDlg(CWnd* pParent = NULL); // standard constructor Z&4&-RCi
// Dialog Data WDc+6/<
//{{AFX_DATA(CCaptureDlg) EQ`(yj
enum { IDD = IDD_CAPTURE_DIALOG }; {G}.b)9FG
CComboBox m_Key; 0Lc9M-Lg
BOOL m_bControl; L z!,kwg
BOOL m_bAlt; jN>{'TqW4
BOOL m_bShift; D@|W<i-
CString m_Path; jR22t`4
CString m_Number; ^ZhG>L*
//}}AFX_DATA fA<[f
// ClassWizard generated virtual function overrides Z!@~>i
//{{AFX_VIRTUAL(CCaptureDlg) v!P b`LCqK
public: /<}m? k\
virtual BOOL PreTranslateMessage(MSG* pMsg); >.'*)@vQi
protected: Nz+949X
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support %Nhx;{
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); ,TPISs
//}}AFX_VIRTUAL g[Ib,la_a
// Implementation ang~<
protected: 65p?Igb
HICON m_hIcon; #H{<gjs]
// Generated message map functions (
Qcp{q
//{{AFX_MSG(CCaptureDlg) "
'6;/N
virtual BOOL OnInitDialog(); /VzI'^
afx_msg void OnSysCommand(UINT nID, LPARAM lParam); #u"k~La
afx_msg void OnPaint(); a1.Ptf eW|
afx_msg HCURSOR OnQueryDragIcon();
HA`@7I
virtual void OnCancel(); 4EZ9hA9+
afx_msg void OnAbout(); *@Y3oh}S
afx_msg void OnBrowse(); W4e5Rb4~f"
afx_msg void OnChange(); \2}bi:e6
//}}AFX_MSG rN<