5 A b u, C% t* g9 M0 b% E: N; ~: c7 [& H$ `) V
6 ?( ] p. N$ n. N; H: f. g0 G
6 h, X2 N' F2 F$ U% {# H s" |- q' X
AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED) $ g2 x1 m- u! E: B //使程序最大化. , |7 O8 E5 K' U S" Q0 Y 2 e& D3 e: g4 t. q (2) 确定应用程序的路径 6 n, b& ]$ a, ^1 r2 q1 _( \$ x! C7 `5 R
7 E: p- B4 m3 X6 y3 G8 S7 S4 _& } 6 f! r0 n9 A* n: m) z1 x0 V' f& V% R G
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。6 E q9 h/ V1 F
Example: / \$ }, W: m( L) i ~ TCHAR $ s% h+ i4 \& k1 ?" J exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧,好象是 : B% g! t* K' P' s 1289 C+ U# j1 Q0 K
GetModuleFileName(NULL,exeFullPath,MAX_PATH) 4 g1 ~3 h! H# }+ ^2 g6 G5 f" P5 F7 e: r+ B! r6 ~
(3) 如何在程序中获得其他程序的 图标? 7 r# _/ \8 \) L8 G2 ]0 E 两种方法:7 V8 f0 `6 Z$ _
(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,; \7 ~/ r! m' a: r5 _6 z
(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.% L* Y: h1 `# m$ D) Q+ P/ _0 a
Example(1): 2 r* P# N, _# o T6 B0 ]* A# l' o 在程序窗口左上角显示 NotePad图标. ( E# J9 K4 x8 \9 \$ @* A) I. q" f( e5 e
; @) O4 q! M9 {# E7 H }% Q, t& P! v* B/ P& M; t
2 A" e9 T/ o7 h: o* p6 g
void CSampleView: , }; r) o k& c$ y OnDraw(CDC * pDC)( e: g' B0 w2 l0 N _ u
{( m& o6 A+ V+ O: V
if( :: SHGetFileInfo(_T("c://pwin95//notepad.exe"),0, 8 `) m: \% I, l$ _5 G &stFileInfo,sizeof(stFileInfo),SHGFI_ICON)) 8 h. T+ Z, H( g9 s/ H) l% U" K { 9 o. g1 ~8 x9 F K/ x) t# E" ]. { pDC ->DrawIcon(10,10,stFileInfo.hIcon) 5 D- S0 w- B2 u& ~ } " w0 X' {* l: D9 A } - E$ q; C/ ]) U. k/ m6 k Example(2):同样功能,Use ExtractIcon Function8 }1 u7 V0 `% T9 u2 t. D( I
void CSampleView:: OnDraw(CDC *pDC) 0 _5 z1 H: A' `6 R1 v {% c) @4 D# B7 R7 M
HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T8 _$ `2 v5 O, l3 J( b( A# x
("NotePad.exe"),0)* ]7 @+ S3 o' O, u8 w
if (hIcon &&hIcon!=(HICON)-1) " I7 _6 H$ F/ w pDC->DrawIcon(10,10,hIcon)4 G0 L6 t# X/ ?: _" J' w9 @
} 5 ?% x& w+ E* p: } 6 H: \7 T; z2 N: M5 M( b! A3 D2 B, s! c% r+ I
说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点. t/ x$ n( c5 u1 s8 I
6 r0 q% I$ T2 B8 M7 e (4) 获得各种目录信息, q- J9 a; s" U; b8 ?" ]
Windows目录: Use "GetWindowsDirectory"8 H6 H! E! D. i) k4 k' N
Windows下的system目录: Use "GetSystemDirectory" 5 h# p5 E- V/ [2 I temp目录: Use "GetTempPath"& r/ k$ {4 O# h
当前目录: Use "GetCurrentDirectory" / {8 i3 K2 c9 ^& x. f- p 7 ~6 q1 F; w& y* t3 @ 请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反. ; j. R0 `1 ~% c, {5 Y, G: F. E; C, I( k3 q
(5) 如何自定义消息 # u$ X# z8 D, `: i 1) 手工定义消息,可以这么写( k, o8 N7 o8 u3 w' i
" p' F( Q5 _, W
# y1 q6 E4 \. j: `: w9 e- z
2 ~, ^2 ]1 g( O
+ A% l3 p) A R) V) w! ~* M6 k: [ #define WM_MY_MESSAGE(WM_USER+100), 0 K* p! G0 y" R2 N U/ U . ?0 I/ C- h" m" p7 R5 M0 ~& m2 j
MS 推荐的至少是 WM_USER+100# g! e& H6 j6 i% G" q# L8 A
. L* @3 a0 {- E! g
(2)写消息处理函数,用' q; [ ]* p7 a, _4 d5 S. M7 |$ X
6 I6 ?+ G) L& W8 S+ n) {9 W
# C) u- _( ]9 L9 V- N, _9 N2 r/ Z8 _1 S
void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point % N3 ]8 C2 X3 p4 ~$ g2 I; Z ) 6 j% k; _" _! C+ C$ r0 [0 Z# x {5 E3 z$ f. z; S& X$ u' |1 @
CView : : OnLButtonDow (nFlags , pont ). p4 _: u$ j6 W# ~9 p
+ C+ H4 H6 x# p //Fool frame window into thinking somene clicked6 D1 U8 w! Y& P/ Z8 o" x1 w# @
on# I) G+ L0 \. L. C H3 l
its caption bar . " d- s: u7 y% f3 ?/ @+ V: w# ?4 O GetParentFrame ( ) —> PostMessage ( {) Z# S5 G1 x% M% Y7 @ D6 y
WM_NCLBUTTONDOWN , : g. i# u* ?# b! C; I7 w; z HTCAPTION , MAKELPARAM (poitn .x , point .y) ) 6 j% i9 D, [' e) w6 [ . y( A; t+ E, _2 y# G3 \2 A; Z } . U0 x8 W" K5 s l% {' u0 q% W' s, L+ M/ `' S
3 n( P! Y& _" j" \" P 该技术也适用于对话框和基于对的应用程序,只是不必调用 # S5 Y, N9 B @ D( T2 k) L - m& U: k) g3 \2 a9 _" o7 q* M3 g2 \* }
) L( z( A. \$ E# M1 s+ h/ b( F) H; N2 ~: ~/ W
CWnd: :GetParentFrame 。 Q7 L5 _( l2 w* t* I void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )' M. N* Z& W. X# l- B$ o; {
{; N/ p! T: f2 j/ r
Cdialog : : OnLButtonDow (nFlags, goint ) 6 }' k* G( e8 t* n7 k/ Z% h0 t //Fool dialog into thinking simeone clicked on its* j. ?' k* M* ]4 o1 T* w
caption bar . : {6 u) y/ o6 | PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x 2 H% N& p* U9 A" B: p- v , point. y 6 Z; v. m2 N1 r1 F ) ) ; |% J8 @/ v! V1 m* K9 p$ O } 7 ]' }( M+ L5 ~* k* l' y/ s- x' h, I- x* k' j0 Y( M/ U
(18) 如何改变视窗的背景颜色 7 w# R# K3 r1 u/ N1 e. o1 Q Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。 0 u5 @' ^7 {4 Y' c8 ? \ ( }" y7 B. a/ W" _ # h" G3 z$ d; I( p* f6 s! z% J( p4 G2 \
. }! l+ `# O2 i. m //Paint area that needs to be erased.2 M8 S m( P/ k
BOOL CSampleView : : OnEraseBkgnd (CDC* pDC) 0 g5 D7 p* H! j1 Q" r {- S M3 h5 F- T
// Create a pruple brush.3 y. K8 ]1 }) }- Z+ z" J- l9 |
CBrush Brush (RGB (128 , 0 , 128) )/ X: I$ s1 }# C1 I
+ O7 L7 w) a* K" W // Select the brush into the device context .- x; E% h/ U% F, E
CBrush* pOldBrush = pDC—>SelcetObject (&brush). V: z1 v/ T) w" o
! s% ~% w4 `9 w4 I // Get the area that needs to be erased .' _$ `. Q8 q5 G4 ]" b: N( b
CRect reClip * q( a6 L+ o) F1 @+ N pDC—>GetCilpBox (&rcClip) . }2 g, J9 u5 \! ?" X! N) h& B9 l- M //Paint the area.0 f. I+ b' B0 f+ a! S
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY ) + F B% P8 a* m5 F/ V0 M& |& e# L9 |5 t. N6 D: F1 k& J- E" q+ G
//Unselect brush out of device context . 9 ^% s( e2 ?7 h! S pDC—>SelectObject (pOldBrush )8 w* Z0 b! w7 X% @2 Q( S+ A
/ @$ q: j/ \3 [: H$ `" | W/ j // Return nonzero to half fruther processing .7 a7 ^: h, x5 Y! b0 a. G4 o
return TRUE ; {8 N8 U3 P" o2 s3 w5 z9 `+ ?8 O } 7 @# N8 G5 B; v3 g) @& ?2 ~/ y( p1 [$ Y
19) 如何改变窗口标题: B6 A, D; V$ j ~3 D
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。. E9 T, Y9 m% x8 } I& F
! }6 o) m! q y3 C& [ / f9 N+ T- ~- X) B+ j+ i6 ]3 R! \% o; h! _& c2 N
3 Y, k g) \. F8 J; Y+ B1 ?' s9 P' E
//Set title for application's main frame window ./ M# N% r d8 Z& W) l
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") ) ) [6 F7 ~+ N' T% H 0 U+ M* Q! r9 C3 ?& K //Set title for View's MDI child frame window . ! z3 O( A0 c7 u4 n' F: a# O GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")+ j! B( ^5 z2 W: B4 E: Z
) 4 }8 z0 S4 ~2 X' X0 _2 a) m }9 u% w/ X% Y8 u //Set title for dialog's push button control.2 H& R. i. }5 V3 ^" h% q b
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )' T) F. B4 u( a: T
, m5 d2 ?8 @2 w2 Z0 e( @7 L
a- f; ?0 a' [1 `3 O: B 如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。 0 u/ [/ h* X) X2 q- Z7 Y! I# ` AfxSetWindowText的实现如下: 1 W, ~$ b4 @, x1 ] u 3 Y) l) {0 E3 w- r: w; f! v - p7 A, |1 g: {4 N; H' T5 o. n- K, B
" \; T. Y( `5 Y" f+ D voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )8 H3 s9 F+ _- r7 a- R
{ , B# h/ S1 L( s1 n5 ?3 r+ @. r itn nNewLen= Istrlen (Ipaznew) # j) s, W. @6 m. ? TCHAR szOld [256] 6 U9 C3 V6 \0 p% E1 b //fast check to see if text really changes (reduces5 V; L' H3 ?: ~1 c0 ~, @" e
flash in the 6 E F e7 k( o2 j9 U controls )+ M+ M; s7 q9 b4 P! I
if (nNewLen >_contof (szOld)7 ]8 S) B9 o0 T/ E7 `! g
|| : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen3 y; S6 U) \# M3 P" l* ]
|| Istrcmp (szOld , IpszNew)! = 0 0 J2 c& m V( n { 1 q+ b- e2 s: M J //change it ' Q0 `! O- M7 ~; L' g : : SetWindowText(hWndCtrl , IpszNew ) $ Z- V8 K+ C2 X) i8 r, v/ F }: r5 D4 e; h! r- \1 v$ @3 g
} ! Z8 }& n# X# w( h% o* e8 ` ' U. @1 F$ G+ H H, ]. }5 [4 G; [ (20) 如何防止主框窗口在其说明中显示活动的文档名 / |( l2 C7 B- B4 c 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置9 \) E. x5 b5 k: [
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。 2 c0 g) D- S) V- b9 d5 k9 C, D3 X+ W9 [' p# w$ B
; T0 _% U* {6 U. f
/ I, q; w% l: P6 D0 O* g2 i & x# I0 I; w B6 T# _8 f* b, m BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs) . j1 ~% s) I3 v2 Z2 y {. M& D5 `, e* L: l1 W7 @& D
//Turn off FWS_ADDTOTITLE in main frame .' R4 g( a: T" w3 q% I
cs.styel & = ~FWS_ADDTOTITLE 5 }9 m. V) \! u$ M l
return CMDIFrameWnd : : PreCreateWindow (cs ) 0 V e1 K7 J# P } ( f+ |7 K: m% @- t+ a: H 7 @, G4 o5 A/ [' b9 R @5 `5 u5 k2 E" c, n
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。& {( [# S5 j& h$ I$ t
0 m& o8 v: m& \9 q# J: k. D: B) A9 | (21) 如何获取有关窗口正在处理的当前消息的信息0 @0 _7 \( k0 H# |" S
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。 2 c6 P6 b5 M; [' C- s' S 1 o3 O9 P2 ?- P! I& C- I* p& \3 M8 x * O* H2 F& U# N9 s9 k8 K- _( u" T& Y+ P/ l6 ?, v' T7 u9 M3 p
, g M4 c U9 F ]4 U
viod CMainFrame : : OnCommmonMenuHandler ( ), c4 ?' ?' C) T2 ~+ m& N. h
{ 0 A) c7 K: F1 r //Display selected menu item in debug window . 5 r: P5 g. b. D" _ TRACE ("Menu item %u was selected . /n" , 0 z$ p( g; O1 y, m! H5 e9 d) h 6 p; G7 ^- |( V3 V# R3 e, e& P- j (22) 如何在代码中获取工具条和状态条的指针 : i4 Z/ D! Z& P/ A6 s" m' {% y8 I 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: , I3 O0 e5 [4 e3 x+ T: q2 T- @! V' t- Z% e- H. m8 b; ]+ v) S
: u. Z) _0 b7 s, {2 z% |& V# w: v( \/ o" m+ p* @$ ^" F9 k
2 Y! b6 |" g$ Y b
//Get pointer to status bar . ) g6 r, `. X3 M8 [ CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( ) # d% {9 l2 A% p" q —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)7 H, q. U* {! ?* U- ]
8 _) s: T+ z9 I! D //Get pointer to toolbar .( N+ R( i" P0 n7 ?3 o
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( ) ; o/ k6 }9 e( T/ s2 m, X9 | —> GetDescendantWindow(AFX_IDW_TOOLBAR) t+ E$ n z; ~ ! [" n( V4 |% b5 [6 u; ~, R (23) 如何使能和禁止工具条的工具提示4 Q- Q; i6 U) x* P8 h ^, O- P
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数: : Y: O, Z6 ~; o' b" j. M& K/ z . z+ p8 B, L& ^- ~3 ?2 ] 2 }) a {% [- d6 Z/ _3 S! H! ~) C, L/ N3 F5 @* e$ f
% G8 @8 H J* ?% q' I6 i2 n4 Y void CMainFrame : : EnableToolTips ( BOOL bDisplayTips ) 1 v0 O- Y& B* ?: A { % h9 w$ B( ^: Y) G: s$ W: j ASSERT_VALID (m_wndToolBar) L( ]! A9 d0 w/ L$ o# w5 F- W- t1 \: I- d% f
DWORD dwStyle = m _wndToolBar.GetBarStyle ( ) % L6 {- \/ a' Z" v- l; F, J: n3 A" g# p4 ^4 S# `# Y
if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS: \5 C4 w! C0 y* L
3 x9 h7 c8 h; v voik CRoundDlg : : OnPaint ( ) 2 R7 }; o3 {: \+ q2 r {3 `4 h9 ^9 E0 R* t" }/ l
CPaintDC de (this) // device context for painting( T5 }' x8 K8 R. G* _) D- C4 Y; W
. * E4 b6 W& B3 R) U //draw ellipse with out any border " W+ P, _$ m; D$ e! R: ]- G; e dc. SelecStockObject (NULL_PEN) 6 z* G2 E) t @, p; H //get the RGB colour components of the sphere color % U. W/ Y3 R/ E9 y/ V COLORREF color= RGB( 0 , 0 , 255)9 {% U' |. T$ A8 [; r3 A$ D
BYTE byRed =GetRValue (color)1 H0 w, e0 J2 q! P; ^8 a! z
BYTE byGreen = GetGValue (color)8 g$ r5 W- Z: J2 V- t
BYTE byBlue = GetBValue (color)4 H! v, O, Z2 Y% l$ x2 z7 p; v
! C4 M4 F; ^0 H# T% ^2 V4 c // get the size of the view window3 F2 {- n- d+ f5 ^4 B. j5 `
Crect rect ! E- _* b; n5 J7 i GetClientRect (rect)# J" }/ U! j8 j) X
& _0 \# K, X" v6 e // get minimun number of units / A$ S% S5 c, s. G& t int nUnits =min (rect.right , rect.bottom )3 ?% ~7 x3 U" G9 i
& r2 m3 {6 P d8 X( @' D
//calculate he horiaontal and vertical step size 0 g0 v3 r, S; y0 C* n float fltStepHorz = (float) rect.right /nUnits2 K6 g* z/ W' P( [3 }, K" ?
float fltStepVert = (float) rect.bottom /nUnits4 s3 v6 |4 I/ D L
' Z2 {% G% X8 V3 e& \ . N2 R3 Z' `" N( D6 _ int nEllipse = nUnits/3 // calculate how many to $ T* x& O! [' d* U, o; z4 X draw c, M4 O2 X' c. j* ~6 ?( L) K( |
int nIndex3 J, @; m) q# W8 ]0 y3 I# w
// current ellipse that is being draw: }2 w' K2 x- S2 r& v' G4 }! n
' z( }# n7 d" Z9 D7 b+ x+ F
CBrush brush, J+ L5 I* n# j
// bursh used for ellipse fill color1 v0 `$ r+ _$ i: I
CBrush *pBrushOld // previous" }) r3 F1 g. ?( A
brush that was selected into dc 1 N$ v- ~( n X2 _ //draw ellipse , gradually moving towards upper-right 8 Y1 J3 z( ~8 n& x7 W2 v; T, V corner 5 k8 n1 D% e( {0 ] for (nIndex = 0 nIndes < + nEllipse nIndes++)% b$ @/ \) {2 g4 K0 M5 Q
{ 9 p9 l8 V5 Z9 t9 f: n+ @- ] //creat solid brush. ^5 B, q& G1 g0 U1 v4 H
brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).& b, }% Y( @1 e9 O0 p% s8 q
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)* v6 l' H& a( e1 e1 L9 F
/nEllipse ) ) ) - a5 _8 N9 Z/ Z, x$ B+ m+ G , A. t! F7 P, @4 D% N2 x V8 n //select brush into dc/ }5 z! ~9 O8 G5 X
pBrushOld= dc .SelectObject (&brhsh), D4 Q% x7 D: ^1 A
n V! L8 i! B! W //draw ellipse 5 z( E% p9 ^/ D$ c' B, |5 q# p dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex , 0 j- K+ O* u5 k rect. right -( (int) fltStepHorz * nIndex )+ 1,4 h3 r* `5 p3 L% L' L$ t5 w
rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1) 3 T% E! o* U$ u' @% v: u; g1 a/ L& Z2 _1 U
//delete the brush ! G# f: o. _) U# s; ?, U* x0 b brush.DelecteObject ( ) . c5 ]8 ~9 z. ^" i! ]5 M7 T" W* F } ' a, h3 M) ~; `" Q6 ^ }- z" T {, W, r
5 q6 H8 {7 D' P. ~6 t0 h 最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。$ i. |- D) d, S7 [* `! b. w7 Q O
* K# G( ]+ Q1 c+ u1 d( S1 r" @
' r6 {$ C* N' Q
$ h q0 e" ?7 |5 b4 `7 C
5 F( I/ T* m m7 {! H2 J9 _ UINT CRoundDlg : : OnNchitTest (Cpoint point )1 r7 k9 i0 b& ? l4 c
{ 4 K1 k/ I% C% a) S: K$ b //Let user move window by clickign anywhere on thewindow .3 g9 S% m1 ^5 Y
UINT nHitTest = CDialog : : OnNcHitTest (point)# I9 a5 D, x$ b9 [: D- G. v
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest 4 G; A( H5 v9 c( m; S ; t& ]% }3 x; C; p0 |! v4 O. I9 S } 3 {. [. S1 y3 u8 [ V7 z/ s, x2 Q, ~( b. a% z3 y- t: @ (25) 如何获取应用程序的 实例句柄?9 ~# D$ f3 g5 a! @- T/ a" `2 s
应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄. 1 }# J3 G$ @' {, p; n& m" }6 ?8 G/ q2 s
/ [+ }& g: ]8 C3 ~- b* S6 b ) R% Z5 x6 |( d; g/ \- M : {( L3 u' Q3 b. U Example: HANDLE hInstance=AfxGetInstanceHandle() 3 r* F9 |+ b* V' l/ S, H# _: k+ w( @, D8 T' j
(26) 如何编程结束应用程序? 2 E' E* g) F9 Y: A 这是个很简单又是编程中经常要遇到的问题. ) p. @; m7 {' R4 H; E' V 向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据. . D& H# q X( D8 j. q' ^ , ^( M4 K. t1 [# y[被屏蔽广告]/ Q% t5 Y) _" o1 @
N! i, [! d0 B- D9 W: u! A% G7 c / U' B& {9 Y' S$ p/ R% c8 d" j+ y1 q( o, e2 c8 @
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)7 o5 u; V, u7 N# R: _- f( n7 O# d
5 Z% |/ e+ Q; J0 F' d
还可以创建一个自定义的函数 Terminate Window % C6 Y$ ~( ~( {- u3 `; C/ r- ]7 H5 @: f
! p2 B5 r& \% H4 _0 O; n7 l: ]0 k
% p; ^. s0 c- F* U void Terminate Window(LPCSTR pCaption)& M: A: w0 C: P2 [/ _) |0 k l% A
{( ~' v2 G% y- q% a9 v) @, ~
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)+ W4 a3 N3 d( \6 |
. r W) N3 d( q5 @1 B* D
if (pWnd) 6 X1 v9 ^# V& \1 s" g3 a9 f. _- J 5 U) v+ E1 ^7 X0 E pWnd ->SendMessage(WM_CLOSE). ^2 ?( W* a/ e5 p/ G
}% j- _/ W! d1 G7 l5 d
6 O) W% o5 D8 o; }0 q4 W
说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。. w; X: P2 a* f ]1 h/ q
% T" x$ G% `4 |0 a. }" n# Y% H
(27) 如何创建和使用无模式对话框 6 a* ]3 s6 G6 O/ n) B+ l3 ]+ u% ] MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。 V1 b2 p" [8 j. h ! Q! R) ]1 o, ?, u- S1 G6 b V& J% ~. ?& n, K, Y/ G
7 b% w( I/ |0 s/ D( u) M1 C! m
) U- o) ` _% c" ]( q% d7 k5 _1 a# r void CSampleDialog : : OnOK ( )1 c+ g' p. p/ c1 M) Y' S! ^8 `) z
{! a& I L: V" k0 N
// Retrieve and validate dialog data .( y3 `. K9 I5 c( T, v
if (! UpdateData (TRUE) )$ w S& N+ J1 b n
{' N" \/ n7 I; s! ?6 p! k8 d
// the UpdateData rountine ( m2 x Z$ O2 b a2 \! a' z will set focus to correct item TRACEO (" UpdateData failed during dialog termination ./n") 9 l6 f& j. S" r6 B% M3 [2 h- A, W return4 @3 @7 }* P+ |& ]- l
}2 z1 N* t9 G: l! v, b6 h% u% {1 U l
! C* V7 _4 ?/ r# x //Call DestroyWindow instead of EndDialog . - ~: s9 F& E% J* S8 C+ x: Q7 J5 o DestroyWindow ( )9 F! T1 C ~ F. _9 M- e* u S
}$ U+ N2 \( b; M
+ c1 J4 s9 H z void CSampleDialog : : OnCancel ( )6 g0 x6 @: a: G
{ . o; s9 t2 q% J' ?7 ]0 G( P //Call DestroyWindow instead of EndDialog . - F; L) {( ^5 @/ P% S DestroyWindow ( ) : e( u( t" s' B: n6 r j } ( i2 K- M) f" k) h4 `6 o2 f* a+ P0 N; x7 r* i4 V/ ~9 H. G7 H
其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。 ! Q0 F8 b0 q' d% C' f2 L' f- M3 Q4 U: P) B# V1 k) w& a, Y
( T- U# x- w( Z7 A% F" ~
+ i7 _% `/ ]* o- j" n, `
: `0 f) P- \ P9 ? void CSampleDialog : : PostNcDestroy ( )5 s* B) N5 |2 N% I; d0 y
{( j5 h8 [* S3 B" g0 D/ E2 b5 n
// Declete the C++ object that represents this dialog.. `8 J/ g8 ]6 ?1 B) h$ D+ S: p
delete this 4 K/ \4 S% f I0 Q4 J' X2 a) N4 A4 j: w+ k) ?; D( w; @
最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回, ! C r4 D) G6 Z+ S& h ) F8 o& u6 A$ Y8 i2 D0 X% G9 J, B( H, o7 [! b( R
9 F J% G$ y& y$ q0 v6 z8 U
' D/ ], S4 \* a |# P m void CMainFrame : : OnSampleDialog ( ) # H q( w6 P0 e/ x: i2 h! ]8 G { 2 S% [2 h9 [' n- |* ]2 _$ U% A; Y //Allocate a modeless dialog object .9 x" ~2 Q+ ^5 X9 ]
CSampleDilog * pDialog =new CSampleDialog " l, k8 s O n |! _5 K ASSERT_VALID (pDialog) Destroy ( ) z6 B/ W8 ^+ ]" H' D" X3 q+ }
9 J/ H9 ]" r! ?5 P# X$ ~; b' }! O) o //Create the modeless dialog . represents this dialog. ' }9 J* d8 i* H$ g+ r. t BOOL bResult = pDialog —> Creste (IDD_IDALOG) D" T5 c( z: C9 q2 [5 k
ASSERT (bResult ) ( K3 a4 |4 G" b/ k9 k/ p+ ~0 z }& c, r/ P9 [2 P" L$ e8 A) m
7 w, |4 ^4 s" ]3 ~/ I/ E6 I, K# F9 E (28) 如何防止主框窗口在其说明中显示活动的文档名 % t# R! ?5 T# H9 \4 u; T. d; m 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置 " T. }( n2 o3 K$ g+ |( W : `6 `2 |( q4 g2 L8 @) B6 j7 G3 i$ l
+ U% T2 @, o% \( U8 ~5 ~1 t1 |5 m' e % U: ?1 P/ t2 X1 [0 X CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。 ! O* e( @5 _0 A s* c* z. [( q BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs) 1 \: v4 [; p0 M4 [! t {3 B. ^4 G U% m% q4 G7 W5 H
//Turn off FWS_ADDTOTITLE in main frame .& ^; J- X: \1 @6 y4 C' N
cs.styel & = ~FWS_ADDTOTITLE 1 L6 t) \4 r+ A% M return CMDIFrameWnd : : PreCreateWindow (cs ) * f$ S! a# I+ S8 D0 `& l* b* n }/ @; v* Q6 R/ v$ S) _% i+ U6 i3 W