用C++ Builder3 制作NotePad(记事本)
用C++ Builder3 制作NotePad(記事本)
?
啟動(dòng)C++ Builder3后,在File菜單中選New APPlication來(lái)建立一個(gè)新程序。這時(shí),顯示在屏幕中間的窗口的標(biāo)題是Form1,這個(gè)窗口是程序的主表單(就是主窗口的意恩),它將在程序啟動(dòng)時(shí)自動(dòng)顯示。而以后再創(chuàng)建的表單(Form)一般需要用Show()方法(Method)來(lái)顯示。和組件一樣,系統(tǒng)為第一個(gè)表單起名為Form1,以后的表單起名為Form2、Form3等等,標(biāo)題(Caption)也是如此。
?? 當(dāng)然,你可以將它們改成你喜歡的名字。我們先來(lái)把Form1的名字(Name)屬性設(shè)為MainForm,把MainForm的標(biāo)題(Caption)屬性設(shè)為“Untited.txt--我的記事本”。接著可以用鼠標(biāo)拖動(dòng)窗口的位置和改
變窗口的大小。以上的這些工作,幾乎每個(gè)程序都需要如法炮制一番。
?? 隨后,我們要開始NotePad的編程工作了。知己知彼,百戰(zhàn)不殆,先來(lái)分析一下MicroSoft NotePad的結(jié)構(gòu)。其實(shí)NotePad是附件里最簡(jiǎn)單的程序了,它的主窗口中只包含一個(gè)占據(jù)全部用戶區(qū)域(Client Area)的多行的編輯控制(Edit)。由于編輯控制最多容納64KB文字(Windows95),所以NotePad只能打開小于64KB的文件。好,我們來(lái)依樣畫葫蘆,選擇Standard中的多行編輯(Memo)組件(而不是單行編輯組件)。
?? 放入表單中,將多行編輯Memo1的Align屬性設(shè)為alClient,這時(shí)Memo1撐滿了整個(gè)窗口,Memo1中顯示的是Memo1。選擇Memo1的Lines屬性,[TString]后面出現(xiàn)了一個(gè)按鈕。
?? 單擊該按鈕,將出現(xiàn)一個(gè)設(shè)置Lines屬性的對(duì)話框,其中第一行便是“Memo1”。多行編輯(Memo)組件的Lines屬性在設(shè)計(jì)時(shí)(Design Time)設(shè)定的內(nèi)容將在該窗口創(chuàng)建時(shí)自動(dòng)顯示。由于我們不需要顯示什么,所以把“Memo1”擦掉,選OK退出。你一定想看看目前的效果,運(yùn)行一下吧。編譯……連接……啟動(dòng)程序……怎
么樣,是不是和NotePad一模一樣,能打字、刪字、刪行,還能使用右鍵菜單來(lái)復(fù)制(copy)和粘貼(paste)。
?? 本來(lái)就是嘛,用一樣的編輯控制,不一樣才怪呢。哎,不對(duì),好像字體小了點(diǎn),而且沒有滾動(dòng)條。沒有關(guān)
系,關(guān)閉程序回到C++ Builder3中,先修改Memo1的字體(Font)屬性,選擇system字體(當(dāng)然你愛選什么字
體都可以),然后設(shè)置滾動(dòng)條(ScrollBars)屬性,選擇ssBoth(兩根滾動(dòng)條都要)。在這些改動(dòng)之后,先別急著運(yùn)行,windows的程序沒菜單是不行的。在C++ Builder中,菜單也是組件之一。選擇Standard中的主菜單(MainMenu)組件放入表單中。主菜單(MainMenu)組件顯示為一個(gè)圖標(biāo)。順便提一句菜單,對(duì)話框或系統(tǒng)功能之類組件屬于非可視組件(nonvisual components),它們的工作基本不是用來(lái)滿足視覺的,或者在程序運(yùn)行時(shí)根本就看不見(相對(duì)于界面上可視組件來(lái)說(shuō)),因此你可以將非可視組件放在表單中的任意位置。
?? 接下來(lái)的工作是制作菜單,雙擊主菜單MainMenu1的圖表,會(huì)彈出菜單編輯窗口,開始時(shí)是一個(gè)空菜單。按右鍵會(huì)彈出一個(gè)菜單(不是我們要做的菜單),其中:
Insert(添加一個(gè)菜單項(xiàng),按Insert鍵完成相同的功能)
Delete(刪除一個(gè)菜單項(xiàng),按Delete鍵完成相同的功能)
Create SubMenu(添加一個(gè)子菜單,按Ctrl + →鍵完成相同的功能)
Select Menu(選擇一個(gè)菜單,用來(lái)關(guān)閉當(dāng)前編輯的菜單并選擇另一個(gè)菜單來(lái)編輯)
Save as Template(將當(dāng)前菜單保存為模板,供以后使用)
Insert From Template(將已有的菜單模板加入當(dāng)前菜單)
Delete Template(刪除菜單模板)
Insert From Resource(從資源文件中取得菜單加入當(dāng)前菜單)
?? 制作“我的記事本”的菜單有一種偷懶的方法,就是照抄Microsoft記事本的菜單。你可以用BC5.02的IDE打開Notepad.exe(先把打開文件對(duì)話框中的Viewer設(shè)為Edit Resource,再把文件類型設(shè)為Exe cutable(*.exe),這樣才是以編輯資源的方式打開EXE文件,否則默認(rèn)的打開方式是Debug調(diào)試程序),將里面的菜單導(dǎo)出以RC(資源腳本)方式存盤,然后用Insert From Resource導(dǎo)入該菜單;一共用不了2分鐘。
?? 還有一種方法就是自己一項(xiàng)一項(xiàng)慢慢地做。當(dāng)然,不管你用什么方法,最后都要做出菜單來(lái)才能繼續(xù)下面的工作。下面附上從Windows NT4.0中Notepad導(dǎo)出的菜單的資源腳本menu.rc,把下面的文件以menu.rc存盤就能用C++ Builder3來(lái)導(dǎo)入了:
1 MENU
{ POPUP "文件(&F)"
? { MENUITEM "新建(&N)", 9
??? MENUITEM "打開(&O)...", 10
??? MENUITEM "保存(&S)", 1
??? MENUITEM "另存為(&A)...", 2
??? MENUITEM SEPARATOR
??? MENUITEM "頁(yè)面設(shè)置(&T)...", 32
??? MENUITEM "打印(&P)", 14
??? MENUITEM SEPARATOR
??? MENUITEM "退出(&X)", 28
? }
? POPUP "編輯(&E)"
? { MENUITEM "撤消(&U)\tCtrl+Z", 25
??? MENUITEM SEPARATOR
??? MENUITEM "剪切(&T)\tCtrl+X", 768,GRAYED
??? MENUITEM "復(fù)制(&C)\tCtrl+C", 769, GRAYED
??? MENUITEM "粘貼(&P)\tCtrl+V", 770,GRAYED
??? MENUITEM "刪除(&L)\tDel",771, GRAYED
??? MENUITEM SEPARATOR
??? MENUITEM "全部選定(&A)", 7
??? MENUITEM "時(shí)間/日期(&D)\tF5",12
??? MENUITEM SEPARATOR
??? MENUITEM "自動(dòng)換行(&W)", 27
??? MENUITEM "設(shè)置字體(&F)...", 37
? }
? POPUP "搜索(&S)"
? { MENUITEM "查找(&F)...", 3
??? MENUITEM "查找下一個(gè)(&N)\tF3", 8
??? MENUITEM "替換(&R)"', 40
? }
? POPUP "幫助(&H)"
? { MENUITEM "幫助主題(&H)", 5
??? MENUITEM SEPARATOR
??? MENUITEM "關(guān)于記事本(&A)...",11
? }
}
關(guān)于菜單,還有兩點(diǎn)要提:
1.一般沒有必要去改動(dòng)菜單項(xiàng)的Name屬性,使用系統(tǒng)給出的默認(rèn)名就可以了。
2.以“-”為標(biāo)題的菜單項(xiàng)即是菜單分割條,而菜單項(xiàng)的Break屬性提供的分割則是一種很奇怪的樣子--“垂直分害條”(群山笑:這個(gè)名詞是我自已加上的)。
?? OK,到此為止,界面部分的工作已經(jīng)全部完成了,接下來(lái)便是代碼部分的編寫。首先要做的就是打開文件和存盤的工作。我們來(lái)建立一個(gè)char *UserFileName的全局變量來(lái)存放文件名。按工具條上的Toggle Form/Uint將工作窗口切換到代碼編輯區(qū)。這個(gè)按鈕用于表單編輯區(qū)和代碼編輯區(qū)的相互切換,按F11顯示對(duì)象觀察器。在“TMainForm *MainForm;”下加語(yǔ)句:
char *UserFileName="untitled.txt";//默認(rèn)文件名Untitled.txt
BOOL If_saved=TRUE;//表示文件存盤與否
char title_buf[256];//標(biāo)題的內(nèi)容
?? 接著,我們?cè)偾袚Q回表單編輯區(qū),從Dialogs組件條中選SaveDialog組件放入表單中。
?? SaveDialog組件就是用來(lái)顯示Save As對(duì)話框的,當(dāng)然用Windows API也能實(shí)現(xiàn)此功能,這里將使用SaveDialog組件。將SaveDialog1的DefaultExt(默認(rèn)的擴(kuò)展名)屬性設(shè)為.txt,這表示如果用戶沒有加擴(kuò)展名,系統(tǒng)會(huì)自動(dòng)加上“.txt”。按Filter屬性后的[…]按鈕,在彈出的對(duì)話框中輸入“文本文件”“*.txt”“所有文件”“*.*”。另外再雙擊Options屬性,將展開后其中的ofOverwritePrompt(文件覆蓋提醒)屬性設(shè)為true。接著在表單編輯區(qū)的菜單中選菜單項(xiàng)“另存為(A)...”,這時(shí)C++ Builder3會(huì)自動(dòng)切換到代碼編輯區(qū),而光標(biāo)停在一個(gè)函數(shù)的開頭。在該例中菜單項(xiàng)“另存為(A)…”的名字屬性是A1,所以這個(gè)函數(shù)的名字是A1Click(TObject * Sender),表示用戶選擇(Click)這個(gè)菜單項(xiàng)而執(zhí)行的函數(shù)。我們所要做的是彈出Save As對(duì)話框來(lái)獲得用戶輸入的文件名,并將這個(gè)文件存盤。所以在這個(gè)函數(shù)里加如下的語(yǔ)句:
if(!SaveDialog1->Execute()) return; //如果用戶選擇了取消,我們就return
UserFileName = SaveDialog1 -> FileName.c_str();
/ * FileName保存了用戶輸入的文件名,但是AnsiString類型的,用其中的c_str()方法可以將其轉(zhuǎn)換成字符串*/
Memo1 ->Lines->SaveToFile(UserFlleName);
If_saved=TRUE; //已經(jīng)存盤
sprintf(title_buf,"% s - 我的記事本”, UserFileName); /* 設(shè)置窗口的標(biāo)題,記得要加上include <stdio.h> * /
Caption=title_buf;
/ * Memo中的Lines屬性即是編輯控制中的內(nèi)容,Lines屬性是Strings類型的,用其中提供的SaveToFile方法可以方便地將編輯控制中的內(nèi)容存盤 */
?? 類似地,我們?cè)賮?lái)處理打開文件的工作。首先,在表單中放置一個(gè)OpenDialog組件,DefaultExt和Filter
屬性同SaveDialog1,將Options屬性中的ofFileMustExist(文件必須存在)設(shè)為true。然后在表單編輯區(qū)中
的菜單中選菜單項(xiàng)“打開(O)...”,在代碼編輯區(qū)中輸入如下語(yǔ)句。
if(!if_saved)
if(Application ->MessageBox("文件還未保存,是否要保存?","我的記事本",
MB_OKCANCEL+MB_DEFBUTTON1+MB_ICONWARNING)==ID_OK) S1Click(NULL);
/ * 如果文件沒有保存,我們得先征求用戶是否要保存文件。s1Click()是“保存(s)”菜單項(xiàng)的處理函數(shù)(就是接下來(lái)處理的菜單項(xiàng)),“保存(S) ”菜單項(xiàng)的工作就是將文件存盤,所以我們沒有必要寫重復(fù)的代碼,而只要直接調(diào)用該函數(shù)就可以了。注意,如果你的“保存(S)”菜單項(xiàng)的名字屬性不是S1而是其他,那么這個(gè)函數(shù)的名字也會(huì)有所不同,但總是“名字”+Click() */
if(!OpenDialog1->Execute())return;
UserFileName=OpenDialog1->FileName.c_str();
Memo1->Lines->LoadFromFile(UserFileName);
sprintf(title_buf,"% s - 我的記事本", UserFileName);
Caption = title_buf;
(為節(jié)省篇幅,以下凡是重復(fù)的操作描述省略)
?? 處理“保存(S)”菜單項(xiàng),輸入:
Memo1->Lines->SaveToFile(UserFileName);
If_saved=TRUE;
sprintf(title_buf,"% s - 我的記事本", UserFileName)";
Caption = title_buf;
?? 處理“新建(N)”菜單項(xiàng),輸入如下語(yǔ)句:
lf(!If_saved)
if(Application ->MessageBox ("文件還未保存,是否要保存?","我的記事本",
MB_OKCANCEL+MB_DEFBUTTON1+MB_ICONWARNING)==ID_OK)S1Click(NULL);
sprintf(UserFileName,"Untitled.txt");
sprintf(title_buf, "% s - 我的記事本-未存盤",UserFileName);
Caption=title_buf;
Memo1->Lines->Clear(); //將編輯控制中的內(nèi)容清空
?? 隨后,我們要處理Memo1的OnChange事件(Events)。一旦編輯控制中的內(nèi)容有改變,Memo1就將產(chǎn)生OnChange事件,這時(shí)需要將If_saved置為FALSE,表示文件已經(jīng)改動(dòng)過了,并在標(biāo)題上顯示“未存盤”。在對(duì)象觀察器中選Memo1,再單擊下面的Events,將列出許多事件,第一個(gè)就是OnChange,雙擊后面的編輯框,后面的操作和處理菜單項(xiàng)是一樣的(其實(shí)前面處理的菜單項(xiàng)就是處理菜單的OnClick事件),輸入:
If_saved=FALSE;
sprintf(title_buf,"% s -我的記事本-未存盤", UserFileName);
Caption=title_buf;
?? 隨后處理MainForm的OnClose事件,輸入:
//OnClose事件在關(guān)閉窗口時(shí)產(chǎn)生,需要做一些收尾工作
if(!If_saved)
if(application->MessageBox("文件還未保存,是否要保存?","我的記事本",
MB_OKCANCEL+MB_DEFBUTTON1+MB_ICONWARNING)==ID_OK)S1Click(NULL);
?? 最后,處理“退出(X)”菜單項(xiàng),輸入如下語(yǔ)句:
if(!If_saved)
if(application->MessageBox("文件還未保存,是否要保存?","我的記事本",
MB_OKCANCEL+MB_DEFBUTTON1+MB_ICONWARNING)==ID_OK)S1Click(NULL);
Application->Terminate(); //程序結(jié)束
?? 到此為止,終于小功告成了,快把項(xiàng)目保存下來(lái)吧。在File菜單中選Save Project As…,首先彈出的對(duì)
話框要求輸入表單的文件名(不能和表單的名字屬性相同),我們就輸入Main。隨后彈出的對(duì)話框才是要求輸入項(xiàng)目(Project)的文件名,該文件名也就是exe文件的名字,我們輸入NotePad。保存后再選Project菜單
里的Make NotePad,或按Ctrl+F9,就會(huì)產(chǎn)生一個(gè)NOtePad.exe,這就是我們自己做的記事本,目前它已經(jīng)能打開文件、編輯并保存。你一定發(fā)現(xiàn)菜單中還有許多功能尚未實(shí)現(xiàn),這就是我只說(shuō)小功告成的原因,不過
下次我們會(huì)完成它。
?? 附件中除了記事本(NotePad),還有一個(gè)寫字板(WordPad)。它們最大的區(qū)別在于前者使用的是編輯
控制(Edit),而后者使用的是Rich Edit控制(有些書翻譯成豐富文本控制)。與編輯控制相比,Rich Edit除了能給文本加上各種修飾,還支持簡(jiǎn)單的對(duì)象鏈接和嵌入技術(shù)(Object Linking and Embedding)。
?? 此外,Microsoft Win32 SDK的文檔中說(shuō)Rich Edit控制能接受的文本大小將只受內(nèi)存大小的限制,這比
編輯控制的64KB強(qiáng)多了。當(dāng)然,效率又是另一個(gè)問題。我曾試圖用寫字板(WordPad)打開一個(gè)15MB的文件,硬盤讀了10多分鐘還沒結(jié)果,只能按Reset重新啟動(dòng)了(我可有64MB內(nèi)存哦)。自然使用Rich Edit控制也比編輯控制難的多。在以后講到RichEdit組件時(shí),詳細(xì)講述它的用法。
用C++ Builder3 制作NotePad(記事本)續(xù)篇
?
?上回說(shuō)到“我的記事本”小功告成,copy給朋友一份,咦,不能用,說(shuō)是缺文件?噢,像VB的VBRUN???
.dll一樣,C++ Builder3編譯的程序也需要運(yùn)行庫(kù)的支持的。找到并打開它看看我們還有些什么沒有做?首先是關(guān)于菜單的快捷鍵問題。如果你是使用我上次所給的資源腳本導(dǎo)人的菜單,你會(huì)發(fā)現(xiàn)帶有快捷鍵的菜單項(xiàng)的文字都像“撒消(U)\tCtrl+Z”一樣。以前用BC的資源編輯器做過菜單的朋友都知道,“\t”表示右對(duì)齊,而在C++ Builder3中也作為菜單的文字了。另外C++ Builder3中的快捷鍵的建立也簡(jiǎn)單的多,快捷鍵已經(jīng)作為菜單的ShortCut屬性了。這里,僅改動(dòng)“編輯(E)”中的“撒消(U)Ctrl+Z”項(xiàng)來(lái)示眾,其余皆可依樣而畫葫蘆之。
?? 先雙擊MainMenu1菜單組件,進(jìn)入菜單編輯器,選中“編輯(E)”中的“撤消(U)Ctrl+Z”項(xiàng)。接著將Caption屬性改為“撤消(U)”(即把“\tCtrl+Z”刪去),并在shortCut矚性中選擇Ctrl+Z。這樣,該項(xiàng)的快捷鍵就設(shè)完了。接著是編輯菜單里的各個(gè)項(xiàng)。首先是“撤消(&U)Ctrl+Z”到“全部選定(&A)”六項(xiàng)(必須先將他們的Enabled屬性都設(shè)為true),C++ Builder3為這些功能提供了現(xiàn)成的方法(Method)。比如“撤消(&U)Ctral+Z”菜單,可以使用Undo方法,即在該菜單的OnClick事件處理函數(shù)中輸入“Memo1->Undo();”。同理有:
??? “剪切(&T)\tCtrl+X”項(xiàng),輸入:“Memo1->CutToClipboard();”
??? “復(fù)制(&C)\tCtrl+C”項(xiàng),輸入:“Memo1->CopyToClipboard();”
??? “粘貼(&P)\tCtrl+V”項(xiàng),輸入:“Memo1->PasteFromClipboard();”
??? “刪除(&L)\tDel”項(xiàng),輸入:“Memo1->ClearSelection();”
??? “全部選定(&A)”項(xiàng),輸入:“Memo1->SelectAll();”
?? 下面是“時(shí)間/日期(&D)F5”項(xiàng),我們必須先取得當(dāng)前的日期和時(shí)間。有兩種方法,一種是用getdate和
gettime函數(shù),一種是用C++ Builder3中的TDateTime類。這里選擇后一種,但有時(shí)使用getdate和gettime函數(shù)會(huì)更簡(jiǎn)便。下面給出該菜單項(xiàng)的處理代碼:
TDateTime * Current_DateTime =newTDateTime; //生成TDateTime對(duì)象
* Current_DateTime=Current_DateTime->CurrentDateTime(); //獲取當(dāng)前日期和時(shí)間
Memo1->SetselTextBuf(Current_DateTime->DateTimeString().c_str());//將當(dāng)前日期和時(shí)間轉(zhuǎn)換成字符串,并用SetSelTextBuf方法插入當(dāng)前光標(biāo)位置
?? 接著是處理‘自動(dòng)換行(&W)”的代碼:
//W1是“自動(dòng)換行(&W)”菜單項(xiàng)的名字(Name)屬性,如果你不是W1,請(qǐng)做相應(yīng)的改動(dòng)
if(W1->Checked) //該菜單已經(jīng)檢取(Checked)
{W1->Checked=false; //取消檢取
Memo1->ScrollBars=ssBoth; //Memo1兩根滾動(dòng)條都要
} else
{ W1->Checked=true; //設(shè)置檢取
Memo1->ScrollBars = ssVertical; //Memo1只設(shè)垂直滾動(dòng)條,效果就是自動(dòng)換行
}
?? 接下來(lái)處理“設(shè)置字體(&F)...”菜單,我們首先需要一個(gè)設(shè)置字體的公用對(duì)話框。從Dialogs組件條中選FontDialog組件放入表單中。下面是處理“設(shè)置字體(&F)...”的代碼:
if(FontDialog1->Execute())Memo1->Font=FontDialog1->Font;
?? 至此,“編輯(E)”菜單的功能都處理完了,下面將是處理“搜索(S)”菜單的工作。其中,我們又將用到兩個(gè)公用對(duì)話框。C++ Builder3只提供了用來(lái)獲取用戶欲查我的字符串的對(duì)話框,并未提供具體查找的函數(shù),所以我們得自己寫處理函數(shù)。下面我給出修改的Win32 SDK的范例代碼,你需要將這些代碼插在程序的首部,即定義全局變量的地方。
typedef enum {
??? frtFind
??? frtReplace,
??? frtRepAll
} FRT
#define GETSEL(ichS,ichE) \ SendMessage(MainForm - > Memo1 - > Handle,
EM_GETSEL,(WPARAM) & ichs, (LPARAM) & ichE)
#define SETSEL(ichS,ichE) \SendMessage(MainForm - > Memo1 - > Handle,
EM_SETSEL, (WPARAM) ichS, (LPARAAM) ichE)
BOOL FWholeWord(char * sz, char * szStart, char * szEnd,
int cch) {
??? if ( sz! = szStart & &
??????? * (sz - 1 ) ! = ' ' & &
??????? * (sz - 1 ) ! = '\t' & &
??????? * (sz - 1 ) ! = ',' & &
??????? * (sz - 1 ) ! = '.' & &
??????? * (sz - 1 ) ! = '\r'
??? ) { return FALSE;
??? }
??? if ( sz + cch! = szEnd & &
??????? * (sz + cch) ! = ' ' & &
??????? * (sz +cch) ! = '\t' & &
??????? * (sz + cch) ! = ',' & &
??????? * (sz + cch) ! = '.' & &
??????? * (sz + cch) ! = '\r'
??? ) { return FALSE;
??? }
??? return TRUE;
}
BOOL Find(char * szFind, BOOL fDown, BOOL fMatchCase, BOOL fWholeWord, BOOL fNoScroll)
{ char * szText;
??? UINT ichStart;
??? UINT ichEnd;
??? UINT cch;
??? int dch;
??? int dchComp;
??? char * szTerm;
??? char * sz;
??? UINT cchFind;
??? BOOL fFound = FALSE;
??? int dcbOnFind;
??? szText = MainForm - > Memo1 - > Lines - > GetText();
??? cchFind = strlen (szFind);
??? GETSEL(ichStart, ichEnd);
??? cch = strlen(szText);
??? if (
??????? ichEnd - ichStart = = cchFind & &
??????? !strnicmp(szText + ichStart, szFind, cchFind)
??????? )
??????? dchOnFind = 1;
??? else
??????? dchOnFind = 0;
??? if (fDown)
??????? { dch = 1;
??????? dchComp = 0;
??????? sz = szText + ichStart + dchOnFind;
??????? szTerm = szText + cch;
??????? }
??? else
??????? { dch = -1;
??????? dchComp = 1;
??????? sz = szText + ichStart - dchOnFind;
??????? szTerm = szText;
??? }
??? for (; sz + dchComp! = szTerm; sz + = dch)
??? {
????? if (
??????? tolower(* sz) = = tolower( * szFind) & &
??????? (fMatchCase ?
??????????? !strncmp(sz, szFind, cchFind) :
??????????? !strnicmp (sz, szFind, cchFind)
??????? ) & &
??????? ( !fWholeWord || FWholeWord(sz, szText, szTerm,cchFind)))
??????? { SendMessage(MainForm -> Memo1 -> Handle,EM_SETSEL, sz-szText, sz-szText + cchFind);
??????? if (!fNoScroll)
??????????? SendMessage(MainForm - > Memo1 - > Handle,EM_SCROLLCARET, 0, 0L);
??????? fFound = TRUE;
??????? break;
????? }
??? }
??? if ( !fNoScroll & & !fFound)
??????? MessageBox(NULL, szFind, "字 符 串 沒 有 找 到",MB_OK);
??? return fFound;
??? }
??? VOID Replace(char * szReplace) {SendMessage(MainForm - > Memo1 - > Handle,
??? EM_REPLACESEL, 0, (LPARAM) (LPSTR) szReplace);
??? }
??? VOID ReplaceAll(char * szFind, char * szReplace, BOOLfMatchCase, BOOL fWholeWord)
??? { UINT ichStart;
????? UINT ichEnd;
????? GETSEL(ichStart, ichEnd);
????? SETSEL(0, 0);
????? while(Find(szFind, TRUE, fMatchCase, fWholeWord,TRUE)) {
????? Replace (szReplace);
????? }
????? SETSEL(ichStart, ichEnd);
??? }
??? VOID FindReplace(
??????? char * szFind, char * szReplace,
??????? FRT frt,
??????? BOOL fDown, BOOL fMatchCase, BOOL fWholeWord)
??? { switch (frt)
????? { case frtFind:
??????? Find(szFind, fDown, fMatchCase, fWholeWord,FALSE);
??????? break;
????? case frtReplace:
??????? Find(szFind, fDown, fMatchCase, fWholeWord,FALSE);
??????? Replace (szReplace);
??????? break;
????? case frtRepAll:
??????? ReplaceAll(szFind, szReplace, fMatchCase, fWholeWord);
??? }
}
?? 這些代碼本來(lái)并不是給C++ Builder用的,但我們只要稍加改動(dòng)就能使用了,這也為我們移植以前的代碼提供了新思路,即一般只要將過去程序中的窗口或控制的句柄(HWND)用C++Builder中表單或組件的Handle屬性來(lái)代替,將過去程序中的程序事例句柄用HInstance代替,就能方便的完成移植。回到程序中來(lái),上面有5個(gè)函數(shù)和2個(gè)宏,其實(shí)我們直接使用的只有FindReplace函數(shù)。先在表單上放上FindDialog和ReplaceDialog兩個(gè)對(duì)話框,隨后寫“查找(F)...”菜單項(xiàng)的處理代碼:
FindDialog1->Execute();
?? 你可能會(huì)很奇怪,這么簡(jiǎn)單,那查找的過程在哪里呢?當(dāng)用戶按了查找對(duì)話框的[查找下一個(gè)(F)]按鈕后,會(huì)產(chǎn)生FindDialog的OnFind事件,在該事件的處理函數(shù)中進(jìn)行查找工作。如何編寫組件的事件函數(shù)?
(1)在表單編輯區(qū)選中該組件(這里是FindDialog1);
(2)在對(duì)象觀察器(如果沒有顯示,按F11調(diào)出)中選擇Event(事件),系統(tǒng)將列出事件;
(3)雙擊事件后面的編輯框(這里是OnFind),系統(tǒng)將切換入代碼編輯區(qū);
(4)輸入事件處理代碼。
下面給出OnFind的處理代碼:
MainForm - > SerFocus();
FindReplace(FindDialog1 - > FindText.c_str(), "", frtFind,
??? FindDialog1 - > Options. Contains(frDown),
??? FindDiaiog1 - > Options.Contains(frMatchCase),
??? FindDialog1 - > Options.Contains(frWholeWord));
同樣的,“替換(&R)”菜單項(xiàng)處理代碼是:
ReplaceDialog1 - > Execute();
ReplaceDialog1的onFind 事件的處理代碼:
MainForm - > SetFocus();
if(ReplaceDialog1 - > Options.Contains(frFindNext))
FindReplace(ReplaceDialog1 - > FindText.c_str(),"", frtFind,
??? ReplaceDialog1 - > Options. Contains(frDown),
??? ReplaceDialog1 - > Options. Contains(frMatchCase),
??? ReplaceDialog1 - > Options. Contains(frWholeWord));
ReplaceDialog1的onReplace 事件(用戶按了[替換(R)]按鈕)的處理代碼:
MainForm - > SetFocus ();
if(ReplaceDialog1 - > Options. Contains (frReplace))
FindReplace(ReplaceDialog1 - > FindText. c_str(),
??? ReplaceDiaiog1 - > ReplaceText. c_str(), frtReplace,
??? ReplaceDialog1 - > Options. Contains(frDown),
??? ReplaceDialog1 - > Options. Contains(frMatchCase),
??? ReplaceDialog1 - > Options. Contains(frWholeWord));
else if(ReplaceDialog1 - > Options. Contains (frReplaceAll))//全部替換
FindReplace(ReplaceDialog1 - > FindText.c_str(),
??? ReplaceDialog1 - > ReplaceText, c_str(), frtRepAll,
??? ReplaceDialog1 - > Options. Contains(frDown),
??? ReplaceDialog1 - > Options. Contains(frMatchCase),
??? ReplaceDialog1 - > Options. Contains(frWholeWord));
當(dāng)然,還有“查找下一個(gè)(N)”菜單項(xiàng),處理的方法幾乎和OnFind一樣:
FindReplace(FindDialog1 - > FindText. c_str(),"", frtFind,
??? FindDialog1 - > Options. Contains (frDown),
??? FindDialog1 - > Options. Contains (frMatchCase),
??? FindDialog1 - > Options. Contains(frWholeWord));
??? 至此為止,終于真的“大”功告成了。至于“幫助(H)”菜單處理,你可以用WinHelp來(lái)顯示一個(gè)幫助文
件,用MessageBox來(lái)顯示“關(guān)于XXX”的對(duì)話框,這些都不怎么和C++ Builder有關(guān),我就不贅述了。
??? 最后還有些收尾工作,選擇Project菜單Options,將顯示一個(gè)程序設(shè)置的對(duì)話框。
??? 1.選擇Application頁(yè)面,這里Title是程序在任務(wù)欄上的標(biāo)題,默認(rèn)的是程序文件名。我們將它設(shè)為
“我的記事本V1.00”。接著,單擊[Load Icon...]按鈕來(lái)為你的軟件選擇一個(gè)圖標(biāo)。
??? 2.選擇Compiler頁(yè)面,單擊[Release]按鈕,這樣就不會(huì)向程序中插入調(diào)試代碼而加快執(zhí)行速度。
??? 3.選擇Linker頁(yè)面,取消對(duì)Use Dynamic RTL的選擇,不使用動(dòng)態(tài)鏈接庫(kù)。
??? 4.選擇Packages頁(yè)面,取消對(duì)Build with runtime packages的選擇,不使用運(yùn)行時(shí)包。
??? 按OK退出后,選Project菜單中的Build NotePad來(lái)編譯一下,你的第一個(gè)用C++ Builder3制作的稱得上“軟件”的程序終于誕生了。
總結(jié)
以上是生活随笔為你收集整理的用C++ Builder3 制作NotePad(记事本)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样在C++Builder中创建使用DL
- 下一篇: 飞鸽传书就不去袭击你们了