* U0 T8 ]/ Z; q4 L* R+ Z) k. c0 w3 N" ~% g; _4 Q! |& L* @% \ h5 p
& Q6 _# {8 e j6 n
//Move window to positoin 100 , 100 of its parent window . ' v3 U4 A7 \2 E# V SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)0 z- w5 P; u7 h7 n: j& b0 c, R# G
N$ n3 z2 _" \! b& P (15) 通用控件的显示窗口 4 e4 V4 q6 I* l, u( h" Z' c MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。! o' j$ n* L9 Q8 z+ h+ |
# @" E X* ]" z, K Y( r5 _4 x4 |
(16) 重置窗口的大小 m( s) }! f+ V9 Q$ S' b g
调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。 ; }8 N+ u7 {7 X5 N) Z5 l& l7 N V* l4 T( _$ V
8 {5 O% }1 t7 a! T# R9 J" P& [+ b4 O; `" w( U/ h( R
6 }$ |7 U; h6 C6 c' Z, M2 d4 C) |0 Z
// Get the size of the window . 2 t& M5 f' ~9 S9 b2 M Crect reWindow B8 l6 {! L& a7 K% H T" n
GetWindowRect (reWindow )- K) ~* m3 `' A. }9 T& @" g( E
; V9 C* }( L+ g8 K+ v' A0 N V3 T //Make the window twice as wide and twice as tall .0 p5 Z$ G) h: C% C
SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,, A( }; F% T1 j7 T; O
3 z8 a1 d& M7 W e N reWindow . Height () * 2,5 ~( f* c/ r/ D# \$ I' g8 Y
SWP_NOMOVE |SWP_NOZORDER ) : o' a, q, t8 R* e+ G + p) x' j$ Z5 f) E" t D! R; i (17) 如何单击除了窗口标题栏以外的区域使窗口移动" ]# [$ B6 l* B" D
当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。 9 Z4 s4 M1 [" \# ]! n9 p F; c( q' p# G) e1 ~: T# R
" q1 H' Q. \1 O4 D* J. Y+ D- c3 n4 o1 ^! `: X: Q
/ A) `; I% H5 e2 i- P+ K \6 H( H3 p1 a& \
UINT CSampleDialog : : OnNcHitTest (Cpoint point )* y3 }0 Z8 Y9 }. V) m" Z* ^: r9 r/ y# @
{ 3 W/ P }4 w6 S. P% J: k. E UINT nHitTest =Cdialog: : OnNcHitTest (point ) " S# p& n/ n. g" V/ x! m$ w return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest : C& I4 c- A2 L } l! p! c3 N% Q l$ b3 k8 B4 b
8 a: G5 l& c! D 上述技术有两点不利之处,. j6 w r* J: H9 X! I u+ W1 w
其一是在窗口的客户区域双击时,窗口将极大; # _( H% _0 y6 Y u- k 其二, 它不适合包含几个视窗的主框窗口。7 [' T. W5 v4 Y0 g, n, ~8 F0 i
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。 ' M3 p+ J f% X2 r& T 7 o. M( ^' w( \# p, v0 f/ D3 l3 H4 m2 |: J4 c/ Z3 n4 f
$ @& f1 @+ n/ e# `( D' ^9 X
% Q7 d& W* K8 c0 l, Y' \2 w
void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point1 A9 L9 X, ~7 P0 ?
)% N- s+ B) Q9 C2 F# E1 {3 w; i) l
{ 6 H; f- X% P8 O7 ~5 ? CView : : OnLButtonDow (nFlags , pont ) 8 h% q4 s8 E! t8 ?7 }3 A6 n- `8 q- e3 f
//Fool frame window into thinking somene clicked 2 u+ _8 J& Y! ~$ Q# \0 t2 W on * x% T4 t; y6 s' Z its caption bar .( e% [: K: a% V6 N# X T# u2 N
GetParentFrame ( ) —> PostMessage (* B. ^6 Z2 g. g( d9 Z+ x, `; t
WM_NCLBUTTONDOWN ,& h! _0 E' i) @% a5 A# m
HTCAPTION , MAKELPARAM (poitn .x , point .y) ) ) N# C+ g. M9 Y1 ? 2 ^8 f A% \. I } 3 @9 H' Q$ b9 G& ?0 j! F. X9 n5 ^. d' b; y) \
$ |9 B& X% S" M' N; O" M0 m
该技术也适用于对话框和基于对的应用程序,只是不必调用9 t3 Q3 B+ x5 j" M4 N$ ~8 @% A; X
, ^6 y3 S/ O% \
! N! j3 W7 W$ ]8 j 4 b+ i4 C o3 W' [ 3 }. a1 V/ h* M$ \) U# ^3 Y# ^. V9 g CWnd: :GetParentFrame 。7 t+ s% \- |1 x8 Y6 L3 q
void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )5 N3 m/ _. W7 j8 v6 v/ l* v
{ : r! ?% X: |) n; u5 N8 I: s Cdialog : : OnLButtonDow (nFlags, goint ): X- P4 F v" s0 E$ ?
//Fool dialog into thinking simeone clicked on its " v4 n( x% I8 W' C caption bar .7 C9 U+ S, L! @* c
PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x$ }, n @ U# O( `: u. K
, point. y ' _8 i1 g0 j' ? R% x, R2 u# L ) ) z9 e# E$ |0 v } 1 H! l" X5 i6 c# T& d : f2 a+ W* t$ X3 a( z (18) 如何改变视窗的背景颜色 $ T' r. q& i& C& Y, x7 D! I4 M Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。 $ C( K0 Z5 w! K; P3 `' p6 k 9 L5 k# {+ Z) G+ p7 y/ x* D; S3 v3 I$ Q
6 F- j; Y3 E& E( Z4 H2 }6 t, J J% \7 }# g/ Z q; z m8 g2 ^. i
//Paint area that needs to be erased. $ f4 x7 P- x% ?2 R; ~0 z BOOL CSampleView : : OnEraseBkgnd (CDC* pDC) 1 r) ?9 j S6 e2 b" q) J {% M" P" h P8 l& Y- n/ f
// Create a pruple brush. / q5 K9 d5 @2 B) F6 n CBrush Brush (RGB (128 , 0 , 128) ) 8 G* t3 M# r- f/ h , e+ X# n) Z1 @: z9 V; I+ ^ // Select the brush into the device context . # d0 R7 ^5 v/ S, M# z8 _ CBrush* pOldBrush = pDC—>SelcetObject (&brush)6 h( f: \/ @6 p; I. t
* x5 S! D5 p9 {( y; s. i' m) | // Get the area that needs to be erased .1 \- x$ x9 ~% E8 z+ S
CRect reClip . A: k% `- d% @3 i1 u9 d3 h pDC—>GetCilpBox (&rcClip)+ y0 R' g9 m E( M2 s2 @# G
//Paint the area.9 e; r" H/ E+ }- K* y$ h" y6 @
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY ) 4 b3 C, j( I( z- P, R Y* H0 }. p# b8 |1 g9 K( Q w
//Unselect brush out of device context .( Y% [% O# O. |
pDC—>SelectObject (pOldBrush )7 z% D1 K9 g. E0 g# Z$ q
" @- u) v! d+ ]
// Return nonzero to half fruther processing . $ l" w- S% Y/ K9 }+ P return TRUE2 V- b$ G z- g) V ~. e
} 3 ]7 ^- E1 D' h ~% t9 \' `; V* M7 Q9 r
19) 如何改变窗口标题 & N' L2 k0 B; w, _. T 调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。# |7 H# J! a+ W+ u) u1 ^' {% f
6 l+ j9 f( e" G. S. E: d. ]5 K( i
( T! r+ G* G" w. Y' G0 y, a2 g Y
7 }" n9 K# c4 [. s3 \
//Set title for application's main frame window . " S: `% {' o$ M6 L, L. L AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )$ `, G5 V {0 i2 I V- y
6 [0 U* H- Z$ H: n2 a, c+ C$ F //Set title for View's MDI child frame window .' s/ [ B6 {) C4 F* S" Z' u( \
GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title") j! g6 t0 j" y/ J e
)8 `8 @! n3 o4 x: }
k6 | V! Y3 I4 t2 { //Set title for dialog's push button control.: x& u$ ^! m8 v! g
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") ) ) P: p X$ l' n& }% L* i2 l% H4 B4 h, i: s* h
( z, Z3 x% U# M# Z$ d W$ h0 _- V' v
如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。 8 O) I C# q; l0 C: a8 P9 v AfxSetWindowText的实现如下:/ \% Q% D+ e# E! `
! e, I: v: y, m' e" r- ^ if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS % g% c( k' l) u+ g8 b ) Y$ k* O) p4 I, c: V else( `* x X2 V, O, ?" X# ^1 X; O1 f* v
dwStyle & = ~CBRS_TOOLTIPS) d |& @8 [ I5 P% r: H+ G
- U' ~" _' g9 P0 m m_wndToolBar.SetBarStyle (dwStyle ) ) C A' y5 N) N5 k+ {* y! ? } 3 P( ]3 f' p$ A* B: i/ t4 |) K% y7 H) T+ h# T3 T! J
(24) 如何创建一个不规则形状的窗口 B0 P! W. b, a4 \5 z8 z% O 可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。$ J5 q6 o; D# A" J
给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。1 H$ n: q, A9 x' l1 |5 _
/ ^3 L" T6 [) U2 J3 e5 q2 C G
# F( B: A/ e R
. L$ y+ R Q' e) T7 D% _9 S
6 q5 r0 K: z, @- m; r& e/ r Class CRoundDlg : public CDialog: S8 p/ z0 T) T1 r, \- g
{ # X! n& ], S; i … ' q4 N7 j+ r) l3 y private : 3 I1 \7 N; \. S! s* ? Crgn m_rgn : // window region) l$ w$ e* q+ Z' E
… " K& H: v. N/ j+ ]5 t. s! w* @, M& Y4 h } N# E) @& E \$ @8 d6 O 修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:9 q7 S1 R+ i$ n( ?$ a; v
BOOL CRoundDlg : : OnInitDialog ( ) ( e6 `# i6 q( U) a M9 K' C { 1 s% S2 i- ^; j; b, S1 X1 | CDialog : : OnInitDialog ( )- c% u7 `/ B6 p4 o$ U' o
7 m! p2 v' `# f" X7 E2 ~. |6 c, S0 {- i
//Get size of dialog . ) q% F4 b; b2 o U2 F6 z+ a! a4 H CRect rcDialog, P- E- p8 ^5 O$ T e: E3 N
GetClientRect (rcDialog )5 g# G: V0 f, |* `! O4 F* T
J8 J; u) y+ I5 _$ ?
// Create region and assign to window .# v9 D3 l% p6 Z( i2 g, L; [: g
m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) ) , ^" k# S$ J& x1 i# P SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE ) " `9 j. d8 v. v# r ` 8 I2 j2 E# Z2 W/ N8 l3 M2 Y' g, V5 K return TRUE# G( l1 e5 w8 X
} . i/ i, J6 w) p$ x" G5 C$ J3 N & a' N& V2 K7 n' @ 通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。7 y1 t/ u* t) A; i" |. Y% F
' k. o9 K' P. @6 H6 {5 p! d 1 U8 ]* L6 l! F( M1 t+ y- l % R$ X+ m! ]6 w6 Y3 P ! }$ ]4 t1 a& K* M% X9 G voik CRoundDlg : : OnPaint ( ) + ^/ N# h0 ^# m: {" D# d4 N4 y { 6 ^' ?- v# s* {4 D, B CPaintDC de (this) // device context for painting" ] } e: c K! B
. ) l w" d+ V. _7 V8 W //draw ellipse with out any border8 _# F1 K1 Z& {! n' H! }8 `
dc. SelecStockObject (NULL_PEN)$ N6 l) I+ G1 R8 i8 o% q4 |0 l) t. q
//get the RGB colour components of the sphere color 7 ]+ C1 ~3 @; r1 { COLORREF color= RGB( 0 , 0 , 255) 2 V! x: G" B. F1 `" q! N BYTE byRed =GetRValue (color) ! n) J1 v% y1 [# _: u6 { BYTE byGreen = GetGValue (color)0 R3 N2 f0 g( e# q& H6 U. _9 |
BYTE byBlue = GetBValue (color)4 Z/ ]' ?' \* k* _
9 D1 O6 q6 l# S& l // get the size of the view window7 [2 ~8 x% V/ I
Crect rect H1 C* O# r; v& Q0 _0 B/ h. I GetClientRect (rect): K2 d& o% |, l3 x" d+ z9 L
5 |# P: `4 t! R) ]7 H
// get minimun number of units- ^# `1 G1 @' B" s0 m
int nUnits =min (rect.right , rect.bottom ) y& U/ d) }! V& t) C% E8 |8 ~
* T% i" V# p. u9 _$ v4 a2 ^ //calculate he horiaontal and vertical step size. U+ U; Q! t) V$ J9 K) U, z: f
float fltStepHorz = (float) rect.right /nUnits 7 _" M, p" a: p* N7 |3 c+ ^# h float fltStepVert = (float) rect.bottom /nUnits ( ^9 u9 ?% p# A* E q# x* K+ z# b4 u5 b: [
/ w3 m/ Q* \/ _- d0 m5 d l- N( u
int nEllipse = nUnits/3 // calculate how many to/ Q/ a7 x7 `( a0 `5 V3 ]# a6 R9 T
draw 2 b& ~4 b0 j5 l- v7 ^ int nIndex8 m \' d( t5 E( k/ Q2 U" d0 D
// current ellipse that is being draw- j2 S3 e7 I- x+ C5 X% e0 t" T, c
3 T. {( [' ~( e) {7 e( Q" y3 M5 d CBrush brush / f, X8 o# e7 q: a // bursh used for ellipse fill color: K& r# t) _* I
CBrush *pBrushOld // previous ' ?+ l) J6 e0 F brush that was selected into dc: I% m; a. P1 b% F# D
//draw ellipse , gradually moving towards upper-right % D- Y4 h0 ]1 f7 [8 K* | corner% K# }- N- r/ v) p
for (nIndex = 0 nIndes < + nEllipse nIndes++)& k0 \3 e1 k% S6 e+ O! J, c
{ : x% a6 x+ Q0 ]) d4 K) s //creat solid brush $ ]( q0 k; a: O6 b2 J d" l! t0 w brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse )." k) x4 O7 t% H
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)% ^- N. c+ K% x' c% ^( C1 n
/nEllipse ) ) ) ( {) O0 \+ l/ N1 K6 | 9 `2 G0 ]4 E3 Q ^+ R& z9 P //select brush into dc & b. J% A6 z) H8 J( D1 j2 s pBrushOld= dc .SelectObject (&brhsh): p8 ?7 c$ m" K
8 m8 p/ x+ K2 A5 w% O6 y" {2 l0 i% U //draw ellipse/ |; G# T, a( Q k
dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex , 5 E' k. {) C4 [: w! H0 U k! z* c rect. right -( (int) fltStepHorz * nIndex )+ 1,$ F* i7 J2 g; L7 r
rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)1 h5 [: v4 X0 `
4 G7 @8 v% U `
//delete the brush0 X' J2 E2 _4 X2 k
brush.DelecteObject ( )' n2 X I5 G/ ?; `
} 7 c$ V I5 W" x u, p( z }; B" i4 |' t3 e# f; _7 G
6 X- q- [' F7 Y# T 最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。 # l& k0 I+ \+ p" T + s! s; d, m; S 9 G( o0 J5 m/ S) G* M# ^% `) D# U$ V, ?+ |4 ]
7 {: z# ?* Y* x. f
UINT CRoundDlg : : OnNchitTest (Cpoint point )" l, r- H( W) j" o& Y
{ # j. ?$ g$ |# ~; t* I* x; u4 L //Let user move window by clickign anywhere on thewindow . 9 @8 W% s4 [- ]: x E9 v- b. `* ` UINT nHitTest = CDialog : : OnNcHitTest (point) 7 P* L B& `7 o7 q; V1 G# s0 K rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest* C4 z2 } W% u4 D' |
# A$ O/ j& @9 w4 w1 J6 F, Y } w6 c4 ~; c0 f5 L
; d( w* V' Y( I* A (25) 如何获取应用程序的 实例句柄? : g- \- F' w f( M9 x9 K 应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄. 5 h' \1 e0 ^- d) m/ e6 V0 Y0 I( T7 @' e! \- |% `: |' m2 o" V; K
2 g/ _: V& q# }8 S