51CTO技术论坛_中国领先的IT技术社区's Archiver

黑夜 发表于 2006-8-29 01:16

C++ Builder中MDI应用程序的设计

MDI(多文档界面)应用程序是指用户可以同时打开多个文档,每一个文档显示在应用程序主窗口客户区的独立窗口中。如字处理程序Word就是一个典型的MDI应用程序,你可以在Word中同时打开和使用多个文档,PowerPoint中你也可以同时创建和打开多个幻灯片应用程序,电子表格中也允许用户同时对多个图表进行编辑。MDI应用程序一般包括三类窗口:
g0U4cY\k:M * 框架窗口:框架窗口与应用程序的主窗口类似,有可改变大小的边框、标题栏、系统菜单等。应用程序必须为框架窗口注册一个窗口类。一个MDI应用程序一般只有一个框架窗口,框架窗口控制着其它各类窗口。
7t,X*`$V5Ki
[Q O0m1S$x * 客户窗口:客户窗口提供对下属MDI子窗口的管理,每一个MDI应用程序有一个客户窗口。
9Gc'k1^&Se8y2h6H
F:L-A,ZB5s)Rz * 子窗口:当用户打开或创建一个文档时,客户窗口便为该文档创建一个子窗口。每个子窗口都有可以改变大小的边框、标题栏、系统菜单、最小最大化按钮等。任何时刻只有一个子窗口是活动的。子窗口不能超出客户窗口的范围。
4[PJ/t,y&|4X)FJ
'znv:Ct 用一般的开发工具开发MDI应用程序相当麻烦:你必须注册框架窗口和子窗口类、创建框架窗口和客户窗口、写消息循环和回调函数、创建子窗口等等,其中的每一步都不是什么轻而易举之事。但是在Borland C++ Builder(以下简称CB)中实现MDI应用程序却相对简单,你只需设置一下窗体的属性FormStyle即可:把框架窗口的FormStyle设为fsMDIForm,子窗口的FormStyle设为fsMDIChild。另外CB本身也提供了MDI程序模板,选择File|New|Projects|MDI Application,如下图所示:
UJ&\!H&v7H CB就会产生一个MDI应用程序框架。直接编译运行该程序,就可以看到该程序已经具有一个MDI程序的基本特征了。L%n v`?'X'b

a5aGCk7M2S 我们利用这个模板设计一个MDI应用程序。该程序是一个支持多文本格式和普通文本格式的多文档编辑器,且同时支持工具栏快捷按钮和打印输出。下面我们就来谈一谈其具体开发过程:
,G g9i7H c (1) 选择File|New|Projects|MDI Application,产生MDI程序框架。$k+lS#GT5Ro:Q
(2) 把主框架窗口另存为MDIMain.cpp,子窗口另存为MDIChild.cpp,工程名另存为MDI。N#i+}#]!^,G
(3) 转到主框架窗口FrameForm,设置其Caption为“ MDI演示程序---可打开多文件的文本编辑器”,在Object Inspector中观察FrameForm的属性,可看到其FormStyle为fsMDIForm。改变主框架窗口FrameForm上的控件(Component)._r nj"w\~+tK

5k!S f"S MgM3]hdG (4)点击菜单控件,改变菜单项和菜单项的OnClick事件如下,使之适合自己的要求:9fbr&i"iI*I5R
菜单项 菜单项的OnClick事件
L(VVn/m 文件:新建 New1Click3Z g{(L9w?4n
打开 Open1Click&l%u wRWY T%SO.I
退出 Exit1Click
$["[?5F5N$v8W 窗口:层叠 Tile1Click:V0uJR/~k"je
平铺 Cascade1Click
Jn6}4qC"Ol0Sm 排列图标 Arrangeicons1Click'x+bi:T6b#z,bp}I
(5) 改变SpeedPanel上的TSpeedButton控件和事件响应,并在其属性Glyph中装入相应的位图图像:
Z5Fs-it0J;cn 快捷按钮名称 事件响应
DJ(f[!G5y]@*v;k SpeedButton1 New1Click
'es S"n3M.~Q"P SpeedButton2 Open1Click
yyO6z8B!R!x,wi SpeedButton3 Exit1Click p } n-wE2U
(6)修改原有的OpenDialog文件打开对话框控件的属性:
Uh"Zf0ws [c 单击Filter属性,弹出Filter Editor对话框,输入:t`@Uq9A
Rich Text Format(*.rtf) *.rtf
(to1P4^?Sep!fK-j*x Text Files(*.txt) *.txt
.c;M]-hdc9@0d All Files(*.*) *.*EUFR,C o
(7) 选择View|Project Manager,在Project Manager中单击MDIChild一栏的ChildForm,就可以查看该子窗体的FormStyle属性为fsMDIChild。设置窗体的事件响应:
7ve"Zv I\/rqyS OnClick FormClick O+_[[@`{,u#{
OnClose FormClose
X]$~.PE(Qb~ OnCloseQuery FormCloseQuery
ZlA]9T g OnCreate FormCreate9r j9J3]!`|QXnS)W
拖动控件到ChildForm之上。6s\A(v.?j
~3t ?pn&tt2~0VkN
(8) 设置ChildForm上菜单控件的菜单项名称和菜单项的OnClick事件:
7AI7~+Oh'Q
i:w_8a&x R(vo9z'e 菜单项 菜单项的OnClick事件4L6QI&N&{w\)d
文件:新建 New1Click-t?(cyD%^ kJ6g
打开 Open1Click
YQ\;O \:T&J;L 关闭 Close1Click
];I(V;l%GDvq 保存 Save1Click2pc K+[1N5s,{
另存为 Saveas1Click
2It"|-c;N} 打印 Print1Click
9]J/li$B*CJY 打印设置 Printersetup1ClickrVLvPRW8p$i
退出 Exit1Click8v2y FtPly3j
编辑:剪切 Cut1Click
tHAgNv2e4s w0ql q3d4L 复制 Copy1Click T9^n(zd K&juV
粘贴 Paste1Click
[/H-E,g&SUmMq!n 删除 Delete1Click h2];OS{:w^N.|
全选 Selectall1Click
NdX!`@8?v 其他:靠左 Left1Click k+}0kW[,G u
靠右 Left1Click D\j s;M
居中 Left1Click Wvh$r H
自动换行 Wordwrap1Click']4e-z*e,`q^
字体 Font1Click
D"{,L(~v%[I @j (9) 从Dialogs控件板选取对话框控件到ChildForm上,并设置其属性:
7t#nL6zO*D6{Y * SaveDialogA4QS v9Y8`Q
Name SaveFileDialog
f'JQ J ^J.h:|;C 单击Filter属性,弹出Filter Editor对话框,输入:
@:t.G#pxsq Rich Text Format(*.rtf) *.rtfd,X#a/DUg3Y
Text Files(*.txt) *.txtSo5]MH|
All Files(*.*) *.*:BW(E7o5g F
* PrintDialog
V Rdn+KM4c Name PrintDialog1
W8RG4~5kdP;N:p8B+b9{o * PrinterSetupDialog
t1|OP7F*~ Name PrinterSetupDialog1eB(J#mNt]bN
* FontDialog
.j6_2a+UVf Name FontDialog1zM"N3T|4s;gs
(10) 然后从Win32控件板中选择RichEdit控件,放在ChildForm上,设置其属性:BZ*p6xZn D
Align alClient
+T xXv(v8P Name doc
D%s,XK3Q6Mry Za&v 点击Lines属性,弹出String list editor,清空里面的内容。0^(v2Y w|e C
vVs'@5TU4SYqd
(11) 最后,在程序中加入程序源代码。运行该程序,然后打开两个文档(该程序在C++ Builder 3.0和Windows 95下调试通过):J*Rb9G6J5F4Vm|'g
附源程序清单:
FxiM"E (这儿略去大部分系统自己加进去的程序代码部分):
/d~1sH ['[ //-------- MDIMain.cpp--------O uj@r7a&R p
#include "MDIMain.h""`Q9e2fw#O
#include "MDIChild.h"+T*Y3c1P7I
__fastcall TFrameForm::TFrameForm(TComponent* Owner):c\bC d$ryk]
: TForm(Owner)
!o0XKk"XL/^.q5k { }
W/MT(N\K void __fastcall TFrameForm::Exit1Click(TObject *Sender)/G*e nEWB*qgN({1lM
{Close();//应用程序退出} ~C0TM5T;s
void __fastcall TFrameForm::Tile1Click(TObject *Sender)6tC"ZF)M
{Tile();//窗口层叠}eY t;]6h0Jz
void __fastcall TFrameForm::Cascade1Click(TObject *Sender)
qRx2W{ h \ {Cascade();//窗口平铺} }-{8hw gD W)L
void __fastcall TFrameForm::Arrangeicons1Click(TObject *Sender)IP;x|L:bi
{ ArrangeIcons();//排列图标}"Qv:`v*^w?
//新建文档
e0o?]|q%t8c void __fastcall TFrameForm::New1Click(TObject *Sender)6_wX7Qz(Q
{ ChildForm = new TChildForm(this); }9b(A K%bZFxhY[
//打开文件
&a6j:{!m)hD v ii"p Fxp void __fastcall TFrameForm::Open1Click(TObject *Sender)
L/b%l Ahj_9[xC {
o,f%nE ]8t if(OpenFileDialog->Execute()){
b(Z(D9Y!t7O;v)} ChildForm=new TChildForm(this);
^'qXoO4{8H3w ChildForm->Open(OpenFileDialog->FileName);g$yr8h(yM0e D
}
yU(g,c C)G,?:Y } G ?uxwW
//----------MDIChild.cpp-------------
G2Xn#w"tE8SP #include "MDIChild.h"QadD1c
#include "MDIFrame.h"
L}6NB'a$PT/` TChildForm *ChildForm;+dvT)g&x'VeX9W x
//定义缺省文件名为Untitled/vXj,^M7VSV.E$_z
const AnsiString DefaultFileName = AnsiString("Untitled");
4v}(`TvDL6e^_ __fastcall TChildForm::TChildForm(TComponent* Owner)O&~Z"uf?
: TForm(Owner)Id2G!M I:C|&mw
{ }k_8M_M:[w xw
//文件打开函数
4K!F:_ o;Y0M/E(i void __fastcall TChildForm::Open(const AnsiString AFileName)
5^O NHD9V {
vo Y8|e7t!R PathName = AFileName;P fM ~ h7n| {&t
Caption = ExtractFileName(AFileName);
G2n&y],H;N8k doc->Lines->LoadFromFile(PathName);
2dN J/F9t@D doc->SelStart = 0;
J;EuXEEM@ doc->Modified = false;
3Em-_0x0IS }2_"LI#UF$d
void __fastcall TChildForm::New1Click(TObject *Sender)
u/D.a6pG n}S2Z0o { FrameForm->New1Click(Sender); //新建文件}
~7p-` J+nWr c void __fastcall TChildForm::Open1Click(TObject *Sender)
Jv[m[ { FrameForm->Open1Click(Sender);//打开文件 }
'o;fk _*A MW void __fastcall TChildForm::Close1Click(TObject *Sender)]&m] ^.D
{ Close();//关闭打开的文件},~j,DP7Fd
void __fastcall TChildForm::Exit1Click(TObject *Sender)
OXG7z g(XF0MC { FrameForm->Exit1Click(Sender);//退出应用程序 }iiH.SzH9F
//保存打开或创建的文档9R*pAP,?1B
void __fastcall TChildForm::Save1Click(TObject *Sender)
A-M mbul { ^xh!n'p
if(Caption == DefaultFileName){
w v5_ PS8A Saveas1Click(Sender); Y#tCugUNT/N
}cY l;} v??
else{~4J$cN Z"bt)WP7qg
doc->Lines->SaveToFile(PathName);9P/L tl m0H$A7K H
doc->Modified = false;euM ad$Q\^1j
} } H5Q,e | G
//另存打开或创建的文档
Ho ?/G:vh{ void __fastcall TChildForm::Saveas1Click(TObject *Sender)
9w,_-M kx3k8e {
gB-w h$q3|%~1dU SaveFileDialog->FileName = PathName;
3_'K6j8P7y]2M ?6k if (SaveFileDialog->Execute() ){
4Y1_ O6AN9?hC/\ PathName= SaveFileDialog->FileName;
Yld/]0DX,[_ r5@.Z Caption = ExtractFileName(PathName);
;q}w m-];A1P*R Save1Click(Sender);
?O@HhJ8j@ P` } }9q,X wil'k!hZy.z-^
//文档打印8W%H%U G~
void __fastcall TChildForm::Print1Click(TObject *Sender) hxo4l,r,p7A
{;]m4q xs6yD9Q;a+^f
if (PrintDialog1->Execute()){
QgX3AGW7V:_8C try {
0|6B+h6c:C4^A6~9T/U doc->Print(PathName);
_'Cj-ey:v }~ZD~Dg%j"{
catch(...){Ye4m[^0E
Printer()->EndDoc();
K5P`N0r d_.? throw;
xS:oSVN s;r } } }
!Ou!Z K G f)IT void __fastcall TChildForm::Printersetup1Click(TObject *Sender)
E f)YgIm@ { PrinterSetupDialog1->Execute();//打开打印机设置对话框进行打印机设置};zC@ MA8{ oE(D DbO#z
void __fastcall TChildForm::Cut1Click(TObject *Sender)_3j x*ji'r'zD
{doc->CutToClipboard();//文档剪切到剪贴板}"Jx-z(ZM `iU L1U
void __fastcall TChildForm::Copy1Click(TObject *Sender))E:zfD1^8B.Io,F
{ doc->CopyToClipboard();//文档拷贝到剪贴板}
"iH0_,t*g(j6Z"h~n void __fastcall TChildForm::Paste1Click(TObject *Sender)
W~0qY-\ { doc->PasteFromClipboard();//从剪贴板粘贴文档}
#WrUa\5~ void __fastcall TChildForm::Delete1Click(TObject *Sender)#x ]OT$I!Z$A[ `EF
{ doc->ClearSelection();//删除选中的文档}
ACT9B{0[N6R void __fastcall TChildForm::Selectall1Click(TObject *Sender)
#R r'j)a4F)qT { doc->SelectAll();//文档全选} `n-]n%c9M,_ m
//文档向左、向右、居中等各种对齐方式响应函数]zv2Bf9i3QG
void __fastcall TChildForm::Left1Click(TObject *Sender)
(R&MC R/|,daS2y Q {
8y:j_/j6Yzq4J.j"]K Left1->Checked = false;$M q"Pa;pa
Right1->Checked = false;
y q1R-}z*@f1J1N Center1->Checked = false;
[ vZe/J!O if( dynamic_cast(Sender) !=0)
4de8iHx dynamic_cast (Sender) ->Checked = true;ORn,Q+bg#gQI t
{d5A{Y~^bi&c
if (Left1->Checked )%w2P#]0pN&iy;]9V
doc->Paragraph->Alignment = taLeftJustify;/xk{TJM
else if (Right1->Checked)
1f/TUYK$NgYP U t doc->Paragraph->Alignment= taRightJustify;
~{:r4Y+ED7~k2h else if (Center1->Checked)
Z s,U4a}4FOB5T doc->Paragraph->Alignment = taCenter;)X'j} m\5R(d8Pj K
} }!d2^|;kX
//文档自动换行 B g(ISDpL9X.t
void __fastcall TChildForm::Wordwrap1Click(TObject *Sender)X pg,ce cI7f2o0wm
{+l"n$I|3Bi/f
doc->WordWrap = !doc->WordWrap; //toggle word wrapping
H}F Cj%P6n]-E if (doc->WordWrap)E^a&g ?`%Y0X-O
doc->ScrollBars = ssVertical;
6v$Dj3\B:_4L\ elsehx_ LB%L_(Z
doc->ScrollBars = ssBoth;
w!Jl+T!J?,A Wordwrap1->Checked = doc->WordWrap; // set menu item check
J3xiP8L5na.S!cO }%](sU{CF
//设置选中文档的字体.{:q"M#r5o`B"y
void __fastcall TChildForm::Font1Click(TObject *Sender)
ng2{sx'[y5Ny {FontDialog1->Font= doc->Font;
&Aa#av5v)uq/d8I if (FontDialog1->Execute())
.t2eC*@Ty ](zT,T doc->SelAttributes->Assign(FontDialog1->Font);
)xjt/S;M?s` }
_SJ Z&DE]!lA"Ei //子窗口鼠标单击响应函数
$p,Ki3R1N s void __fastcall TChildForm::FormClick(TObject *Sender)
:jL&}%iT1|J7RTX z {,I*`yY6P4c"@)`
bool HasSelection;*SC)D;B8o+i(?A
Paste1->Enabled = Clipboard()->HasFormat(CF_TEXT);
IjU N?l;W0N HasSelection = doc->SelLength > 0; N/M#gq;dQn
Cut1->Enabled = HasSelection;
K!q)vK K3{ A&bI\ Copy1->Enabled = HasSelection; LnCl$E2U.G[h
Delete1->Enabled = HasSelection;
-R]SP+b&|XOpS },SOc.uL$eZuQ
//子窗口关闭时事件响应
w!o/[qig.FG4K/wK void __fastcall TChildForm::FormClose(TObject *Sender, TCloseAction &Action)
D0Nm]&I[3K8y9H {Action=caFree; }
0Vv%F*O,F //子窗口关闭时询问事件响应$MPO\C
void __fastcall TChildForm::FormCloseQuery(TObject *Sender,
s:`&P qdUQ(qK.} bool &CanClose)
Y9S`V5i3gx9z.Ot {
9dDV'o$}#P @"J%|7w if (doc->Modified)
:P+t nMP6tNrU {%?2Vs/O0H2Q i
TMsgDlgButtons temp_set;
uaV] O(b temp_set<< mbYes<<mbNo <<mbCancel;
$iU`e^'YF String buffer = "Save changes to " + PathName;
lXdfbG BPR switch(MessageDlg(buffer, mtConfirmation,temp_set,0))
-zP+cx c*aR C {Ol\6~^7H
case mrYes: T'P.]/Cn)N%{)n
Save1Click(this);
C;Gx7MJ[ E break;0W,L/Z;jY
case mrCancel:
xL$E"iC&mGk CanClose=false; Q-T P!XhHg*b
break;;YE r;[8@"A
} }}
` P&W5Xah;m void __fastcall TChildForm::FormCreate(TObject *Sender)
*~(~ rd:W+hx-tz { PathName = DefaultFileName; }A1?|rT_&tdXb7v P
gn(K:Am.gh(w3UO4X
//---------MDIChild.h------------'|(Yku,t r
class TChildForm : public TFormjo]OZ-s.f
{
HY6d:lT private:    // User declarations
`7j-{M,bcw.k~ AnsiString PathName;//文档文件和路径名定义
Eu1Mjdy9a public:        // User declarations
+iX f3{t a'l void __fastcall Open(const AnsiString AFileName);//文档打开函数声明AY_+N(Y4|AXj
virtual __fastcall TChildForm(TComponent* Owner);
Fu.D{%F7LR };Ey+_nL4V6t
另外,你自己也可以根据上述开发思路来开发出各种各样的MDI程序,比如,你可以在文档中利用OLE加入图片,声音等多媒体因素,使你的文档更加丰富多彩!

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.