$ j7 Z' Z- s" V! Q8 N m_nCmdShow=SW_SHOWMAXMIZED //最大化% D8 k% L0 f& s9 e, \- b
m_nCmdShow=SW_SHOWMINMIZED //最小化# v3 h3 P1 W7 N
m_nCmdShow=SW_SHOWNORMAL //正常方式1 z% b9 f/ E0 ]- G& x
3 B0 D( t( q+ i6 W" W/ G- ` MDI窗口:2 I3 f/ N* o, P: `& ^
如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE6 G) z P" N* b+ y0 F- j) A( X, |1 Z
) \3 [; T0 t" |% r; B" J
如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。 9 K8 Q, Z }+ s ) v- O" n8 z3 ?; f9 B( y (10) 如何限制窗口的大小?/ O: e: j, a) V$ {4 w8 v
也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码: 3 ~* N, a& b5 J) Z( _& ~: Z4 l , ^$ G5 z" L5 J (11) 如何使窗口不可见? " O" }% i1 V& o+ _ 很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow控制.8 X. o5 Y; F* m3 Y, y7 K
" b$ k4 n0 Y3 ^8 K
(12) 如何创建一个字回绕的CEditView : D% J' J; N( a6 H6 X 重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。 . ?' z$ c. U) r7 v. p/ D; O+ G5 w4 F3 }( }5 f' ~
7 z: G) e3 r2 B6 D, h8 J5 f( u' ^/ l- v1 y2 F
! W( c0 e$ X9 E
BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs) , d( l5 ?& d5 f/ | { 5 P. P: J% F0 H/ T4 v //First call basse class function .& z- M) _- G" Y/ r( Q/ l; ^; L
BOOL bResutl =CEditView : : PreCreateWindow (cs) " X$ ~2 w! D( D N |+ B3 R8 H& A% F8 m* u# H/ k x1 {0 O$ j
// Now specify the new window style .: h: o2 C7 L9 q: j: E! f
cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL) * I4 Y% S0 M9 S! B W/ u1 B' D return bResult : d5 Z& |3 f& v+ p: i3 {: n) M } f7 e. ~$ Y0 b$ P9 O' M
' S! w; j5 w; s; l( y, E# o5 j+ i4 A (13) 如何使程序保持极小状态?- n- z( S$ j' Y7 a! y& I
这么办: 在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数3 H' w+ D, m+ m* q$ d! Z. X$ D
$ y0 w- k: r" F5 c) ^, Q
* G9 a9 B( B7 }9 L" s3 K
& m `7 ~& r* F$ P0 H
% Y( Z, N; p; d$ N4 I( r; B OnQueryOpen() ,add following code:, T# [3 o" O1 c' `9 M1 E
2 Q, @( j6 y8 }$ C+ o3 p
Bool CMainFrame:: OnQueryOpen( ) + w- b+ f( F* R/ n6 X { . S& S; t7 q( E1 n, | Return false ' y. ^, Z7 N( [0 e" Z& |0 a }4 ]5 P5 r& ]0 a. Z( W* \
4 i/ E* T) w( U" s2 I$ | (14) 移动窗口' b: Q! O& {; y, T
调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。 O5 k8 H* u' V( a) u / u5 A2 T6 F4 M/ Y* Q& o1 v& B! s; {; L
6 J3 Y5 g% _$ u7 \* z
1 j" [" Y- f- E
//Move window to positoin 100 , 100 of its parent window .: h2 b/ G2 E1 N. S$ A; Y) ?7 X
SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)1 u) ?; z2 {3 h' G' k
3 F7 }: _2 {6 x7 ?8 x2 c- q (15) 通用控件的显示窗口 1 H. W. j( b+ z) [( [ MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。2 o0 V& H3 |3 @$ H2 ~5 P
$ Y9 [( g+ Z Z: t, y(16) 重置窗口的大小 # Z+ V2 E& j) y$ l1 i7 i& a 调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。9 Z. i+ F( C. N$ W* r7 c
. B c. R3 `. T( ?) ^" m' u - c. e" [3 ]5 C n$ ?/ R6 z. t) a6 G6 w# w
& V" w" k" K. F
// Get the size of the window . N5 Q8 ?$ c# F Crect reWindow ) l! n5 Q* i8 `+ r* x- I2 G! J GetWindowRect (reWindow )( M; I4 z9 P1 O* c @7 Z
% v* `- B6 A9 V- k% o' i //Make the window twice as wide and twice as tall . 1 P! s: E1 Y8 U, O% @ SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2, ( S# ^+ `3 [" S9 Q! c2 L6 Y" v. C% c, I3 W6 d% U# x9 K
reWindow . Height () * 2, 1 L+ w4 T1 h5 F SWP_NOMOVE |SWP_NOZORDER ) ) p/ z d: j6 ~( b" j $ ]- k" M+ b K0 z (17) 如何单击除了窗口标题栏以外的区域使窗口移动 # S2 j2 ]! R7 x& a 当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。" g0 l0 O& s0 |
. `# ]; e3 E/ t. q7 k2 r
1 O9 R" R$ {6 D; n
) ^# h1 k# R P$ a8 t* [% U9 K6 ^$ I" ?
UINT CSampleDialog : : OnNcHitTest (Cpoint point )# A3 {9 K6 w5 V
{0 @! E1 C* h7 ?# J" c9 D
UINT nHitTest =Cdialog: : OnNcHitTest (point ) 1 @4 J4 @; m; f) Z; C' J return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest 5 a% @, L3 Z8 X }' w0 u9 g5 L% X# F
* V9 _1 j1 ^' v; \4 Y
上述技术有两点不利之处, k( x6 K6 ~* r; V: q9 d1 [ 其一是在窗口的客户区域双击时,窗口将极大; % Q: o ~1 w( N5 C; r 其二, 它不适合包含几个视窗的主框窗口。5 S# j5 f/ C4 z% a. U7 i- k
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。4 a4 t- K0 f2 b' n# A
4 @* c2 B% y; O
0 H/ V% D- F0 s8 O5 R. s/ U
- c& `, O* K% D
0 o$ L+ }0 w- e& i0 n2 Y void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point 3 N4 `, E1 ^* v1 x$ J& J ) " ~( y Z. r; R, ^, ]4 [ {0 S; ~+ d1 [3 v }+ C% A
CView : : OnLButtonDow (nFlags , pont )5 H$ u; d/ D- _1 A- h* S
! ^+ t3 C3 J" ^1 Z" C5 H3 f7 l. } //Fool frame window into thinking somene clicked 7 g7 ^6 q3 I8 W! i on8 j; |/ l2 Y5 w' _, {& _" Y
its caption bar .4 T: Z3 V+ l$ d
GetParentFrame ( ) —> PostMessage ( + u5 O9 \2 S! z1 h8 d) o4 ] WM_NCLBUTTONDOWN , , f% [. O5 c) r4 G( {. P. S& O HTCAPTION , MAKELPARAM (poitn .x , point .y) )5 ?+ F2 S0 z1 W. G: Z: K
: M* R) R) P, g3 D
} # ?* u% W+ Z& w* q$ X) o( O) N$ ]( C 6 x7 B" L! k! L/ @* T+ @3 k 3 i, ]+ w# ~: b 该技术也适用于对话框和基于对的应用程序,只是不必调用- T$ V# u$ u" K G2 S
8 s' g% t3 e( b$ C. O/ J/ s Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)" S9 j9 j0 ]% _& V0 r9 n
& b5 I1 l0 v b4 q3 M
还可以创建一个自定义的函数 Terminate Window % i: J9 h4 [0 o# z" n 6 l3 Y, b' ^7 j, ? ) I% d( R, s3 V1 z ! _( O$ i7 p5 q% g' l4 q) Q" j! B8 w3 y) J6 J+ f
void Terminate Window(LPCSTR pCaption)" p4 }4 z: w0 t4 K
{ , ^# e1 C, V" K* x CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)0 U! a0 D L' a8 b
' [* E, f" K3 T- n& E( r" q
if (pWnd) # K8 e4 m3 ]2 S$ T& d+ N8 {2 g. ]5 t: \9 Z' @: j7 `! H! m: f. Q3 {+ ^
pWnd ->SendMessage(WM_CLOSE)* z% l0 M, J. g/ ?2 f! ~
}1 t$ N' ] Q$ }) t C9 {
) Z: {/ B* L6 |8 t& a2 u
说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。 - z N2 U# f: R( z4 ]4 \5 ]6 Q& e: o+ i1 R2 o8 W; m* }
(27) 如何创建和使用无模式对话框& f! m) V6 a' d n0 h0 Y
MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。 . ^+ ^7 b" ?8 R% l/ w; w, U* u9 L1 W
& I& m5 J* Y$ [& k: i8 t z
5 u J% N: b! E4 _ $ e+ \9 s1 R5 `- o+ ~9 j0 o6 k5 z; H void CSampleDialog : : OnOK ( )2 _4 P# p( A ?6 {1 ~/ f* X& n
{ 0 G: X5 u3 V% i; h; b/ k // Retrieve and validate dialog data .3 B: W5 e2 }0 @1 z! S3 L
if (! UpdateData (TRUE) ) 8 x: S! z/ z7 f. ~$ A, q+ j {- f0 W* b+ i8 s) q9 T
// the UpdateData rountine 5 K2 [& O* E" G6 ~/ n will set focus to correct item TRACEO (" UpdateData failed during dialog termination ./n"). d# y% M* w! o! `( T
return 3 z M" `7 Y D5 { } + Z3 q- o2 t; \ o4 m0 S: k/ Q. S* B4 w+ p8 m" i- b) h
//Call DestroyWindow instead of EndDialog . 3 e# J4 a9 w8 l DestroyWindow ( ) 1 ?; C2 t- C) N1 N3 C* K5 [ } # |% a) O$ v( \2 p ( H* k' U7 r k$ L void CSampleDialog : : OnCancel ( ) & T6 q. v% R+ U6 `( x { . t3 L6 x H4 e3 z% d0 ~ //Call DestroyWindow instead of EndDialog .4 v, I. U0 e% g5 {9 N
DestroyWindow ( ) , `3 ?: X$ O7 P+ @+ c } + U1 P/ K" T6 g" v0 r& u. g' ^8 U9 E" b% n
其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。- m( U8 {5 \/ }* B4 w
% U+ Y5 L1 B4 }7 O: m" E
% L6 [5 ?7 S1 y1 c+ r - T; C+ ?: Z- P0 `6 ] ; {4 q2 s* [# m; t void CSampleDialog : : PostNcDestroy ( )% T- h$ a3 x7 p }- v- l
{6 H3 g. `: g2 e* H0 }/ E
// Declete the C++ object that represents this dialog. 1 }8 J0 L" r+ N* I- p9 \6 }/ B delete this, G- E# L7 Z! @
6 k5 [ g. H" i
最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回, 6 L" a0 K8 G6 P4 d& r+ D6 h8 J5 ]: T7 S+ m. \3 |% o8 t: a
6 D- E' u8 \: j5 |: R/ o
. h4 G: C' z: y- M: B ]* C
9 ~) l, r& q' Z6 w
void CMainFrame : : OnSampleDialog ( )0 N& j) F+ _9 n
{ " w/ s3 ]4 i3 s" H" B I& w* f4 ^ //Allocate a modeless dialog object .5 |; G6 _% h2 d9 Q! B$ V
CSampleDilog * pDialog =new CSampleDialog2 v) H& e' t! V+ V
ASSERT_VALID (pDialog) Destroy ( )5 o$ t! W# l1 ~: z; l
( i; s V( e2 l //Create the modeless dialog . represents this dialog.0 [7 y7 N. P% t3 z, U* m* z
BOOL bResult = pDialog —> Creste (IDD_IDALOG) $ d6 i8 g' w$ l$ I _/ F; H ASSERT (bResult ), u9 z- a* d& J& J" _: S1 F
} : k. M. H+ [/ C' ^2 y5 M, ]# f# q6 c# H s- e3 z
(28) 如何防止主框窗口在其说明中显示活动的文档名( R/ v. U, j' i9 l, j( }% j2 ?
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置) @) m* v2 _" |! v& z4 W. }
7 [" I5 M* ?8 b9 |' X( v8 C) h+ m
5 S9 t. }: d, ^; Y! z: y
+ M" M; M3 Y. S: s2 X4 T+ U9 G # z( g$ w5 |) g! J CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。! i1 }" W1 ^: ~! t
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs) 6 |# s; L( {% p) M9 K { ' t: f9 B6 t9 S) c! P //Turn off FWS_ADDTOTITLE in main frame .8 |2 y5 E; m; U8 d
cs.styel & = ~FWS_ADDTOTITLE , p/ g4 Q/ {+ P. g8 ~& {% G return CMDIFrameWnd : : PreCreateWindow (cs )# V1 t# j0 ]. P! h$ d
} 9 K% w8 u: x/ i% g0 w3 L: f# K# m+ M% k+ m7 W% N
- } Q7 G6 k% Y1 y0 L, I3 y 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南+ T$ P' o, f# }; o5 s8 o
- _: \: H. s) Y0 z
(29) 如何在代码中获取工具条和状态条的指针* W: E& F2 Y, q7 D% ?. s
缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:% \( e. S: a2 S: L9 n' Z
9 ~6 ]4 [3 d! t4 O9 o 3 X$ e+ g' u7 R+ B0 |6 L2 K: X8 I) r; l6 B& B" m: v1 \
8 z' w7 f! K6 S! i! Y/ w! Z
//Get pointer to status bar .: T& h& t/ e. d1 l, c4 P
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( ) ; B4 d4 |' ^; @9 ]$ ~) l9 p —> GetDescendantWindow(AFX_IDW_STUTUS_BAR)1 A7 {" H% M" ]- K
7 W( `7 @" Z1 {% r }
//Get pointer to toolbar . ! ?: I n3 K/ b/ [ CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )! d" I5 T! b0 e1 B! P- n
—> GetDescendantWindow(AFX_IDW_TOOLBAR) 8 p5 l% B$ b9 O! e# E3 d) P$ p+ D. q' Q% l& W4 ^* I, e
(30) 怎样加载其他的应用程序?) V' a4 P' M4 B/ j& C" \2 i
三个SDK函数 winexec, shellexecute,createprocess可以使用。 - H0 `, b2 D6 Q3 Y0 R# d I WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。 ' e4 R6 S- u# {# P. B* T. H+ U2 |, }, \" ]3 `4 b1 B: p
ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:/temp/1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.) R4 R4 J3 w& \% k% q1 A
F' z. }7 M+ p- }! r2 c6 T3 Z" O. ?4 x 1 `% \* x; m1 w: A/ P* {3 B8 Z , h+ X+ J) Z/ g( `2 g 7 B+ F& H$ |! ]; n- x0 | ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED)" j1 M, i) w- ^+ x& n; X( `! a9 j
X: }# Y/ O: k& j3 y" K
CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:+ k- A" E: ^& v6 B' ?4 `
# h3 `1 w. b8 Q. s* M8 z
# z, D1 J4 ]2 ?& z" l7 L/ t8 Z3 i
4 B+ u5 j" L. Q7 |1 a* {0 `- a/ }' a3 z ! X) D5 J! c% d( D2 p4 F STARTUPINFO stinfo) f% d1 s2 p3 Z( ~8 K0 B
//启动窗口的信息9 {- t) f0 Y( T6 N# Z9 E% ]
PROCESSINFO procinfo //进程的信息 % I/ {) w2 [& d5 j" d/ B/ v- O8 E" x4 t
CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, e% p) C, t$ Z+ b
NORMAL_PRIORITY_ - x: g2 b' i; ]+ Q+ r5 c . ?5 r+ c7 o2 M2 e CLASS,NULL,NULL, &stinfo,&procinfo) 5 {( _4 }2 N$ X, v & X; D( c7 N, B (31) 如何在代码中获取工具条和状态条的指针" Z4 S+ P' [' x- p/ B% C+ C5 @" g
缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:, ]$ B- ^: Y: o- K2 O# h; ~