MDI(多文檔界面)應用程序是指用戶可以同時打開多個文檔,每一個文檔顯示在應用程序主窗口客戶區的獨立窗口中。如字處理程序Word就是一個典型的MDI應用程序,你可以在Word中同時打開和使用多個文檔,PowerPoint中你也可以同時創建和打開多個幻燈片應用程序,電子表格中也允許用戶同時對多個圖表進行編輯。MDI應用程序一般包括三類窗口:
* 框架窗口:框架窗口與應用程序的主窗口類似,有可改變大小的邊框、標題欄、系統菜單等。應用程序必須為框架窗口注冊一個窗口類。一個MDI應用程序一般只有一個框架窗口,框架窗口控制著其它各類窗口。
* 客戶窗口:客戶窗口提供對下屬MDI子窗口的管理,每一個MDI應用程序有一個客戶窗口。
* 子窗口:當用戶打開或創建一個文檔時,客戶窗口便為該文檔創建一個子窗口。每個子窗口都有可以改變大小的邊框、標題欄、系統菜單、最小最大化按鈕等。任何時刻只有一個子窗口是活動的。子窗口不能超出客戶窗口的范圍。
用一般的開發工具開發MDI應用程序相當麻煩:你必須注冊框架窗口和子窗口類、創建框架窗口和客戶窗口、寫消息循環和回調函數、創建子窗口等等,其中的每一步都不是什麼輕而易舉之事。但是在Borland C++ Builder(以下簡稱CB)中實現MDI應用程序卻相對簡單,你只需設置一下窗體的屬性FormStyle即可:把框架窗口的FormStyle設為fsMDIForm,子窗口的FormStyle設為fsMDIChild。另外CB本身也提供了MDI程序模板,選擇File|New|Projects|MDI Application,如下圖所示:
CB就會產生一個MDI應用程序框架。直接編譯運行該程序,就可以看到該程序已經具有一個MDI程序的基本特征了。
我們利用這個模板設計一個MDI應用程序。該程序是一個支持多文本格式和普通文本格式的多文檔編輯器,且同時支持工具欄快捷按鈕和打印輸出。下面我們就來談一談其具體開發過程:
(1) 選擇File|New|Projects|MDI Application,產生MDI程序框架。
(2) 把主框架窗口另存為MDIMain.cpp,子窗口另存為MDIChild.cpp,工程名另存為MDI。
(3) 轉到主框架窗口FrameForm,設置其Caption為“ MDI演示程序---可打開多文件的文本編輯器”,在Object Inspector中觀察FrameForm的屬性,可看到其FormStyle為fsMDIForm。改變主框架窗口FrameForm上的控件(Component).
(4)點擊菜單控件,改變菜單項和菜單項的OnClick事件如下,使之適合自己的要求:
菜單項 菜單項的OnClick事件
文件:新建 New1Click
打開 Open1Click
退出 Exit1Click
窗口:層疊 Tile1Click
平鋪 Cascade1Click
排列圖標 Arrangeicons1Click
(5) 改變SpeedPanel上的TSpeedButton控件和事件響應,並在其屬性Glyph中裝入相應的位圖圖像:
快捷按鈕名稱 事件響應
SpeedButton1 New1Click
SpeedButton2 Open1Click
SpeedButton3 Exit1Click
(6)修改原有的OpenDialog文件打開對話框控件的屬性:
單擊Filter屬性,彈出Filter Editor對話框,輸入:
Rich Text Format(*.rtf) *.rtf
Text Files(*.txt) *.txt
All Files(*.*) *.*
(7) 選擇View|Project Manager,在Project Manager中單擊MDIChild一欄的ChildForm,就可以查看該子窗體的FormStyle屬性為fsMDIChild。設置窗體的事件響應:
OnClick FormClick
OnClose FormClose
OnCloseQuery FormCloseQuery
OnCreate FormCreate
拖動控件到ChildForm之上。
(8) 設置ChildForm上菜單控件的菜單項名稱和菜單項的OnClick事件:
菜單項 菜單項的OnClick事件
文件:新建 New1Click
打開 Open1Click
關閉 Close1Click
保存 Save1Click
另存為 Saveas1Click
打印 Print1Click
打印設置 Printersetup1Click
退出 Exit1Click
編輯:剪切 Cut1Click
復制 Copy1Click
粘貼 Paste1Click
刪除 Delete1Click
全選 Selectall1Click
其他:靠左 Left1Click
靠右 Left1Click
居中 Left1Click
自動換行 Wordwrap1Click
字體 Font1Click
(9) 從Dialogs控件板選取對話框控件到ChildForm上,並設置其屬性:
* SaveDialog
Name SaveFileDialog
單擊Filter屬性,彈出Filter Editor對話框,輸入:
Rich Text Format(*.rtf) *.rtf
Text Files(*.txt) *.txt
All Files(*.*) *.*
* PrintDialog
Name PrintDialog1
* PrinterSetupDialog
Name PrinterSetupDialog1
* FontDialog
Name FontDialog1
(10) 然後從Win32控件板中選擇RichEdit控件,放在ChildForm上,設置其屬性:
Align alClient
Name doc
點擊Lines屬性,彈出String list editor,清空裡面的內容。
(11) 最後,在程序中加入程序源代碼。運行該程序,然後打開兩個文檔(該程序在C++ Builder 3.0和Windows 95下調試通過):
附源程序清單:
(這兒略去大部分系統自己加進去的程序代碼部分):
//-------- MDIMain.cpp--------
#include "MDIMain.h"
#include "MDIChild.h"
__fastcall TFrameForm::TFrameForm(TComponent* Owner)
: TForm(Owner)
{ }
void __fastcall TFrameForm::Exit1Click(TObject *Sender)
{Close();//應用程序退出}
void __fastcall TFrameForm::Tile1Click(TObject *Sender)
{Tile();//窗口層疊}
void __fastcall TFrameForm::Cascade1Click(TObject *Sender)
{Cascade();//窗口平鋪}
void __fastcall TFrameForm::Arrangeicons1Click(TObject *Sender)
{ ArrangeIcons();//排列圖標}
//新建文檔
void __fastcall TFrameForm::New1Click(TObject *Sender)
{ ChildForm = new TChildForm(this); }
//打開文件
void __fastcall TFrameForm::Open1Click(TObject *Sender)
{
if(OpenFileDialog->Execute()){
ChildForm=new TChildForm(this);
ChildForm->Open(OpenFileDialog->FileName);
}
}
//----------MDIChild.cpp-------------
#include "MDIChild.h"
#include "MDIFrame.h"
TChildForm *ChildForm;
//定義缺省文件名為Untitled
const AnsiString DefaultFileName = AnsiString("Untitled");
__fastcall TChildForm::TChildForm(TComponent* Owner)
: TForm(Owner)
{ }
//文件打開函數
void __fastcall TChildForm::Open(const AnsiString AFileName)
{
PathName = AFileName;
Caption = ExtractFileName(AFileName);
doc->Lines->LoadFromFile(PathName);
doc->SelStart = 0;
doc->Modified = false;
}
void __fastcall TChildForm::New1Click(TObject *Sender)
{ FrameForm->New1Click(Sender); //新建文件}
void __fastcall TChildForm::Open1Click(TObject *Sender)
{ FrameForm->Open1Click(Sender);//打開文件 }
void __fastcall TChildForm::Close1Click(TObject *Sender)
{ Close();//關閉打開的文件}
void __fastcall TChildForm::Exit1Click(TObject *Sender)
{ FrameForm->Exit1Click(Sender);//退出應用程序 }
//保存打開或創建的文檔
void __fastcall TChildForm::Save1Click(TObject *Sender)
{
if(Caption == DefaultFileName){
Saveas1Click(Sender);
}
else{
doc->Lines->SaveToFile(PathName);
doc->Modified = false;
} }
//另存打開或創建的文檔
void __fastcall TChildForm::Saveas1Click(TObject *Sender)
{
SaveFileDialog->FileName = PathName;
if (SaveFileDialog->Execute() ){
PathName= SaveFileDialog->FileName;
Caption = ExtractFileName(PathName);
Save1Click(Sender);
} }
//文檔打印
void __fastcall TChildForm::Print1Click(TObject *Sender)
{
if (PrintDialog1->Execute()){
try {
doc->Print(PathName);
}
catch(...){
Printer()->EndDoc();
throw;
} } }
void __fastcall TChildForm::Printersetup1Click(TObject *Sender)
{ PrinterSetupDialog1->Execute();//打開打印機設置對話框進行打印機設置}
void __fastcall TChildForm::Cut1Click(TObject *Sender)
{doc->CutToClipboard();//文檔剪切到剪貼板}
void __fastcall TChildForm::Copy1Click(TObject *Sender)
{ doc->CopyToClipboard();//文檔拷貝到剪貼板}
void __fastcall TChildForm::Paste1Click(TObject *Sender)
{ doc->PasteFromClipboard();//從剪貼板粘貼文檔}
void __fastcall TChildForm::Delete1Click(TObject *Sender)
{ doc->ClearSelection();//刪除選中的文檔}
void __fastcall TChildForm::Selectall1Click(TObject *Sender)
{ doc->SelectAll();//文檔全選}
//文檔向左、向右、居中等各種對齊方式響應函數
void __fastcall TChildForm::Left1Click(TObject *Sender)
{
Left1->Checked = false;
Right1->Checked = false;
Center1->Checked = false;
if( dynamic_cast<TMenuItem *>(Sender) !=0)
dynamic_cast <TMenuItem *>(Sender) ->Checked = true;
{
if (Left1->Checked )
doc->Paragraph->Alignment = taLeftJustify;
else if (Right1->Checked)
doc->Paragraph->Alignment= taRightJustify;
else if (Center1->Checked)
doc->Paragraph->Alignment = taCenter;
} }
//文檔自動換行
void __fastcall TChildForm::Wordwrap1Click(TObject *Sender)
{
doc->WordWrap = !doc->WordWrap; //toggle word wrapping
if (doc->WordWrap)
doc->ScrollBars = ssVertical;
else
doc->ScrollBars = ssBoth;
Wordwrap1->Checked = doc->WordWrap; // set menu item check
}
//設置選中文檔的字體
void __fastcall TChildForm::Font1Click(TObject *Sender)
{FontDialog1->Font= doc->Font;
if (FontDialog1->Execute())
doc->SelAttributes->Assign(FontDialog1->Font);
}
//子窗口鼠標單擊響應函數
void __fastcall TChildForm::FormClick(TObject *Sender)
{
bool HasSelection;
Paste1->Enabled = Clipboard()->HasFormat(CF_TEXT);
HasSelection = doc->SelLength > 0;
Cut1->Enabled = HasSelection;
Copy1->Enabled = HasSelection;
Delete1->Enabled = HasSelection;
}
//子窗口關閉時事件響應
void __fastcall TChildForm::FormClose(TObject *Sender, TCloseAction &Action)
{Action=caFree; }
//子窗口關閉時詢問事件響應
void __fastcall TChildForm::FormCloseQuery(TObject *Sender,
bool &CanClose)
{
if (doc->Modified)
{
TMsgDlgButtons temp_set;
temp_set<< mbYes<<mbNo <<mbCancel;
String buffer = "Save changes to " + PathName;
switch(MessageDlg(buffer, mtConfirmation,temp_set,0))
{
case mrYes:
Save1Click(this);
break;
case mrCancel:
CanClose=false;
break;
} }}
void __fastcall TChildForm::FormCreate(TObject *Sender)
{ PathName = DefaultFileName; }
//---------MDIChild.h------------
class TChildForm : public TForm
{
private: // User declarations
AnsiString PathName;//文檔文件和路徑名定義
public: // User declarations
void __fastcall Open(const AnsiString AFileName);//文檔打開函數聲明
virtual __fastcall TChildForm(TComponent* Owner);
};
另外,你自己也可以根據上述開發思路來開發出各種各樣的MDI程序,比如,你可以在文檔中利用OLE加入圖片,聲音等多媒體因素,使你的文檔更加豐富多彩!
(全文完)