8 v/ Q- G1 ^# Y6 ~: X9 _, X(8) 如何将窗口居中显示?& Q( P6 t }5 W8 m
" [$ O( a" C s& m9 D- V5 T% R3 N
$ y" q+ w& s+ l' Q+ m+ o7 n* g+ P$ H+ b3 \; w; h
7 e6 h( P0 m6 R2 d+ d( c
Call Function CWnd:: - s2 P& C3 A2 z8 R8 q Center Windows# a4 S/ o. \+ }1 c/ ?& n
; N" I; r! j" X9 D3 k1 |) `* }5 S1 H: O
Example(1): 7 a/ s* |+ P9 Q- I/ m5 c6 ^ Center Window( ) //Relative to it's parent + j9 d) U" ~* L8 j9 [6 N // Relative. u" O- V" D, n7 O3 v+ C) c
to Screen7 L, b. w# |5 _- I/ g
Example(2):% w6 ?5 q, [1 ~% V7 D$ |& q8 Q. ~
Center Window(CWnd:: GetDesktopWindow( ))2 m: R7 j7 C" N0 D
//Relative to 1 R4 K* Q, `# D8 o0 n2 i! |7 G' y Application's MainWindow- p: |1 V1 P) r! ?1 v
AfxGetMainWnd( ) -># G$ D h+ b& b! N
Center Window( ) / n5 l9 |4 v" R; M+ J8 A+ H; O! `& v! z* j
(9) 如何让窗口和 MDI窗口一启动就最大化和最小化?% z$ }* p& Y" N
先说窗口。 2 W8 F z0 m* r7 H9 \; D 在 InitStance 函数中设定 m_nCmdShow的取值. % \( K+ D+ R5 [, W4 b" M4 K+ x0 u4 r* y* y: V; h9 N% D* h
8 w% R" b/ n7 \; |5 P7 P 1 [2 u$ e6 v" `! v3 R/ v0 s* Z1 E
m_nCmdShow=SW_SHOWMAXMIZED //最大化 3 P" E- Y2 [* h( Z$ x/ J m_nCmdShow=SW_SHOWMINMIZED //最小化0 W" R. u( T" i! D2 m# A
m_nCmdShow=SW_SHOWNORMAL //正常方式6 p4 L0 J" l ?2 n# W" s/ @# I1 X% m
5 Q2 v4 O- x! {* N) G9 w* r0 c" E MDI窗口: ( H _* {! n: G7 k$ x 如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE7 r5 `/ J) v. c' O
0 o- m; E# B9 u, f" n* R 如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。 # R- l# c* g+ u4 r3 t0 t% }6 J! n1 s' h3 Y4 u% _$ q$ u6 h9 T
(10) 如何限制窗口的大小? . N/ |5 U+ o6 u7 t5 J 也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:$ A2 |# a# G! u7 ~
1 k9 C0 I3 ]7 c& a) G9 l) m
(11) 如何使窗口不可见? * N6 v5 ? U% V7 `* j 很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow控制.- z& j5 K& A8 t1 `
$ w8 S" X* {' ^) K7 S; S0 d" m2 S
(12) 如何创建一个字回绕的CEditView 4 i3 Y O6 B* r% K 重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。 2 i' x3 j$ b" J6 w6 F3 Q2 Y X2 ^7 x# e; O; i0 Q3 s& A , _* Q0 q3 c9 s1 c7 T3 R/ l, Z0 H. W- j k+ F6 x; s
& r( I2 h* Z5 [$ H g( l/ Z
BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)9 P7 C3 w9 z$ j, l V R% x" E1 K
{ / I3 p: N+ o9 j, l //First call basse class function . 3 L4 ]& m+ Y; \3 t' Y9 ?! l BOOL bResutl =CEditView : : PreCreateWindow (cs)* J& v- D( B( j/ i7 `: }" _
. |$ l- p' H) K, l% m& a // Now specify the new window style .9 V3 U* `1 Q' [6 j, O
cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL) ! a5 i( y5 Z5 t8 m6 O+ Y2 T! [; E return bResult . y& p7 F/ W4 F5 I- s( O/ k! Y8 p }4 ^! t& z. D% `/ t% G$ P( H
' ?9 k' N2 k5 c; \0 s5 z% P9 @0 T (13) 如何使程序保持极小状态? G0 K) a8 t& W2 D* d$ C2 G7 X 这么办: 在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数 + S2 O2 V8 C* P, { 3 ]! z$ p" I, G5 w" n; [8 E: k, g) b
* w) y& _1 ]) M8 `0 q4 n
. S; B$ E4 l" y) X" d# u( h
OnQueryOpen() ,add following code:' _3 I8 ]$ L' L7 Z3 n- V! N
6 S' F% G. _/ ~# G4 @% c q Bool CMainFrame:: OnQueryOpen( ). p: O( P W' k/ e7 P
{- b* U; {+ E& U1 P
Return false b& n9 u: L. J3 H: L7 }. q$ A! v1 a }! l1 U- I0 ` W; J' ]# _
; r- w9 c1 l7 u: s/ H, Z& g* R
(14) 移动窗口 . R6 D; M) ]5 q4 j 调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。, T# f+ w% F6 r( }7 E u8 f
- D7 Q4 l& t0 n' f1 X6 R . G1 J9 h# @' r: D' N5 ^2 n5 y8 [$ R0 M# n9 ]8 O
5 K- v. k* |8 e# r) g" }- e
//Move window to positoin 100 , 100 of its parent window . " [* |- n6 @: ?6 m- F; {8 f SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)& O2 g# m+ Y# v t4 \( ?
9 U$ D7 W8 G; L, g9 d+ u
(15) 通用控件的显示窗口; h# Y6 f# q4 k1 F/ e( I
MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。, N2 E; ]+ |/ _6 b
/ G6 m7 t8 q0 x% X" e; P. v
(16) 重置窗口的大小 " }: q4 Y$ Q2 Y6 ~7 v$ Z# a 调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。 Z/ y3 \- B0 ~6 |( X0 O% F
2 n3 Z4 {1 a/ e, U: W, I' Y0 P0 M
" D9 D7 [! c' A3 R8 K# w5 A; J* M! u5 m& X4 A
/ d7 L7 i; d) T: E // Get the size of the window . 6 e% p# c+ M, H+ u. b7 w# B r Crect reWindow ( S) I: X9 b& |% l2 ~1 L- w) a U+ Q GetWindowRect (reWindow )7 L4 ^. E4 F9 X$ m8 h! k
/ W# h; q( ?" S% X5 C3 { //Make the window twice as wide and twice as tall . 2 @6 v/ c$ f1 ~2 K% l9 p! L SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,5 f9 L4 I( B4 g7 A1 |6 j; z
. n/ D6 Q, D8 U7 W9 N6 |. f8 K, }
reWindow . Height () * 2, 4 d2 {; H; a7 z. t3 B SWP_NOMOVE |SWP_NOZORDER ) , ~8 D4 G5 U% `% r8 x A8 y- {6 T$ r; W (17) 如何单击除了窗口标题栏以外的区域使窗口移动 & L% p0 O" H% r7 p) O3 F3 a 当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。: K8 e! T, n1 u$ ~: r
4 b4 ]" C2 Y; V+ F( c0 ] ) V/ P; u% M( n% ]% L3 N* l1 s8 y7 h) S: Y: d
! @ } A# `+ \0 K6 o7 X: [
UINT CSampleDialog : : OnNcHitTest (Cpoint point ) 5 H! A' ]+ X0 `7 w% T9 I% _6 N {2 U6 N7 |" Q! }, R# b' w
UINT nHitTest =Cdialog: : OnNcHitTest (point ) 2 h" A+ s* J( Y' @% u return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest 5 r7 i5 x) z& v' r3 x } : _6 ~3 t; g$ l$ z M3 R / ?! I F1 ]6 g3 f( B. F0 y( g 上述技术有两点不利之处,3 Q5 t4 V. M! Y, m7 U/ g
其一是在窗口的客户区域双击时,窗口将极大; 1 S9 r$ G) ?/ e" \3 f- y 其二, 它不适合包含几个视窗的主框窗口。8 @0 M0 [; S3 i" r, o
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。 % ~( L8 w1 x* g* R! S( w+ H! m9 |, R3 g
. A" s: e$ e7 @, x a5 X5 Z 6 j8 f7 Z0 j4 B$ v * i% r& l, W6 F# x3 h% w2 t; B void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point7 T$ e8 u% _4 O5 _- L3 L$ `
) ) ]/ {1 B# `1 `- m { 5 k/ K, T% O% K; x/ | CView : : OnLButtonDow (nFlags , pont )5 w( \4 P, E8 q1 G4 f
7 D) j, D2 b8 A* ^ D- |) O
//Fool frame window into thinking somene clicked 1 _2 n3 ~, s& c) U on 1 c5 O0 R% o* H, T k its caption bar . " [. j8 H9 ~! g. [+ c2 _ GetParentFrame ( ) —> PostMessage ( 3 W) p& Q, S% Q WM_NCLBUTTONDOWN , 6 `9 h2 W O* T9 ~! F% @ HTCAPTION , MAKELPARAM (poitn .x , point .y) ) 4 D/ d. ^3 O1 _ 4 C7 l0 O8 `3 l- }$ r* B3 f } j3 \+ W$ h! B2 W
8 }7 M, h" o: w. q $ c$ Y5 s5 v, L0 K; N 该技术也适用于对话框和基于对的应用程序,只是不必调用2 }3 J! U" V/ d5 [" |. w1 m
: o8 I F6 ~& A- M0 z8 d 7 j' j1 P" P( D# e6 l* N: e( e$ p0 t1 L* m& g
3 B: d6 \) C+ l9 ]; O CWnd: :GetParentFrame 。 2 Q E+ M+ n- w void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )# n+ B+ d6 i# _& e* w
{$ t5 r! Y! x f
Cdialog : : OnLButtonDow (nFlags, goint ) + U w) H9 W- o //Fool dialog into thinking simeone clicked on its 9 y& l, _" ~* a! v caption bar . : `5 }3 w( n& _) n! \ PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x 0 l% Y: h' \0 {+ \1 I3 @" L , point. y; Z1 q R- a9 O" o6 d' ~
) )6 P' F) `8 f1 Q- d [7 m
}$ z2 `+ G1 W7 ]3 [6 e
; @9 L" N T/ z# \3 {
(18) 如何改变视窗的背景颜色+ u: s1 r. ^, c
Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。 # S* [+ g3 B; I% m/ S: [# g2 ^. W$ {) g5 ?+ N- @+ `( z/ v7 W
& S: l W6 t8 e
9 D& U& u5 S: f# {6 b% V0 A
7 ^$ f D. s' m' R
//Paint area that needs to be erased. " r l% N2 A3 ^. A% \ BOOL CSampleView : : OnEraseBkgnd (CDC* pDC) + [+ ^( E$ O" i8 H4 @& ~1 j {1 P8 Z7 [! G' g
// Create a pruple brush.5 X' ?0 W% b, \( {
CBrush Brush (RGB (128 , 0 , 128) )6 O( ^7 x+ Q9 ~) L3 [
) u7 ^) z. @. J/ n6 } // Select the brush into the device context . 4 c6 I% `" W; E$ @3 b CBrush* pOldBrush = pDC—>SelcetObject (&brush)' X' M4 g6 b8 C( d' G/ Z5 z! X
- l' j: @& H. u5 x // Get the area that needs to be erased .: Q/ Q8 |8 b5 W9 S, J; m+ A2 O
CRect reClip ! e1 {& p0 C! ?& k pDC—>GetCilpBox (&rcClip)6 H9 L- a4 S( |2 J/ n1 p2 \
//Paint the area./ ]; O% B0 J" i+ K
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )" ~4 h, S2 }8 G" H7 G
) I2 u& D# f2 b; E8 x1 h //Unselect brush out of device context ." O5 V1 M: V6 k, z9 d6 I) n4 g- u4 M9 R
pDC—>SelectObject (pOldBrush )4 z" u4 E% D* X4 J) F/ I& y+ K# H
3 C$ @0 |8 s7 m
// Return nonzero to half fruther processing . A; x; a F* C. P0 p. {
return TRUE ' p; l9 p9 k; h }5 u2 Z1 N# [" h) w" d
& N, |; `5 P5 j' N/ U19) 如何改变窗口标题1 a8 [5 s" z7 m
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。' M* y; L2 q; s7 C' \. O, D
" s& r; k( A- Z( E% C+ o
9 A, G6 B5 C2 F* `) h) ]% K5 n% g" L& c1 D
4 u5 G6 |, x4 n. e
//Set title for application's main frame window .5 a: S+ `1 s& m( F8 l% I2 Z
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") ) / i0 \* ^9 U6 P, t4 }( e 1 {9 D4 r" q; e5 |: t4 l3 R h //Set title for View's MDI child frame window . 6 _$ T# d A9 T& | GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")$ O R4 j- I) ~# J, l3 h
)' y% z5 y* j- ]- T0 S% |) _' Q
7 |- ?; }0 l4 j8 j' x/ X0 A# P //Set title for dialog's push button control.& r1 R3 o% H' [% y( U1 f% G8 o
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") ) 2 U+ {! H) B5 o4 @: p. `5 c' M$ z) ~ o- n) f8 C
) o( E& i8 t$ X3 V; T/ e( x' n
如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。 + l0 j9 P1 R# c' S9 O- f- v8 ~* X AfxSetWindowText的实现如下:; v* L/ K2 Z# r( ]' {. a
5 p7 y& g/ s( S4 ~, w , V, ~+ D* O3 R. u % L# B y) H) h( _; @4 F; Z" l* q; Q. W; G9 ]; q2 z8 a- h, L8 B7 ~1 o. q
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )6 T- ]+ g4 {$ x. g5 |4 x# J% ]* x
{ 3 n2 b# _' ]# d5 Y) R4 I3 o itn nNewLen= Istrlen (Ipaznew)3 u" V( K2 y7 [" M: ^- A
TCHAR szOld [256] / t; }4 H9 \7 F" f //fast check to see if text really changes (reduces; o, u, {; L) `- J }
flash in the8 L% H$ w' y% V1 y( L; h
controls ) ) _4 B) Q+ d' e' ]6 ?" E if (nNewLen >_contof (szOld) . H2 p% X e& Z6 |4 `. M || : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen& {5 ^. V# H6 U+ [0 @
|| Istrcmp (szOld , IpszNew)! = 0 e/ u+ h+ ~! B, X+ T9 G9 v4 ^# y
{" E& L4 T( k0 ?* n5 T
//change it+ Q" H' W) O0 R9 H+ q
: : SetWindowText(hWndCtrl , IpszNew ) . h5 i" a/ j& E# c* v/ X5 m4 K }0 G, a" Q7 z' [% P5 t7 j7 B
} c, S6 R2 g: ]% q" j3 K) s6 S( W: a9 C# O* H t' x1 C
(20) 如何防止主框窗口在其说明中显示活动的文档名 ; j B- O9 |" y2 W 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置1 O& \- J$ `- p" i0 k4 E9 F2 z
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。( d* b3 H) W" h/ Y8 [% L1 `4 a
! N% T2 z7 ^4 I4 _& ~ 9 ]) b w3 c) l- e. P! [/ M5 ]5 F0 ^9 i' T% Q2 Q
# ~- @5 c1 {8 G6 W- j" e4 Z- H1 t$ W BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)2 N$ t0 j1 k4 h% J1 A. i
{( |9 u+ V' D, H* X { N! P( U
//Turn off FWS_ADDTOTITLE in main frame .! }; y$ f* X+ D4 ?7 S* q: }- ^
cs.styel & = ~FWS_ADDTOTITLE 6 R9 T9 Q2 ^4 k% }; K
return CMDIFrameWnd : : PreCreateWindow (cs ): k f" ^: D! n+ Y/ l- r
}% v/ p: P: p9 U$ r4 M( C7 z
$ |; r. k- O! c4 y2 D2 `- V 2 d& |: p2 {: | A" [9 d% w 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。, b. f7 a, F0 Q. G' N
- R! D9 p* k0 z3 q- J# k$ X
(21) 如何获取有关窗口正在处理的当前消息的信息; G9 C% v+ G% f1 p% i
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。' {) }$ T0 U; a& \
: O1 S' ^$ c& m) s$ P8 D' p. s% e
" I) w7 `4 x9 }9 {7 F6 w: V4 k 6 S6 V. f/ w: Q& n3 P" d, `) J9 N viod CMainFrame : : OnCommmonMenuHandler ( ) 0 c% p! s/ ^& F0 [) b { 9 n' z) @) Z( E L+ @" `8 r0 X; r7 Q //Display selected menu item in debug window . , P& ~$ |$ l7 l) D; o( \* N2 [ TRACE ("Menu item %u was selected . /n" , 3 y7 G5 ?" w- o0 ^* S 9 L- r M5 [; u: s8 Z, D; G* ` (22) 如何在代码中获取工具条和状态条的指针 - a8 w4 G6 o$ R9 x5 R* l9 }# `1 P* Y 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: 4 {8 ^- B& R. @. h0 _ & z; p f/ |# b) @/ L/ ] K+ B; A% Z' E9 }" A A8 [4 a
`- @* ?, e1 w" [/ U7 K% c ) {( }. m# `) W //Get pointer to status bar . : D, i2 T. f( n1 [; j2 d CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( ), k/ G/ y! L! L
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR), b* e3 C1 X7 W1 ?, e E U
9 B1 R+ L" J5 v. i6 _+ b" ]# a
//Get pointer to toolbar . ; E: i4 U0 I1 n( K; P4 e3 ] CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )4 e# y9 o: C9 i. x
—> GetDescendantWindow(AFX_IDW_TOOLBAR)( S( e$ c3 S& J$ B* j% {$ J
/ j) `5 ^- \' r3 t& u, Q( f
(23) 如何使能和禁止工具条的工具提示 ( o& z' D: w) X' G& z1 F" h 如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数: 0 p+ V' L+ L+ ^1 E' d9 R% _4 ]" C4 H. [1 ^4 X, V5 g6 D$ n
7 t! M) h9 j8 p9 c2 v# D* }, i' u) `# u
" H$ H/ S( W3 D void CMainFrame : : EnableToolTips ( BOOL bDisplayTips ) . H( C7 Y- p% S4 c {" z6 a5 W7 f8 D; w' X7 H
ASSERT_VALID (m_wndToolBar)" u) v" x! @1 k4 s' h# a6 `1 H, G
) ?- h) P! X- H8 |$ } DWORD dwStyle = m _wndToolBar.GetBarStyle ( ) 0 }' j) d- P _- z* ^* b2 _5 X8 C# s7 ^
if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS % ^, a/ ~8 Z) V: W) _) E- |! a; g3 h" W2 H& c
else3 k/ S$ a2 m4 H. A. ^) n, s
dwStyle & = ~CBRS_TOOLTIPS 1 P* p; W% S# a* x1 M1 S3 B1 q# q 1 |9 }, j8 M4 ?) r, z/ G m_wndToolBar.SetBarStyle (dwStyle )9 D+ p2 \6 |2 Z1 l( C$ o$ `& I
} ' ]' P1 v$ j P: R5 i$ k( Z# q( @# {$ s' ]: `1 Z1 I; \
(24) 如何创建一个不规则形状的窗口5 ` m* M8 E8 n1 r0 n
可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。8 q# a3 q) I* ~2 q l' z) o
给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。 8 L. V2 d. d! R p) v6 }5 n( {* m! s% T7 R
& f$ s0 _# U4 S6 p1 k% _0 L+ z9 ]2 ? 1 d. g, o% m' D. ^/ @ T c' y! Y E, F, S$ l# d Class CRoundDlg : public CDialog # K- M K1 B" G& J { * }3 N5 U A1 K& b+ F … 1 ~8 t6 s6 j- ?; o) A/ F {4 u private :% U3 V, J+ [2 Z
Crgn m_rgn : // window region( J/ g: m( Q+ M; P
… 6 ^4 ~* i! ? C& l" m" G }7 r2 f# m" E8 Z6 @0 F6 c( W
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口: % O, X: @/ Y: r0 N$ x, C1 q BOOL CRoundDlg : : OnInitDialog ( )* T8 r6 k! |, W/ k
{ 0 N7 V! P7 o$ V9 p- T, d CDialog : : OnInitDialog ( ) * y1 D2 y# v5 c5 p G# H" \, {: p4 w5 N6 i% d `
//Get size of dialog .! N! u! L7 \ \+ _/ e* W) e, [
CRect rcDialog 9 h; \. m( V; y8 T GetClientRect (rcDialog ) 8 Y/ q: R. e: M- c9 b- Y, u$ N5 _' B) E0 J9 X+ g
// Create region and assign to window .2 O& k* m1 U1 z" o1 V
m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )* ^& D2 y9 y" Z" V `
SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )! b! z+ a# a; J. \
2 M" p$ |: U6 C return TRUE , u- c; G: u8 Q* N3 z, Z }& V1 g! e# Q4 ^+ S% a
; E4 z: ~9 e" Z3 q; G) u, o: ?3 Q void CMainFrame : : OnSampleDialog ( )4 I5 V) r* C/ O2 Q7 {+ b# h
{4 \ D' K; ]& o8 S6 W! Z
//Allocate a modeless dialog object . 9 B+ y' ?4 I* r. Z( x CSampleDilog * pDialog =new CSampleDialog # w8 C- z4 `2 ]) O ASSERT_VALID (pDialog) Destroy ( ) 2 _- K# g/ A. }3 X8 Q. G ' v8 x1 H v8 }( o //Create the modeless dialog . represents this dialog.6 X7 R w9 e+ _$ V6 h
BOOL bResult = pDialog —> Creste (IDD_IDALOG) - Z& F5 n. R: ?+ W1 J5 G ASSERT (bResult )! U6 A C+ P5 B* U0 D
} ' h5 g% s7 W7 g7 \5 ] ~( W! Y- i) ^6 Z! j
(28) 如何防止主框窗口在其说明中显示活动的文档名! p4 H8 h! v; _! g( o6 n: Q
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置 ; d, V& ]2 t' P0 T9 [( s* v& M1 |& @' f+ P
$ B9 w9 K+ W! u; f6 y1 Y
, Y. ~( ~' v P1 A* ~% \2 C' ~$ u# u
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。3 [9 d3 N5 |0 M/ Y8 C; ^/ W2 t& _
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)3 X) i9 r6 L T; }" k' C
{/ M1 R0 O. }& e! m) K7 T
//Turn off FWS_ADDTOTITLE in main frame . 9 l' V; n8 {' @# V, F! c$ D cs.styel & = ~FWS_ADDTOTITLE : Q1 O) m) J L
return CMDIFrameWnd : : PreCreateWindow (cs ); x; G+ k; _9 O- i# ^ W* G9 m. k6 d
}* \% \- ?, p- }2 ]7 g. @6 s
# o/ `2 O, \7 Q0 {9 Q/ O - I, s: Y: n- w- }9 x 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南 $ q+ l) N8 a: K4 X$ W l# ]8 J6 J( y! x+ q4 T: @- h% }
(29) 如何在代码中获取工具条和状态条的指针 ' z- P7 v; X' ^% N$ V 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: . Y$ V- K, B" t% G & L) z" X! I1 ]" m 3 A+ m8 l# H" j }/ h$ O' E- P; w+ @: h0 G1 _8 c" t$ q4 B
9 s H* b6 T) o //Get pointer to status bar .: A7 i. P: G/ i. c0 f- b7 \/ i! F! M
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )4 s% H' f' ~5 i' h
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)* ~9 @# X7 P/ W
8 I2 b) ], h' B0 `6 G7 a //Get pointer to toolbar .. p% r( d: t+ r$ }5 o4 }
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( ) $ R6 j( a* K) o —> GetDescendantWindow(AFX_IDW_TOOLBAR), P7 y s6 O2 i
. W- X% C- [( q1 x$ h2 b' A7 E (30) 怎样加载其他的应用程序? $ n* ?' ~( ?5 T) n* `/ h 三个SDK函数 winexec, shellexecute,createprocess可以使用。$ X w" |) e' @3 k6 K/ i9 H& a
WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。: U0 I% T0 T" e8 ^
+ a$ E+ A; Y9 V* |: X1 J7 M
ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:/temp/1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦. # Q& c$ B0 _/ E5 b" j0 E2 j 4 {% z& \. c/ ]) K0 v4 T" v* q+ f1 I" n/ [' d2 O3 {' c- ^
$ V3 K( m" Y- N6 b1 K6 [* K. V
; r/ Y- n3 c1 h: F; o$ d/ t
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED) % U2 A& ^+ y, h1 k ; _0 B* r- ]: f% ~6 O! l CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example: % X/ O0 f6 d# H4 a3 P( Y6 w% Q2 f$ x
+ X8 F0 U$ k0 W2 M7 f ! g% q, V. R- w# ^& d6 ^! s1 v/ s+ }2 p6 G
STARTUPINFO stinfo; H' o, O" P* }. L3 u
//启动窗口的信息; c! y. Z$ ~$ z) p+ `; t: y" V8 D
PROCESSINFO procinfo //进程的信息 7 A) `% ^8 z& L% Z7 N9 y( ]" l0 R1 ^! I8 K1 w6 f+ a
CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, ' V: F1 E4 P7 |! e* p NORMAL_PRIORITY_1 m: ^% G% G* T
4 i: m$ ]) S% e/ V: W CLASS,NULL,NULL, &stinfo,&procinfo) 5 v4 j7 B/ _9 s, f: ?' \9 _- V H4 B6 B/ H) g6 m C; e' _
(31) 如何在代码中获取工具条和状态条的指针 4 z2 f) {; s: P, a) Z5 Y 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: i A+ ~" ?: m) V: u% U9 T
/ k: ]5 j7 u( v1 Q
2 `* @4 A9 k7 _6 f$ i$ o. n ; a7 M5 ?4 O; X! h8 K$ n: x( }8 v. C. U* c3 j
//Get pointer to status bar .& V) s5 G( _% ^: J% j3 H! O
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )8 J8 B* v) n" Z8 z& x+ ^8 @3 X
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)" M( X& M( I& l, @
- E2 W2 a; O* ] ~4 v; \
(32) 如何使能和禁止工具条的工具提示, A, s( U- u& ~' p' P4 S
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:& G2 \% i4 Z2 Y/ l9 K1 c, O
* m2 H1 Q, X( q
) e3 e% b: L: q' \( }( s) E) g5 b
) m/ n: G3 v' _) {* l" I$ G u0 m& g3 M& A# [! ?: D7 F
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )8 R/ }: P6 x" F1 B& [
{ x0 W0 N9 I: A5 Q) w
ASSERT_VALID (m_wndToolBar) , s1 h4 z. r8 a8 a9 D: V3 k, o2 \, G: l3 v
DWORD dwStyle = m _wndToolBar.GetBarStyle ( ) " N/ M; j# e9 _$ H $ k& g6 K+ Z B. i# K( G. T if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS @7 r& \) ]; l+ i2 s% }; W9 J/ B
8 O t) X# \, Q1 ?5 c& z else* _6 @0 x; b" C: V# B
dwStyle & = ~CBRS_TOOLTIPS! C9 C+ G% H' P$ n( r
+ R. ^# f$ A% f0 A
m_wndToolBar.SetBarStyle (dwStyle ) 6 S- U. ?4 v7 S4 y& u, S }/ _! t4 C" T% u" x
2 J# M( ]# b. ^$ U' U9 B- G
//Get pointer to toolbar . / O2 k0 E% p0 c$ u; g CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )* K% n8 z4 u/ f
—> GetDescendantWindow(AFX_IDW_TOOLBAR); \& l+ g+ ~5 ?5 }2 Y
) ~% ]* E" T6 J/ D: p
(33) 如何设置工具条标题 , E! u. | Z( e; B 工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,例子如下:; R! R; f& m3 ?* Q
1 `* S9 e2 z/ Y5 z6 f' _* ^! V, B: G
) w0 |# N& f6 ]: o- ~* ^8 t% _' D) s$ e$ C# n! |
int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct ) " X/ y) @6 K! S$ d { / j1 t* Y4 h' G" U% i4 o … , f6 v9 r; d: F; z, I. d7 L0 K // Set the caption of the toolbar ., \/ S7 k( A) g; s9 f; W$ _! K
m_wndToolBar.SetWindowText (_T "Standdard"). W4 ?3 T( F( q& R% Y. L" m9 f
! c: ]. ^! r2 G; @, ^" o# ]
(34) 如何使窗口始终在最前方? : c3 i" h( V; S5 i8 ^6 k& Y0 S, b1 ]% U9 S7 s2 _) G
' U5 v* B- V3 i r
8 h( D/ x" G9 y) v, N$ l7 \% k/ U5 W5 H 0 ^( A! Y1 u8 @ v BringWindowToTop(Handle)3 Y% h, ] ~' d# M$ D; B3 A: a0 y
; k0 r7 t% I1 B2 {& y7 M
" H' q- H& H Y8 {" [+ `
SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格7 D0 c7 G3 m; y$ C9 |
9 C6 C, ~7 F9 ~- _ ) u8 R$ |+ [0 C, n' O- l8 L2 ]: B3 g8 q) H
- I7 ?$ `* p6 d: [
Example:3 T- [# }; W0 w' R3 r
void ToggleTopMost( $ b9 k) b% q3 Q# k) P# H$ A3 I+ U CWnd *pWnd); s$ h) B! X$ m+ F9 O4 u* R
{ - Z+ S% E- l/ N8 R9 F U. t ASSERT_VALID(pWnd)9 I2 M& w6 W2 N1 p. M# X: n
2 i ?3 O+ j/ ?4 O, o
pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)? $ Q; H$ L* E( g+ M8 c! O7 I8 Q) ?5 g0 n( V4 P) ^3 C
&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE) 3 n. y$ m. P1 g, K" h$ n% F D }& ]" t" z) r8 H2 O; E9 d3 d' Q
& w' i* d1 l0 B) f0 _
(35) 如何在对话框中显示一个位图. q! J* m+ `% r: ~ O6 E" r
这要归功于Win 32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。) S h$ m* H# s d, y! s& m
8 N8 s' u1 k9 h: `. p. F+ b! ~4 ? (36) 如何改变对话或窗体视窗的背景颜色1 c- @ X( O7 y" a
调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。 9 |+ ]& }) l* T! S/ ^+ c9 U9 @2 k8 p7 p' W
. Z) D6 i; ~. l9 J X7 U6 H, u/ O4 B: Y- Y& i
! t! s3 Z2 m7 W. Q o
BOOL CSampleApp : : InitInstance ( ) " J0 b5 _3 N, S- J/ R { , p8 [" P/ c) e …" E5 d/ U6 K% ~& ]' O
i6 f* |8 O# X8 E* N- y, j6 [9 y
//use blue dialog with yellow text .8 T5 D9 v7 o4 E4 s$ q: K0 D
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) ) 1 L% k! f4 t( @ o 6 r4 A& V, r/ d/ K: O9 \+ w: z … U- B% y/ w* @3 k3 f) w }/ q; U" b( V! T7 c
4 V$ S! `1 {/ D$ v8 F# Z. f* h ~ 需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。; V d( H' ]) q5 J
7 I" \, x2 P1 z! ~- W; U 首先,给对话基类增加一人成员变量, z2 B8 n4 Y' o: ^4 ]# A$ s d5 F6 X* e
* A1 u4 l( O( D7 F
$ m! H/ K3 i& S% o! K
. f2 K/ w, x+ l0 Y' s' Z0 y! T8 m
: J. Z9 p8 H8 x7 |" {: U0 R9 \
CBursh :class CMyFormView : public CFormView9 X4 N7 j+ ]/ o' `
{; f2 @: ~/ m$ B: \
…' J# t8 x" }; m0 X. i; ?
0 l0 U# P2 o' C- g0 |+ M private :0 i" h) v$ i" H9 @; c
CBrush m_ brush // background brush% o# _/ Y+ K. w8 i. I
% d8 X9 E9 ^2 j
…8 V) h* S1 T; r& `( Q/ i
}. ]% X2 C' p& A9 W+ Y3 o