5 G9 i9 t& C V Class CRoundDlg : public CDialog " ?5 z2 P& X" X% x! ? { + n4 L0 G9 Q6 p0 r' x. ]) `( e …* j& h3 E8 M1 Q
private :4 F1 W$ G9 c! F8 _; {2 Y- A6 m
Crgn m_rgn : // window region* M( G" t; _$ M D
…* u, H1 m v+ M
}8 T7 W+ Z: T' j; `! ]
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口: ; A& @7 V0 }* F8 U! T BOOL CRoundDlg : : OnInitDialog ( )$ T. e" D% G$ g, I& D2 W
{ $ n% r& |# T4 M1 e( v CDialog : : OnInitDialog ( )/ q! q# c O* G. Y
+ D1 V; n7 C1 U( l0 Y1 K# B( ~7 J% ]
//Get size of dialog .9 ~; R- r, U( m7 `
CRect rcDialog ; a4 R+ {) r' ?( s5 k GetClientRect (rcDialog )2 B; j% n2 E) C3 v
) i. z0 E/ u1 i# p& r+ l // Create region and assign to window . u. l; |! |$ y1 O) R7 f: C& e( M m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) ) " e7 V4 ^/ W, w5 w6 `, C' l+ D SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE ) 4 ]% `; E' o' {* a5 X* q. Y- q" B7 L v$ L% X# u
return TRUE3 v a4 v. L; ^! e7 v- ^4 i
}. H4 p, c! N) C( }7 ~$ K
- @7 T- q' f4 [5 G, i. @: X 通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。( e! A3 G1 l- Y$ G B0 ?6 N
6 {! W H/ H: l+ ~4 f6 R& b
G6 w+ y: k3 _% A/ X2 \: D5 Q" I) \
9 a, C" E# ^% f6 v/ T# g
& I; ?4 \3 @, C. Q6 @& s! `) R
voik CRoundDlg : : OnPaint ( )4 }! ]9 u5 V+ a# n+ G
{ 8 P- P; y( ~: y- o; _/ C$ j1 g( ~0 | CPaintDC de (this) // device context for painting * \' o7 V b# R0 M7 y . c3 N0 X2 E* h8 f
//draw ellipse with out any border. ` c0 p" Y: [6 s! T
dc. SelecStockObject (NULL_PEN)! M% y9 h: U! T
//get the RGB colour components of the sphere color7 a/ Z( F( H/ q: ~! \
COLORREF color= RGB( 0 , 0 , 255)( T9 Y9 r- m l3 f P& M2 X
BYTE byRed =GetRValue (color); i! u& r9 T, R: O
BYTE byGreen = GetGValue (color) * A5 ~+ K' z, b, P, d( O$ j: ^; _ BYTE byBlue = GetBValue (color)7 W) z. m& n0 C. v( w
: j3 k2 i% o, `8 H3 r) T) G; }
// get the size of the view window % [% Z9 z$ S5 f& l5 q$ T8 I- M9 @ Crect rect , L& U) \" j2 ]( |+ J, d' F4 F GetClientRect (rect) . N/ Z- a# C- H5 H6 @: B$ @. `& Q5 N: M
// get minimun number of units8 `6 m/ F( X8 H
int nUnits =min (rect.right , rect.bottom ) 6 _$ A0 q8 F- ?3 P( ]' Q# `$ Y: K/ Q! U/ N
//calculate he horiaontal and vertical step size. h( Z$ r6 d* d; W
float fltStepHorz = (float) rect.right /nUnits 8 }$ s8 J! c& }# R0 I float fltStepVert = (float) rect.bottom /nUnits2 y- _* o, y+ [ _4 Y
, c8 k2 \! c' a0 i+ \- {9 {! X! H N! ~! \: R
int nEllipse = nUnits/3 // calculate how many to# h7 ^. \+ v% w0 S6 u
draw ' ?7 p; A8 Z9 [5 k int nIndex5 I% ^" a! h' ?7 K
// current ellipse that is being draw& H* p7 i. i; c+ z; b& k/ i9 Y0 ~
* D# Z$ _% O9 ~
CBrush brush * j" S+ P o/ D' x; x: X& X( Z- _ // bursh used for ellipse fill color" ~6 ~1 E% r2 L" k& K' @4 {
CBrush *pBrushOld // previous : a5 _9 H' t! X* m. k# A brush that was selected into dc + J# x; K: M2 ?8 q( v: @! b //draw ellipse , gradually moving towards upper-right & R1 r5 r% G- n, S corner% R) F) w/ M7 F% C" _9 T) l0 P
for (nIndex = 0 nIndes < + nEllipse nIndes++)! U3 U. K4 f% g, W6 e
{. t/ T4 k* |! ]
//creat solid brush L; A& k8 M" Q, P, y" _ brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ). # {+ h( b2 W' A& [1 Z" H ( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)( r0 k8 V' Q6 P ?
/nEllipse ) ) ) ' ^7 w6 o# y0 A$ z$ i & `, f/ |3 c3 s //select brush into dc# X& E4 M e& |
pBrushOld= dc .SelectObject (&brhsh)% P2 R( [3 O0 U/ m7 A0 A, R' p
' ?$ i4 @- ]7 ^! z! B: T( e //draw ellipse+ `( y( L) D3 @8 Q! C- N
dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex , & f5 H) o, J4 b4 G4 i& x9 M rect. right -( (int) fltStepHorz * nIndex )+ 1, & n3 @7 c5 a5 b- E rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)) H+ K& z3 A: R& s! B1 [& z
]$ R6 B; [) H* V5 e8 @! n% N
//delete the brush 6 x, ~& O1 L2 e6 p# J& T7 h# ~ brush.DelecteObject ( ) 1 f' K4 u# Z! ^; k8 P3 [& z }" z: u, D. F( k2 @; q
}4 z T. _# f* W1 h% z
- I! W5 Z6 Y- S' z1 z
最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。 & p3 j2 Z( _; G# G 6 `- H$ }- V$ z9 f7 Q( i- p9 e! q" v+ o. \ ( k: b4 d( w. G/ ~+ B* V& k; }1 F: a$ E. E2 X0 w% u
' `% I8 k: B# q3 F. L- g9 O
UINT CRoundDlg : : OnNchitTest (Cpoint point ) 7 l2 o5 j2 n4 F$ W { ! b2 F) o- R @0 P3 Z //Let user move window by clickign anywhere on thewindow . & y8 Y; ~! V7 x" m! | UINT nHitTest = CDialog : : OnNcHitTest (point)2 J( U6 `' W7 p8 W3 Q% n) [
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest) C( g, y2 G% ?+ q- h/ F6 L
U2 E) R7 E# b) u) s
} # j: G& G5 z5 j$ e; U! t e! y ! @% l6 r9 `) h# m1 e" [( C7 \ (25) 如何获取应用程序的 实例句柄?2 M) q+ _$ |6 \4 y& P6 T; U8 g6 \; C
应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄. - [7 K: U5 a7 B' w " ?4 ~. J+ A5 b. i# `' m 3 M! K8 y% W6 L' j% B : M' {6 d) {7 ]* E- [' C) Q( P G+ g9 k! A
Example: HANDLE hInstance=AfxGetInstanceHandle() 4 {( o$ J a, T6 g9 Q; ? + ~- D8 j6 O, J$ o: ]3 ?+ J# B(26) 如何编程结束应用程序? / k; I/ S h* g$ n9 e! H 这是个很简单又是编程中经常要遇到的问题.) U2 b4 i9 t( ]2 f5 \
向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据. + U$ ?5 B/ D8 w% A+ f3 l. H0 p% o' X; I T
[被屏蔽广告]. k" K) v- g8 ?& {/ }
9 y/ |9 W p: v. i" c; P/ d3 i+ z' } 系列文章:VC实用小知识总结(一)9 ~4 L' P: f% U; N
# O( [3 y# a$ a/ ?( Q# E [" J
: N9 ^8 W! u1 Y5 u0 i
- q4 O- }; d' t/ u' p9 y
# u6 z8 t5 |% m3 J
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE) 8 w7 F% `5 @* |$ ^! \5 Q* m% z
还可以创建一个自定义的函数 Terminate Window ( |. n" v. u, c# }1 N! L " U8 l3 H! |* Q2 w$ ]8 Y3 z; m+ x # f' p8 V9 \( I0 ?4 h! P ) r- z; @" K% k8 C* Y+ \6 } " ~" n0 M1 c8 l. O void Terminate Window(LPCSTR pCaption) $ X) U8 M) ~. K2 x6 w. t( Q; f { 7 m& q: Q( R* Q3 J7 C$ n# j9 M CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption) # ]2 `& J: ~1 F, n3 b. t8 Q. n& s5 `8 `) D; w8 |
if (pWnd) " }8 J9 [! e, r# i( n+ ] , a) t0 \. y4 Z( u# A# W pWnd ->SendMessage(WM_CLOSE); t! L9 E* `0 B1 x; M& V6 t% Q' j
}2 I* M7 q! ?" x- h
7 k/ P/ e! R+ ]9 j# i 说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。 4 P. S; Z5 ~( q* `; h- g/ p, x0 c5 h2 ?1 _+ F- {& n
(27) 如何创建和使用无模式对话框! [8 l# _. _6 b' }: F( X( Z
MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。) k; x( U, T& N, I
2 J( [* \1 n- h2 Z5 u$ ~5 ?/ ^ k* @, o4 m) Z
7 c$ ?6 ]7 k* [* [9 w
0 s+ t5 D1 r$ i) n0 C
void CSampleDialog : : OnOK ( )6 }6 u: l' A% N+ a* ]
{) R: n; j, t; c' G+ y
// Retrieve and validate dialog data .+ g7 P% [5 N8 y7 }$ U. C
if (! UpdateData (TRUE) ). Q, d0 W: X) p
{ V/ H0 W; C! a; \6 k // the UpdateData rountine 4 U7 U# t6 l" j8 g will set focus to correct item TRACEO (" UpdateData failed during dialog termination ./n") . J7 _0 j' g+ ~, v5 H$ b( H' x return 2 K4 p/ V" Z8 t" y8 N2 r/ N } ( A! h+ I/ |/ y2 N1 c7 {2 t6 [$ P! z$ y. Y; a4 m
//Call DestroyWindow instead of EndDialog .- N! H( ]$ Q8 ^( G1 U- X$ O
DestroyWindow ( ) 2 B% N4 t; z m9 n4 j, d } & Z6 s }8 h3 c4 ~! Y# ^7 `$ O( X! w+ p: x% c* r
void CSampleDialog : : OnCancel ( ) W3 ^' H [* B; @. D
{& [" j t, ~( W. R
//Call DestroyWindow instead of EndDialog . ' M( E3 @0 X/ x* }; ?( \ DestroyWindow ( ) " {# I& j- d: S$ P- ` }/ s* r5 L7 `6 N6 F: u4 Y
3 K/ `+ K, W: a) ^) }# g* S 其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。 ! `- t3 l& i" L: y ' j; J( d% @" c1 c+ [) l5 N) \" c; Z5 a
! K! d* v$ F6 o& U: e2 z7 h+ }
2 A. @1 _+ G) x; t4 d2 V/ b void CSampleDialog : : PostNcDestroy ( ) - g# s( J6 e, | {' d7 U: D/ k" @9 m
// Declete the C++ object that represents this dialog.9 w0 d$ M: a9 f4 Z
delete this; q6 p$ J& t+ a( p+ X, R* ^. q
6 B9 O. L: W! T M2 E1 O- u6 X 最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回, $ V0 K5 m ]" I 8 ^$ \" D' x( ~ u9 c- n$ ^$ P9 V% b/ \1 [$ A' i S; Y
; V! O7 l$ v3 T/ b" T( u + ]. l. j3 w2 j. k# S void CMainFrame : : OnSampleDialog ( )" @8 P* _ w! m: Y" E# t# c
{ $ M8 I% z9 ]! Q- v! L& ]2 M" p, b //Allocate a modeless dialog object . , P3 h+ B t: t1 T; A& ` CSampleDilog * pDialog =new CSampleDialog, q2 |& ~& u& j: B, t) T
ASSERT_VALID (pDialog) Destroy ( )8 R5 J9 W0 U e; R, M; ~3 O: _
# b8 ?$ d' K% a- H0 D5 x, d //Create the modeless dialog . represents this dialog.- z4 i$ k# L! V/ K
BOOL bResult = pDialog —> Creste (IDD_IDALOG)* n: k5 b1 ?- J5 G
ASSERT (bResult )& s# B. Y) c. a6 I# E! j# I$ J; c
}# e8 H% C) m0 q% `: ^$ W2 w
" ?( ~% \$ l8 c/ E
(28) 如何防止主框窗口在其说明中显示活动的文档名 p0 ^* S- Q% M6 Q6 l" j" f; q 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置1 F+ `& I' R. X. t" {
! w2 ~- j% O/ {2 ?3 [
7 w. F- s4 d# C& k# [ 6 O" X1 Q3 l, }5 f) U+ K; X F3 |4 M$ }$ ]7 u CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。2 f2 @0 E% L7 G& }: z
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)% l/ Z; r0 V& r O
{ & M) s" L0 O; v3 }- |2 C! S: P //Turn off FWS_ADDTOTITLE in main frame . - }) S/ x9 P$ T! } cs.styel & = ~FWS_ADDTOTITLE 5 B! m; i* p# a u2 y* P9 m/ O return CMDIFrameWnd : : PreCreateWindow (cs ) " h" @! P* q: H1 i' {1 t }. d; c! [1 e& I) ~8 y T3 x$ r3 V
& ?) @& {$ s7 N, q, s5 m. \
2 I, ~& w- R0 E& Z: f& N$ n. f2 B 关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南6 o' N+ T: F' Z7 Y$ Y
# a9 c# N! r3 T' C(29) 如何在代码中获取工具条和状态条的指针 & A- C! _' R& [+ C) x2 ]1 G( U 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: + R5 R% ?( s& W5 {! J 1 L L: x9 F. g0 E! L / @3 d B, z5 F3 Z4 R+ |; ? ' o( z# x0 l& U# n1 s P / ]1 o) o3 Q. _3 Q //Get pointer to status bar .% R& O) H# Y' y2 a
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )6 V2 w4 J; B7 Z. }# C; t
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)& E0 w# Z4 \! u/ d( N* W
$ p1 }0 s# h9 S" P //Get pointer to toolbar . % N( o6 R* l; J* ^ CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )$ H, Q+ \) l! l
—> GetDescendantWindow(AFX_IDW_TOOLBAR)2 m% D; }) S, l. _* _, Q
$ L/ E+ Y. P4 y: ]$ n
(30) 怎样加载其他的应用程序?$ G; a4 X: ] _' [1 K! w5 N
三个SDK函数 winexec, shellexecute,createprocess可以使用。8 C4 |! W, M8 c& i& i
WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。 X) l% f a1 f
) x- J4 ~! m& O G! V" ?) _% n ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:/temp/1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.- d: ^1 `- D4 D, @8 {
; ^; J2 B3 {& u+ T' q& z* V d, l F1 a5 g; }# \' S
0 |$ ]) b' A# l. G d
0 n1 ~. t$ A' |7 k5 d6 N
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED)- o+ N6 f& O; G8 ?1 C9 T! J
8 w z4 p" h- W7 v3 K. L
CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:% T8 W4 p6 V; m+ ~$ C