/ Y d( P3 v, K) Z8 w # j" k5 O9 F. a" u/ @ {& [ e+ L2 q9 A# J2 z9 Z2 Q+ N
* n" }2 K+ _5 N6 ]5 y1 S" D0 ? OnQueryOpen() ,add following code:& ^& I2 t* ^6 U5 }# @! K [! A! s
3 P5 Q$ R: s3 e( F& @8 x Bool CMainFrame:: OnQueryOpen( ) * E# `& }) W A. K! e {5 l7 U/ `/ _% W; {% V; R
Return false 3 X7 F' G! r6 h5 [# j7 p }* h" Y, h/ i/ m1 c8 }2 M4 K/ p& y
* g1 C0 x6 |- N. H, N: r (14) 移动窗口0 T1 G3 ^, k8 j( o8 k/ Q
调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。 3 g5 m" a5 z4 Y * R7 R2 G! X; B2 n. j ) L' p F& C/ \2 k7 ?8 p. C : d1 _& z% } x0 Y% [) D, H: D1 {& A1 ` B( B' W3 u
//Move window to positoin 100 , 100 of its parent window .+ L9 t6 l0 ]; [! Y+ _2 `8 C$ t
SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)& v% x. { `7 v. j V0 O" L. ~
5 h6 P' Q- w* O6 x' \* q
(15) 通用控件的显示窗口( P' w+ _: \, K! k8 U9 A, j! m
MFC提供了几个CView派生的视窗类, 封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。) C( l* e4 y! S( k, c* ?
3 G+ [' j" l* ?
(16) 重置窗口的大小 ; V* v6 f9 P2 C& t/ | 调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。0 \. v/ b4 n, B/ }1 f
! S9 {) h2 w( N2 R
d5 ]- Q; d: s2 I 6 z: }% s; z. r$ L 5 E; b# R. C _3 i* B0 g N h // Get the size of the window . # W' Z# j' t1 ~2 L) V Crect reWindow F8 N7 g+ l1 Y
GetWindowRect (reWindow ) - ~- a: D8 `3 C* L# [5 E& M, @" X9 F' d
//Make the window twice as wide and twice as tall . 5 [6 x) L9 t5 k. h SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2, ; D5 s& t. m4 N9 p9 ^. ^3 O" U1 a2 w9 d2 O+ u
reWindow . Height () * 2, ; q! O# z' i. D* U; w SWP_NOMOVE |SWP_NOZORDER )+ [! B" M- @9 d
1 v+ b1 n. Q) Y# _; H5 e (17) 如何单击除了窗口标题栏以外的区域使窗口移动2 V, `0 R O* K6 M+ O+ U
当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。, d6 Y# ?( e0 _
9 ^: t! t' G; V ! A6 ?; s h6 J/ r7 B; D3 \6 n- a* ?+ s, y, w6 p/ O0 u
- i; | U% l% P7 f. d' \5 [ 系列文章:VC实用小知识总结(一)8 ?6 l* p$ F+ W0 i; h6 s/ e
+ O: z/ J" {# {2 U$ K8 h1 _) E+ n" X+ Y2 k. H3 f
2 k9 A" b4 \' P |3 }6 n0 [
3 o1 |$ ?1 B1 K1 p% b' c Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)" |7 R- D7 Z; I# T+ D9 Z$ n
& E4 H+ {6 w% ~* B/ X 还可以创建一个自定义的函数 Terminate Window! j( A" S* I* n0 A' K2 k
9 {) o4 l7 T" f8 M p/ e" @1 Z- I
% ?, f. I4 w- G
, h, t$ Z o1 k4 N3 [ 5 d% X; W0 {+ U) U9 k void Terminate Window(LPCSTR pCaption)) {: z6 n* r! @& i) u. P
{+ t9 ]$ H; O3 s1 @* P
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption) / B# {) d! q- b" h' G2 V, l; @9 v! R# P
if (pWnd)9 W( J' d. G5 {6 _0 t/ N
/ ^: Y" R# _. u% b
pWnd ->SendMessage(WM_CLOSE)8 Q2 O$ |2 J( ?9 K; n6 A$ u8 f5 e
} / c( L# n0 C. ^9 x- E 2 M, a# }5 a8 N$ I 说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。 & p ?: o* w! e, P% k4 Z1 k( |) P) v5 d( T) \$ y
(27) 如何创建和使用无模式对话框" t4 e9 x4 Q" S/ V0 l, E: Z
MFC将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。 ) m) [9 w% D+ f; o; p1 t+ ~& a" C" u+ b2 Q
! G( h ]( Y8 i$ ]6 d + o. s. C: a5 @# `. Q5 | u+ N( `( }* e% b9 [ void CSampleDialog : : OnOK ( )3 L/ M' h' u8 F) G, A
{ - a( `( }: i8 [. u% k0 C // Retrieve and validate dialog data . ; y% o" G9 m" {3 }, }: [2 x1 Q5 | if (! UpdateData (TRUE) )! t3 A1 u3 w `2 G' N& k# p
{+ ^5 |0 E6 u7 C' R; F1 x
// the UpdateData rountine2 s7 {& X$ P9 d# R4 w! J
will set focus to correct item TRACEO (" UpdateData failed during dialog termination ./n") : k1 V- }3 u$ U$ r4 z/ L, n. a O return: A0 Q6 i9 a* W9 ^4 O5 C5 Y
} 6 i4 [3 N% |+ S ( @( G1 A1 u% P+ b //Call DestroyWindow instead of EndDialog .: m+ } b9 m$ `$ F
DestroyWindow ( ); v; D# w7 F) N; P7 j
}. I6 K0 D( h$ o
! ]. H, v3 U3 p7 n
void CSampleDialog : : OnCancel ( ) 3 H9 c2 b* ?% B5 r { 6 O. H$ F9 [* B+ E% T# M //Call DestroyWindow instead of EndDialog . 7 @& H @5 [- r. n DestroyWindow ( )4 k8 O M; @2 S8 K! {- g
}( @2 Y- `. K0 L) H8 C, u% E4 h0 W
* F7 P* e% ?5 t! O 其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。" m9 {9 C/ p) _, B, Y
" n6 r& T; b$ F8 G# f
: i7 y5 n; X' h
0 \7 b: h& ]8 r# W4 t ) o7 ?* [" J0 m s void CSampleDialog : : PostNcDestroy ( ) 9 E4 X G0 n2 O {0 m; O5 y% F( `) ? O% O' }
// Declete the C++ object that represents this dialog.- i F" H4 G& n+ j
delete this 5 y& f: ^3 k1 K* k' V* \+ K3 k% @0 [3 _, x
最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回,+ e3 c. i$ g$ o. b
8 @9 x, M1 c% d# H# u
5 I% |6 y1 y: ?$ E+ ~" n * ~2 k. X$ [, S5 v! Q - f5 ]+ [3 \+ a6 r a. ? void CMainFrame : : OnSampleDialog ( ) + b1 v8 \8 \, i1 y9 M7 @ {5 J# j& N, p- S
//Allocate a modeless dialog object . 4 ^1 h; L3 W# p- J CSampleDilog * pDialog =new CSampleDialog0 ~6 u, n e: l" Q
ASSERT_VALID (pDialog) Destroy ( ) # c3 T3 v3 p; O4 W6 ~8 b6 K) l5 H9 n8 k. }" K3 c
//Create the modeless dialog . represents this dialog. 5 i _; I; }0 t# A6 ^; o, F/ K0 g BOOL bResult = pDialog —> Creste (IDD_IDALOG)& M8 ?0 |2 c1 _
ASSERT (bResult ) 3 X9 {8 P: r1 g# w$ c5 {: n } 1 `% L8 |& \+ Q; Y9 q8 n5 [: k; d8 x+ S+ A7 H# Z/ b
(28) 如何防止主框窗口在其说明中显示活动的文档名 / `; s, i; {5 Q* c' p& e 创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置 M, F9 d4 u# x/ k* ^
+ i/ j8 {0 @2 y" B: {3 z5 u8 S4 a : q* R) s: L9 o! O5 I( P* i# T$ Z. k4 q5 F" {# H
1 t( L0 j! }! b( r6 t8 a: I
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。* j2 u7 p4 p% M" G* _) m
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)# M! n1 j- |6 o, c& c' q
{ , |$ G% L$ C3 h9 r. g //Turn off FWS_ADDTOTITLE in main frame ./ B7 A. a, X- L5 r" E) v9 `/ c
cs.styel & = ~FWS_ADDTOTITLE , ~" X' l" P9 V3 h$ e return CMDIFrameWnd : : PreCreateWindow (cs ) ; i0 {# }4 L8 }' }. h0 v }4 }5 S$ d8 D4 y; K9 } q
: l5 M7 @* R8 V2 P* C1 |7 h: |- N% S" ?" [
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南. Q; h% s5 D7 j' y: B0 X! O! f' p* \& f
- l$ L' \% g1 S- g1 C
(29) 如何在代码中获取工具条和状态条的指针 8 K4 c, m* Z4 E 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:2 l' m( [$ F* M* X" r
' A3 s0 n, _8 O. R, T- i4 V //Get pointer to status bar . 2 h+ @) ] U7 z$ {9 }# ` CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( ). j) M" e4 C! Q; B. q) H& p' _
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR) + M; W8 X+ G" F- E; W; R/ s6 O# J & t6 T, B- a4 A //Get pointer to toolbar . 8 @6 M: Q. `) D3 S* T1 [3 ? CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( ) * f5 w" J- @( s. J —> GetDescendantWindow(AFX_IDW_TOOLBAR) ; I; b$ X5 o2 c ; `- `4 M7 T+ ?' K- s% R5 b& d4 l6 i (30) 怎样加载其他的应用程序? ( y$ C3 s; z) A# b5 d 三个SDK函数 winexec, shellexecute,createprocess可以使用。* i. L4 b: L7 [) H* D$ o
WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。 # \' Z" Y2 J" j& s3 B0 Z7 U0 W/ E4 d0 E
ShellExecute较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:/temp/1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦. 7 E7 Z7 q5 z! p! _ / r' E5 G# Z4 m 5 V! J3 ]) B# j9 N# A & j8 O/ g2 a, ^0 K- Z) `6 S5 r7 l! J9 w% b2 I% e5 B6 e
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED)4 W& z$ ~7 `7 N/ ]; X/ S# z7 r
: ]) o$ ^& f- V6 f# U* ]- j( b CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example: H. ?) S. S* M% A/ v# ^- G2 E. |/ n9 {9 N- v
' @ p2 I. i# c J' [* j$ v
0 B) p2 J( k& Z2 E ; ?+ `" e* f- p& E6 q STARTUPINFO stinfo / N O; V* c m% M( g+ C7 W1 ^ //启动窗口的信息 ! } L+ z/ Z: ^. R5 O' x6 p5 }* ? PROCESSINFO procinfo //进程的信息4 N6 J: X) r; u- |+ p
9 b$ k G& P- Z" T/ {: |8 ? O# w) b
CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,+ Q( ~( C+ ` a7 {
NORMAL_PRIORITY_ 5 p6 c1 ?4 w) f5 ^6 J: @ 6 i& [4 s Y: H7 G3 o9 _" d CLASS,NULL,NULL, &stinfo,&procinfo) ) \$ H F* C, x+ _; X q$ _- l& e& X: l$ L/ C2 B (31) 如何在代码中获取工具条和状态条的指针 % W6 _0 N; ^% ?8 M9 Y 缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针: 1 ~+ A8 J! G: o2 H3 V3 h2 {' L1 _ @6 Y' u k
1 w# r t$ k( ]5 X& K5 O6 Y. R; E/ g" ~
. s+ S# j3 M5 F //Get pointer to status bar . ' o& K' ^. g& z4 c f! z' e/ b CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )' ^: ^) L# S1 ? X8 N/ b" t! R
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)5 N. M8 h3 s; J g2 ^3 J& o
* ^7 n' I. z- y. A0 |7 S/ h# A) Y
(32) 如何使能和禁止工具条的工具提示1 X9 u3 E9 [! a" p: W/ A
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:7 E g7 |# m" Z4 x* g$ t4 H+ R5 J3 a
% U, V+ |+ h0 Y) a - z3 w3 h: `/ h" e: w7 |6 M$ | F* d% d! j5 ~* s5 M, n
% M2 t1 N+ O% Y. ~! y2 w4 i! \! I void CMainFrame : : EnableToolTips ( BOOL bDisplayTips ), I1 x4 L7 l! ^5 @
{, f2 A: r/ X0 n$ N
ASSERT_VALID (m_wndToolBar)3 w9 g# I2 E# [9 Y
- S. L E6 r2 u+ O4 j
DWORD dwStyle = m _wndToolBar.GetBarStyle ( ) 9 O! R4 q% d; p# M2 l+ l( m0 S% E G# {! a. `6 p3 ]% F6 f
if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS - l0 Y7 ?9 i2 |2 ]8 h " N N# R6 n+ s' l' e8 p, p7 f else+ W; K) _) h. D, o4 u; W
dwStyle & = ~CBRS_TOOLTIPS 1 U" O- f# S4 c" w1 C$ }, Y8 A0 U, a* n! ~- k$ R
m_wndToolBar.SetBarStyle (dwStyle )$ ]8 M8 N5 Y4 ~& S# F3 I& b
}4 E) l6 J; J7 X( e5 ^9 f8 R
8 D1 p1 T+ z* v9 I$ o, s& m- |
//Get pointer to toolbar . : e; M7 D8 q" u7 T- W. f CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )" P# g) l6 p) b& @
—> GetDescendantWindow(AFX_IDW_TOOLBAR) % @4 V( t1 ^+ L0 c) r# p # Q% R! e& v5 B: O3 j6 K2 A. d' P (33) 如何设置工具条标题3 n& W# C9 ?2 R
工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,例子如下: 1 J7 `, ^/ t! f- r6 C ) u) w1 S7 e# G* J' ~9 z/ f2 \ 9 `6 H: v. x: X1 k# _7 l5 g) y Y7 G/ D, M5 S6 Z+ |8 ^
6 a" @0 T$ ]8 w; R0 ~# U
int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )/ Z, o9 [9 |3 E3 d" R
{# @, y( n+ R: n- _( L$ U1 H3 y
… . a# g0 {5 f1 L8 l // Set the caption of the toolbar .. c/ d; C& f) [
m_wndToolBar.SetWindowText (_T "Standdard")+ c" h2 M5 ~& f: U. V: f
, x) |4 l# w/ o! c8 b g5 }4 z' _8 \(34) 如何使窗口始终在最前方? 1 Y" i b# g( s( ~# b % H0 b% s& u4 S# H0 \9 r% N# J4 K _* Q7 B3 K0 g
3 i7 ?( g+ S8 j' B