) I% b- d2 \6 {9 w- v _ 3 b/ O. h% \4 M: f; L4 L+ ` UINT CSampleDialog : : OnNcHitTest (Cpoint point ) * @$ |' o) n& n {$ R1 p4 ? z9 Q: @& ~
UINT nHitTest =Cdialog: : OnNcHitTest (point ) + X4 ^ K7 n, H; |0 W return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest* V6 x D, S9 `- C
}% d1 t1 [! y" A! c
- Y1 o9 V1 g8 [3 m6 p" ]9 S
上述技术有两点不利之处,/ E7 M& s5 A, |8 R3 q) o" f
其一是在窗口的客户区域双击时,窗口将极大;* v) X2 g; ^5 Y+ V
其二, 它不适合包含几个视窗的主框窗口。 3 e# O% x6 p2 o1 C: V0 _& A8 J% m 还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。 % t# X; T; H* m3 b; ]/ S5 I& ^0 ?
( H2 u" b: o2 z4 i, P, h; U& R 5 S3 F* m8 q d* t' \2 E D) |8 C1 k- z/ ^) V+ g/ W
void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point) b" t/ u( @7 g6 n
) 9 m; s/ W# X; x. u+ `2 h6 s0 n {6 u/ q9 Z+ v3 S T( N4 D+ g( ^
CView : : OnLButtonDow (nFlags , pont ), Q% u# O" f M, Q z$ F, o! e
6 @( x, P& |9 V& {8 b
//Fool frame window into thinking somene clicked5 Y, E6 v( r1 a9 C
on0 C0 a( s- r' K# S
its caption bar . ; j" y% _* M& D GetParentFrame ( ) —> PostMessage (" g/ A: _8 G8 {6 i
WM_NCLBUTTONDOWN , 4 G- X: h4 }' O/ e# n- ^/ i HTCAPTION , MAKELPARAM (poitn .x , point .y) ) 2 E8 d1 y3 s6 L. Y" X& e4 U% q" g6 ^' w0 r: @
} 7 o- L- H( @5 r& h4 K8 R1 ?5 M' l' ^. ~/ e8 b y( L
4 R0 b" @" E/ n; u% ]. s
该技术也适用于对话框和基于对的应用程序,只是不必调用, Y& f5 L' ]0 \3 @& {. P8 k( H
7 D4 v/ b3 _/ U5 P2 J
% A& v7 V3 J9 G6 T& z: z' i, G* @1 y w& g! `- u2 [, w; O
+ b |$ t( m+ ^1 i' K4 j
CWnd: :GetParentFrame 。 2 \0 t$ w i; P3 G- K" T void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )/ V+ X4 [( r! u. S' J
{ 3 \5 B0 y' g" q5 b; f. C7 U Cdialog : : OnLButtonDow (nFlags, goint )+ T' L. g7 }" {2 C' S
//Fool dialog into thinking simeone clicked on its$ ~8 C6 `8 c3 l, M, W. F/ a/ @
caption bar .* m" R( K* c. m4 z {) H; C3 v* z
PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x/ [3 t$ k, F5 B* B, E9 z5 k
, point. y1 r; ~# M; X6 W, M7 k. J3 d* ?) t
) ) 0 j# e/ }+ f9 z# {; V, j } S' v5 N) g# M# \
6 Z1 J8 H5 v# o0 v- w+ k
(18) 如何改变视窗的背景颜色 9 I! y, U }# [2 U5 p1 D Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。 0 ^( \. ?; g& p% i# g+ Q; J; v. F7 Y# B7 B' B) C V
1 g5 Q8 y; i$ j" g 7 ~; K7 b( e" [2 }+ P8 H4 `0 A7 ~0 X R4 j L0 U9 i/ x
//Paint area that needs to be erased. 8 k, P6 H5 }3 w3 f5 ^' b+ { BOOL CSampleView : : OnEraseBkgnd (CDC* pDC) 1 d( X @) u t/ P { 6 Y5 z. ]4 q3 D6 R // Create a pruple brush." P/ A% Q6 V5 a& W" ?) c! v. W) c
CBrush Brush (RGB (128 , 0 , 128) )+ x# Q2 v$ d9 n
2 i9 b2 |; B4 b. |, J7 I2 m& E // Select the brush into the device context ./ h' U. s4 N5 K- {# d# D
CBrush* pOldBrush = pDC—>SelcetObject (&brush)8 P* e! N" E. `8 \7 ]
5 F( Z5 e9 W: N- i5 F" h9 s // Get the area that needs to be erased .3 ?) @& X- ^& x! p; l
CRect reClip, S/ }; P' ~+ q! G- p5 B
pDC—>GetCilpBox (&rcClip) % X; V5 l% ]/ W9 y, ? //Paint the area.! |; ?( L% T% l4 \& H& b2 n( {
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY ) 8 f' M* f/ q5 N$ z' Y8 O3 ^+ S2 t& j' r) J
//Unselect brush out of device context .+ G0 F4 J$ E0 P, P% D X4 l
pDC—>SelectObject (pOldBrush )0 T5 X, _7 o; O& `$ b
1 Y& A6 W, E# d
// Return nonzero to half fruther processing .5 @; l8 ?, ^, Z- K$ U) {5 I
return TRUE4 x& ?* [- R5 t/ L& J
} 5 b' R$ y% ^; D, M+ G 6 N# _5 y3 |: M# H4 j& t, T9 p19) 如何改变窗口标题/ k) Y1 s, M: \, v' q
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。$ v/ |7 q" _- U& d3 ]4 C
: @; q) W0 R: f* N+ h3 Q
1 s4 i# d8 b4 i* }' e , y2 v* @+ ^ l1 E0 W4 D# a) v. D6 ?$ R7 D2 p8 h
//Set title for application's main frame window ., c* I |' C) [5 _5 A1 o- c- e1 y- c# c
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )# v B8 \) e! p! B' a* `
8 d7 B' e- {' Z& r
//Set title for View's MDI child frame window .$ Q) z- S9 H; i8 C9 C6 l) y
GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")' Q( K% h6 {2 ^1 M
)' f+ ?% K" l& P5 z& a
- D6 Z/ K3 D0 v0 J) m //Set title for dialog's push button control.' X9 K9 z, u; k: u
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") ); s7 v) H; f1 k6 K8 t) U4 v& W
- b" p' y, @7 w5 Z- w U7 }" X: B. w5 w
如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。- y& t3 _9 h6 X! z1 D
AfxSetWindowText的实现如下:( a# ]0 \5 C; `+ z8 }& @
3 _( a0 t% a2 R2 J1 z; n- Y
( ^0 u- j1 s! D0 P3 x1 Z3 E
2 B* B+ \2 U" |" Y( J4 ?
, Z# |* o2 L0 C; f" w- {5 T
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew ) # V' }2 B5 ]* ]# s3 n3 A. v$ M { ! V+ o( d6 N! x0 z q0 ~% ]/ X itn nNewLen= Istrlen (Ipaznew) " |) E1 o2 U" L/ V6 A* q TCHAR szOld [256], o! c1 \% q3 B1 s( e% f7 o6 O1 x1 h
//fast check to see if text really changes (reduces , G% U# i2 T+ E; K+ H flash in the ' Z5 m& p' w1 b0 d$ {! |8 z8 t controls ) , S6 c9 ~: c @2 Q W if (nNewLen >_contof (szOld) # t9 s- l* ~) \% V4 q || : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen . [: s- b- G! F. L || Istrcmp (szOld , IpszNew)! = 08 x( z9 ?8 F8 n- I. y
{5 @/ j& V! P+ W- z4 T1 U
//change it3 B2 T" p+ ~, t1 D" u! x
: : SetWindowText(hWndCtrl , IpszNew ) 0 C) P k0 Z' g* X } $ g! W- H: |1 k) B( O/ E }% \& _5 d- i7 s5 X/ P
: f0 s' a; c2 ? (20) 如何防止主框窗口在其说明中显示活动的文档名 4 ^" x- G( ^% K& Q: ^7 W 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置) p+ Z2 z1 I H! m8 ` @0 S' Q5 F2 ]/ u
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。7 F" ~$ E; d; X4 F: s; ]
$ q. s+ [: R- p2 Y( y* N2 g$ ~+ d$ K [" m0 p$ P
# W& _8 S- Q1 b3 l% d/ z( v+ ]* z5 @9 v! D5 a+ E1 V" U
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs) # a/ r% r. ]3 p4 j1 P { / u! J0 R) ?0 q8 b, c! T6 R4 T //Turn off FWS_ADDTOTITLE in main frame .$ m/ s, O! O3 b
cs.styel & = ~FWS_ADDTOTITLE O5 M$ R3 b' r* I$ K* w% q return CMDIFrameWnd : : PreCreateWindow (cs ) 2 \ q. ]0 t S+ ^; ^* F! U3 J3 ^ } # S; S' B0 c, @7 ~# n V% H# X0 W% E7 a8 h6 t' f' }& P! T6 k
/ [# u2 w3 y3 u" V: S
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。0 F, h5 k0 n U+ y
/ Y/ c, Y1 w% i# `8 a
(21) 如何获取有关窗口正在处理的当前消息的信息 ' X/ e/ t' C6 f+ ^ 调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。; D- { D7 W; p0 @( F! m
2 f3 q; f1 |3 j, Q( l * J! j( C3 O# f1 W/ v6 B0 {, U 5 v# U, R4 ^5 D( |$ W 2 U; ] L3 m' _* f7 V) L9 H viod CMainFrame : : OnCommmonMenuHandler ( ) # M" d; |0 K w. D8 X {! Z: X( w( K2 J2 j' }% g9 P9 i
//Display selected menu item in debug window . ' _& H! h2 k& ^$ Z( C- H TRACE ("Menu item %u was selected . /n" , ( o2 r% u; R6 L' m 0 L% Q H: N1 J: R/ E% F (22) 如何在代码中获取工具条和状态条的指针 $ e6 U# l& T3 i6 j& m 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: & g6 z0 m% J% K I4 |9 P% w2 Z9 V3 Q; ^4 E+ T/ \1 M
) D, X$ K) k' a* Q) r: W 4 [ Y! z: M' R- M; ` ( G0 P2 U4 H6 G, C h! H0 k //Get pointer to status bar .: @, E5 r: e4 _# \+ L) v9 X
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( ) " p, c9 [8 c; Q8 J( x —> GetDescendantWindow(AFX_IDW_STUTUS_BAR) ) g+ f& i& w; A. D& }" ?- e& O# e4 x5 R* y
//Get pointer to toolbar .0 d2 K1 Q+ [* z% S3 _+ O O
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( ) ; M- x+ F6 ^. @6 X7 c6 P. _+ d —> GetDescendantWindow(AFX_IDW_TOOLBAR)" T9 m. M6 ?# c9 O+ Q
# y$ F& P- c6 }0 M' G
(23) 如何使能和禁止工具条的工具提示1 k1 d+ s" h2 _$ A! \3 X, i
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:/ k$ C e- [. | P
1 Q. ~: p: b) ?& h% r* U. S* _ ) X8 @# V$ N7 S9 \8 x2 Y! w7 s7 v4 e, H4 e, a; C2 G
`/ e" e9 \( H* U9 ]# _: ` w( N
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips ) ) E$ V. u( i$ U( e% W* R- L4 n: @ {% V" G7 m Y( P5 `# \
ASSERT_VALID (m_wndToolBar) : E0 d1 w, r1 M" B! U( U' ^. A4 s& y7 O, K, G
DWORD dwStyle = m _wndToolBar.GetBarStyle ( )5 y9 Y# @# w) q6 J4 l& R
$ }7 n4 Y9 d3 n# o) c% | if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS 9 o0 p7 v" Y u: d& a$ B4 D K7 j* R* W( j$ G' J: B
else * y' y( J1 u8 f: q: L, t6 I% b* W dwStyle & = ~CBRS_TOOLTIPS . X: y! S2 t$ A/ U& z, q2 D; H+ [1 ~+ j% T4 S
m_wndToolBar.SetBarStyle (dwStyle )9 [1 b! D( e8 l$ s
} 7 U: V4 g% t1 b0 \# J , `" C5 g6 G, e3 A(24) 如何创建一个不规则形状的窗口$ m2 O" Q$ M7 u8 T
可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。 2 ]. U9 [( M. C 给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。 9 M N E+ m3 ~3 g4 A! W, i* B 9 |) x7 t- {) p K 9 D# `8 v% D, G1 | }: { ' Y1 S" ]) h& l- G; s# m+ y! f: \0 v8 u
Class CRoundDlg : public CDialog 4 N) ]# i& L& J {; r4 x; i) L; f4 O& Y c
…. C$ ~0 o; P* L0 D0 A+ u: A
private : ) Y1 m8 j: H, M; x Crgn m_rgn : // window region 2 O/ s' I) `; G+ E … ; S: n* _9 Z: |$ J9 W }' S& P+ @) X d& {2 k
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口: ' r: i6 ~) J2 S* k3 L: S- ~: I; { BOOL CRoundDlg : : OnInitDialog ( )8 g% r: a9 U5 U
{ ( W5 ^! C! R; M' T* r CDialog : : OnInitDialog ( ). L: i; _% t, w( E2 g
: Y- y( D5 F9 x8 F+ H
//Get size of dialog .7 ?& B# m: }# \" O7 z
CRect rcDialog 1 F- {" T7 W: E! k! ~; t* z0 M; w6 G GetClientRect (rcDialog ) j0 y3 ^6 g& ~! k( I& |# F- b* h
: u/ P8 D* C: c/ g$ y // Create region and assign to window . - B6 Y2 l" S) K1 F m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )+ O* u2 M! s" b
SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE ) ; F0 _5 ?3 V) N" _9 X 3 a0 b+ |$ d: m: M' W4 a$ M return TRUE9 L B# e) L2 V i
} `8 @' q, |6 y* H# p ) K' Z- c" y. x3 b# { 通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。 + E. `9 ]8 L3 k- Y 9 T1 c5 c: |1 W+ @8 N : \% V( ^0 p8 O$ w. Z) P |5 M2 P( M, [6 q `6 m+ x1 F" E
; {6 z V1 @' F4 U& R voik CRoundDlg : : OnPaint ( )( T$ w' f. w4 @" ^
{ 5 u$ M# H: T. c0 v1 _ CPaintDC de (this) // device context for painting & @1 u) t) Z: e. f . 4 S9 Z' A' B, z //draw ellipse with out any border 3 p+ E5 w2 p$ U dc. SelecStockObject (NULL_PEN)& Z6 }- U! r! K! T5 B3 @* w0 c
//get the RGB colour components of the sphere color, @7 z) x0 }6 n! Y9 h7 N
COLORREF color= RGB( 0 , 0 , 255)6 L$ }) }# r" {
BYTE byRed =GetRValue (color) % l' f. S2 n2 ^( U- ]3 P BYTE byGreen = GetGValue (color) " l- O! B$ h. u0 a; i' h BYTE byBlue = GetBValue (color) 6 J# @) Z1 h3 G8 X& S$ A9 A% r7 S; E% S' z* C+ [9 K
// get the size of the view window 3 r- N$ E/ J* q7 \7 q @$ F Crect rect# p- Z, f% ] `9 @, \8 i2 p( a; K
GetClientRect (rect)4 d$ S* e. r1 x+ _5 a" ?9 {
( p7 m+ A& s! X8 {5 `5 K
// get minimun number of units9 W( \% k) c4 ~( F4 j
int nUnits =min (rect.right , rect.bottom )& _& T& S& q: G* {+ S
3 X+ v2 u0 R6 Q7 x& I. Y6 l/ X //calculate he horiaontal and vertical step size 3 U( _- u/ c' _: J float fltStepHorz = (float) rect.right /nUnits& h6 @! ^; P8 i5 M" }5 [* @" B5 A, `
float fltStepVert = (float) rect.bottom /nUnits6 e7 J0 \. d i3 K/ T0 L# ]
; h3 n7 G0 J) f. W
# |6 O6 g* X: f! w7 ^" E& S int nEllipse = nUnits/3 // calculate how many to3 o' r0 v+ C2 P5 H+ x
draw* A5 Y6 _/ n3 M% \: o: ]; ?4 y7 w( x! K
int nIndex& h; c% l$ i6 |% Z
// current ellipse that is being draw" z8 o6 u8 z% u6 |4 {2 h) l
& \" Y7 u" Z7 s" `9 t CBrush brush 4 R( k8 u6 S3 |8 a0 M$ } // bursh used for ellipse fill color/ i9 x) q7 C# z# e
CBrush *pBrushOld // previous 6 K. ~# Z( S, q' v brush that was selected into dc7 u9 `6 y: |- i* R3 K- j! l1 j
//draw ellipse , gradually moving towards upper-right & R- P$ Y& N& T7 N3 T corner 6 L3 K; o. S, [$ N. k. V for (nIndex = 0 nIndes < + nEllipse nIndes++) # q4 L2 I5 Y# n5 N) i { 8 H$ f5 @' W/ s7 m8 w //creat solid brush 9 x! z2 A: Z5 y brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).2 K. _; p4 i- R2 J
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)5 B( M' n9 u$ @. M: ~% l; o# V5 c1 P
/nEllipse ) ) ) - P( ?; n, B, c, b \, u0 Q& p1 c# f8 o6 Q
//select brush into dc4 A! L, n& O* V$ M) I6 G
pBrushOld= dc .SelectObject (&brhsh)8 t* |& n, W3 X% \; j, ^( }' \# G
# T3 v) |7 e4 T
//draw ellipse 8 i1 B+ X9 v4 k9 m- Z4 [7 v dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex , . L6 @4 O# u6 _8 E* R& } rect. right -( (int) fltStepHorz * nIndex )+ 1, $ V3 q$ b0 z" ]+ X9 J6 o' h rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1) # F5 w& A$ u$ N. C9 Q4 `! l( }' v ^6 D) a% ~) t
//delete the brush - _+ ~7 d, p& Y& t P* p brush.DelecteObject ( ) d) b( I0 q8 I3 y
} $ y0 [) V; V% ?$ n# V/ [8 r X }! y, T& `2 q0 }: @# A
* T* y1 e2 Q1 c1 u3 `2 v( N
最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。 + U) R& J& ?# I( x. r/ n ! }2 ~4 ~% ]& U+ A) `0 P$ K5 j; g+ A( i
2 x/ I- x& l4 r& J7 u7 T6 e+ M/ A + B6 I: ?2 Q3 z UINT CRoundDlg : : OnNchitTest (Cpoint point ): q, j/ \. P4 w; p$ `9 F
{ . V3 X0 l" ?% i9 q' g: G/ U( c //Let user move window by clickign anywhere on thewindow .$ M! R, f1 ^4 b
UINT nHitTest = CDialog : : OnNcHitTest (point)6 }& [( v! }- @# L2 z0 S# o
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest" E3 h) J+ |/ `
- h" U5 Y# n0 o' A" X } * s4 @7 O/ @4 N- y2 c+ |8 }$ l- c7 B; h" K$ r7 Y6 k% i) l# V
(25) 如何获取应用程序的 实例句柄? # {" j: I3 {3 ^' V+ z! T" G! z! s 应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄. 0 l7 f, j( B+ O: ^/ z2 Q& E! K- J8 H- t , s# d, Q2 i8 \" I, K- P 4 ]) T& z" L& T, f 7 R$ _7 y5 p/ ]6 M' ^, P $ @3 }# T1 z1 |( w Example: HANDLE hInstance=AfxGetInstanceHandle() * ~) Z8 f/ \0 c' l- |! P- A% U" P+ D4 }0 p' e( z
(26) 如何编程结束应用程序?+ Z+ _/ f; {' l, i* d, ^' V# ?& j# v
这是个很简单又是编程中经常要遇到的问题.* w6 F& @ M/ Y8 k
向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据. 5 J$ E7 W/ ]$ n2 e" p! C. n0 k* n) v# s4 n8 H2 h; O |
[被屏蔽广告] _" ^ o# M' h
1 i' i! A& r! b" N& I' T 系列文章:VC实用小知识总结(一) 2 h4 c* |6 i" W/ {+ F4 k8 v# s. Y& f9 \/ V- v
1 d4 {3 j( f2 w3 H1 {) S+ D4 p: Z
) g9 z. g: P) P5 U7 p2 S " T! I# e; ~2 Y5 ? Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)1 x: x: s+ Q7 l7 I+ O1 w3 H
7 D/ t, F: _4 a# m" j3 `( z
还可以创建一个自定义的函数 Terminate Window3 `. K& U$ i# G7 ^- V: @
1 y, r3 Y8 P2 P6 Z: I$ r
0 |+ v; `8 z8 L' d- R+ o3 P1 e
7 R2 _8 W. _$ o, _( H$ O2 z( E) @. s, y/ g: v/ T8 t
void Terminate Window(LPCSTR pCaption)5 Y$ u) G7 f8 O* n3 O- p
{ 7 X6 y" c4 I* _7 O9 T- A6 ? CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption) # l \* D' `4 V1 C. O, d- ^/ T) q9 `* }# a/ f$ C
if (pWnd)3 E5 X# L& c9 J6 ^" H
4 @% K$ N3 [* p/ _. O0 z pWnd ->SendMessage(WM_CLOSE) * w Y% n. _+ s6 S$ r5 i } % w" c f+ C6 ?' T3 Q/ Y 5 T Y: c2 G1 L, D, D: b7 { 说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。 6 X6 G, S1 q# F) K- B% U* U+ ]. {; a" v6 H
(27) 如何创建和使用无模式对话框 $ m" W5 S# F0 m MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。 " }0 F9 Q6 v) p! K/ V8 f4 Y' ?; k6 J8 `9 g8 `
+ A6 Q" w4 Q- t0 X# X! U6 E- p5 _ ; R! q# e& b5 b( n/ k' v; v- Y: J9 y" }. Y# T; Z/ b* z
void CSampleDialog : : OnOK ( )# H; S9 ~: `% k! U5 U
{ 3 ~+ _/ ~& v7 k. c // Retrieve and validate dialog data . * P# {, s% n- _) }) `( O+ S# M* x if (! UpdateData (TRUE) ) $ U* u$ U) K! ` f {. d6 ^/ I- m- f& r9 C' w
// the UpdateData rountine9 {8 ^" Q# f! M8 }; B/ Y
will set focus to correct item TRACEO (" UpdateData failed during dialog termination ./n")$ H4 ]4 p$ T8 q( k. f/ I' a
return X2 k$ M( ?4 @( Y) L9 m
}) M' I3 J. _1 w0 o* ~6 @% g( B" p
% C1 G ?$ N P+ y9 ^$ m void CSampleDialog : : PostNcDestroy ( ) & }0 z! l/ f5 L {5 i* [! c6 _+ f* R' x" _/ B, N% O
// Declete the C++ object that represents this dialog.4 U1 K: d" K% d) @1 ]4 l
delete this & R) f4 Y$ N8 Z/ N/ c2 q) e% ?4 l0 ]9 i0 u% v6 q
最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回,' y5 Y. K& d+ B# |7 k7 I9 H+ ?
$ Q" ^$ t) n+ K9 ^. ]; z - l' j$ ]- m% S9 p5 a' p$ T4 v- V ) k4 ]& V6 Q3 F% f- P9 p ( H5 H ^1 z0 A. E/ u7 T void CMainFrame : : OnSampleDialog ( ) , \5 h/ [0 W1 ?$ Z; y$ S4 A { ) t$ _7 H y e- C% d, P //Allocate a modeless dialog object .9 R2 m; X) C9 I
CSampleDilog * pDialog =new CSampleDialog9 b* k0 ?3 m z) L- E2 N
ASSERT_VALID (pDialog) Destroy ( ) ^2 i) e$ k% T8 {0 n% G5 Y$ T, l% ~4 K4 Y9 S# h8 W
//Create the modeless dialog . represents this dialog.' y3 V; [% v. c8 a& G
BOOL bResult = pDialog —> Creste (IDD_IDALOG)/ a* u2 l+ K" i4 \
ASSERT (bResult ) 1 x! j/ b$ u9 {6 U } 3 H5 g2 ?! h! C f) S6 S e7 g! w e( t7 q
(28) 如何防止主框窗口在其说明中显示活动的文档名 9 W3 @" S# z# Q! _* v6 K% m: w5 v 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置" c3 O* H7 w, u- L% a: P
/ [, Y- h4 ?, m4 K! ]. \- e7 S: Q
% Y6 A, @6 \$ X
8 A$ v2 M* c5 J5 S5 f( v E2 w* S
/ u) N4 [+ A9 i
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。 [3 S1 s) c, ]# B
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs) 5 W& j- o: L# z6 i {. h( D7 j& z) V7 M8 q* J+ X/ j
//Turn off FWS_ADDTOTITLE in main frame .5 m. G4 w0 v- v% C4 d
cs.styel & = ~FWS_ADDTOTITLE & ?# n/ w. T# R return CMDIFrameWnd : : PreCreateWindow (cs ), \( R+ ^- d5 P4 n1 U
} ) \" ?- }. B$ s" ]* \/ s) ]9 P- I- R( |" _) X
+ m$ ~: l5 Z9 L& k' t* C$ A 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南 7 r* ]9 ]) `# p! v& T/ Y- s0 q( Q# g, M6 c
(29) 如何在代码中获取工具条和状态条的指针 + b( T, i% c2 X' S 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:5 G* ~& ?6 [/ g3 G6 \# Y; X
- B2 g! a5 k9 j% L. o8 p
/ ]. m, g8 [" R) Y. X " ?$ P) X/ {; ^. O 1 ~. T x/ Z6 G8 e //Get pointer to status bar .% A- F4 h4 ]3 T4 M
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )& _% C( k6 M) z. X" k
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)7 b: m/ ^* W7 B- y0 E; e