[發(fā)表于2002年第11/12期《電腦報》軟件星空版,連載兩期。]
“聰明的程序員用Delphi!”現(xiàn)在,真是有越來越多的人開始用Delphi了。不過,高手畢竟是少數(shù),像我這樣的菜鳥可謂遍地都是,哈哈。既然是菜鳥自然就有一大堆很菜的問題,什么這個怎么設(shè)置、那個怎么寫的……所以,以下我就以我所積累的那一點點經(jīng)驗和論壇上常見的小問題作一個總結(jié)性發(fā)言(全場熱烈鼓掌!哎,這鮮花我就收下了,那個什么爛番茄就不要扔上來了嘛)
==系統(tǒng)應(yīng)用篇==
A.Delphi自代了大量的常用控件,如Delphi5就有一百多了,而今年出的Delphi6更是Delphi5的1.5倍。這么多控件,就是在1024*768的分辨率下也無法全部顯示他們的組件面板,而每次要按那兩顆小按鈕來顯示更多的面板,真是非常不方便!但通過添加下面那一個注冊表鍵值就能實現(xiàn)組件面板自動展開:
[HKEY_CURRENT_USER\Software\Borland\Delphi\X.0\Extras]
"AutoPaletteSelect"="1"
(注:X.0表示你的Delphi的版本號;如果沒有Extras主鍵則新建即可,下同)
B.每次新建窗體,然后設(shè)置其字體、大小……真是好麻煩的!那就再添加一個以下的鍵值,讓系統(tǒng)自動來設(shè)置吧:
[HKEY_CURRENT_USER\Software\Borland\Delphi\X.0\FormDesign]
"DefaultFont"="宋體,9,_"
(注:_表示空格,也可以用Bold(粗體)等代替)
C.自定義工作環(huán)境,讓它更加適合自己。
•設(shè)置工具欄。在Delphi的工具欄右鍵單擊,選Customize,然后挑選需要的按鈕拖到工具上,把不要的拖出來。我常用的是:Standard工具欄下的Open、Open Project、Save、Save All、Undo、Redo;Debug工具欄下的Pause、Add Watch、Program Reset、Run;Desktop工具欄下的Save Current Desktop、Set Debug Desktop;Component Palette工具欄。
•設(shè)置窗口布局。為了能跟高效的編寫程序,合理的布置各個窗口是很重要的。我常用的窗口有:Object Inspector、Project Manager(View|Project Manager)、Watch List(Run|Add Watch...) ,具體的停放位置如圖1。
[圖1]
設(shè)置好各個窗體后按Desktop工具欄上的Save Current Desktop按鈕保存。
•設(shè)置顯示顏色。讓代碼的顏色更符合自己的習(xí)慣,有利于編寫時思維的清晰。Tools|Editor Options打開Editor Properties,選Color標(biāo)簽頁,設(shè)置代碼顏色。以下僅解釋一下幾個常用的:
Whitespace:空白處,即背景;
Comment:注釋;
Reserved word:保留字;
String:字符串;
Number:數(shù)字;
Execution Point:正在執(zhí)行的當(dāng)前行(即F7步入時所到達(dá)的那一行);
Enabled break:斷點;
Error line:錯誤發(fā)生行;
D.掌握一些Delphi編程中的快捷鍵,能夠極大程度的提高效率,還不會讓你因為過多無聊的設(shè)置等而感到厭煩,現(xiàn)在如果不用這些快捷鍵,我會很不適應(yīng)這樣的編程的!以下我就介紹一下我常用的幾個快捷鍵:
Esc : 選擇當(dāng)前選中組件的容器(通常是Panel,GroupBox或Form等);
Ctrl+方向鍵 :將所選組件移動一個像素;
Ctrl+Shift+方向鍵 :將所選組件移動一大格(類似Fireworks中按住Shift再用方向鍵移動時的效果);
Shift+方向鍵 :調(diào)整選中組件的大小,每次一像素;
Shift+選中組件 :按住Shift鍵再用鼠標(biāo)點擊組件,可以同時選擇多個組件;
Ctrl+鼠標(biāo)左鍵 :在procedure中掉用其他的函數(shù)(如一個自定義的過程),在這個調(diào)用處按住Ctrl會發(fā)現(xiàn)當(dāng)鼠標(biāo)移上去的時候變成了一個類似超鏈接的格式,鼠標(biāo)單擊就能直接轉(zhuǎn)到所調(diào)用的此函數(shù)的實現(xiàn)部分。這個功能我可是用的最多了,讓我找模塊變得非常方便!
Ctrl+Shift+C :在一個對象中聲明了一個方法,然后把光標(biāo)放到它的上面,按下Ctrl+Shift+C就可以為他的實現(xiàn)建立一個基本框架,如:
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
procedure Mine;
end;
把光標(biāo)放到procedure Mine這行,按下Ctrl+Shift+C,下面這段代碼將自動插入到單元中:
procedure TForm1.Mine;
begin
end;
==窗體操作篇==
在有多個窗體的程序中,Delphi默認(rèn)是將它們在程序啟動時全部創(chuàng)建(只是都隱藏了,只顯示一個主窗體),這樣,那些暫時不必要啟動的窗體就占用了許多內(nèi)存空間。所以我們需要在菜單Project|Options...的Forms標(biāo)簽頁下,將那些暫時不要啟動的窗體從“Auto-create forms”下轉(zhuǎn)移到“Available forms”中。這樣,這些窗體的創(chuàng)建和釋放就需要代碼來實現(xiàn)了。
A.兩種創(chuàng)建窗體方法之比較。對于這些非自動創(chuàng)建的窗體,我們必須在Show之前Creat(Self)或Create(Application),將其創(chuàng)建。如Form2.Creat(Self)和Form2.Create(Application),可是,它們兩個到底有什么區(qū)別呢?其實兩者區(qū)別不大,
但如果Owner是屬于別的窗口或控件的話,當(dāng)它的Owner被釋放的時候,該Owner所擁有的也會被釋放。關(guān)鍵的區(qū)別是由誰來管理該窗體的資源。用第一種方法創(chuàng)建,該窗體的資源由編程者來負(fù)責(zé)管理;用第二種方法創(chuàng)建,該窗體的資源由Application來管理。
B.幾種窗體的釋放方法。既然是為了節(jié)約內(nèi)存,那么用完了的窗體就應(yīng)該“搬出”內(nèi)存。在這里我列舉幾個大同小異的方法:
(1)
procedure TForm1.Button1Click(Sender :TObject);
begin
......
if Form2 = nil then
Form2:=TForm2.Create(Application);
Form2.ShowModal;
......
end;
procedure TForm2.close(Sender: TObject; var Action: TCloseAction);
begin
ModalResult := mrNone;
Action := caFree;
Form2 := nil;
end;
(2)
procedure TForm1.Button1Click(Sender :TObject);
begin
if not Assigned(Form2) then
begin
Application.CreateForm(TForm2,Form2);
try
Form2.ShowModal;
finally
Form2.Free;
Form2 := nil;
end;
end
else
Form2.ShowModal;
end;
(3)
procedure TForm2.Button1Click(Sender :TObject);
begin
Form2.Close;
Form2.Release;
end;
==控件使用篇==
A.大名鼎鼎的RXLib控件包是由三位俄羅斯高手編寫的,非常的出色!不過,內(nèi)容太多了,要用好也不容易。我在此拿RxRichEdit簡單地說幾點。
•好多人都問RxLib怎么安裝,似乎的確有點復(fù)雜,呵呵,所以我也順便說一下:
運(yùn)行rxinst.exe將RxLib先安裝到\Program Files\Borland\Delphi5(或6)\RX文件夾下,然后打開Delphi,選File\Open...,將RXCTL5.DPK、RXDB5.DPK、RXBDE5.DPK分別打開后按compile,繼續(xù)打開:DCLRX5.DPK、DCLRXDB5.DPK和DCLRXBD5.DPK,將這三個分別按compile后按install就可以了:-)
•AllowObjects屬性。Win98下默認(rèn)設(shè)置為True,右鍵菜單沒有問題,但設(shè)為False時快捷菜單會連續(xù)出現(xiàn)兩次;Win2000下,設(shè)為True時會使右鍵菜單無法彈出,而False時卻顯示正常。所以,為了系統(tǒng)的兼容性,需要判斷當(dāng)前OS版本:
procedure TFormMain.FormCreate(Sender: TObject);
var
OSVI:OSVERSIONINFO;
......
begin
OSVI.dwOSVersionInfoSize:=sizeof(OSVERSIONINFO);
GetVersionEx(OSVI);
case OSVI.dwPlatformId of
1:RxRichEdit1.AllowObjects:=true;
2:RxRichEdit1.AllowObjects:=false;
end;
.......
end;
但我不知這個屬性為什么會有這么一個問題,還望高手指點。
•OnURLClick事件。RXRichEdit有自動將網(wǎng)頁地址轉(zhuǎn)為超鏈接格式,但具體的行為還是要自己寫代碼的,不然這些地址就成了個空殼了:
procedure TFormMain.RXRichEdit1URLClick(Sender: TObject; const URLText: String; Button: TMouseButton);
begin
if Button = mbLeft then
ShellExecute(Handle, nil, PChar(URLText), nil, nil, SW_SHOW);
end;
B.為了節(jié)約內(nèi)存,優(yōu)化運(yùn)行,我們總是動態(tài)創(chuàng)建組件??僧?dāng)用完之后,如果不及時徹底的將其從內(nèi)存中清理出去,那就有違我們的初衷了??稍趺?#8220;殺死”所創(chuàng)建的組件? 比如創(chuàng)建了一個Edit控件,現(xiàn)在想讓它消失,但用Edit.Free后,調(diào)用Edit.Text卻仍然存在……我們知道,光Free是不行的,這只是將Edit所指向的內(nèi)存空間釋放了,但是指針并沒有設(shè)定為nil,當(dāng)調(diào)用Edit.Text時,Delphi仍然會根據(jù)Edit提供的指針訪問已經(jīng)釋放的內(nèi)存區(qū)域,所以會產(chǎn)生Access Violation ....錯誤。所以我們需要在Free后Edit:=nil或者FreeAndNil(只在Delphi5下有效)將指針nil掉,才能保證以后的正常運(yùn)行。
C.將各控件的提示文本顯示于狀態(tài)行上。這個可用Application的OnHint事件,但由于Application為不可件對象,因此可以采用如下方法:
......
public
procedure DisplayHint(Sender: TObject); //聲明一個方法用于顯示提示文本
end;
......
procedure TForm1.DisplayHint(Sender: TObject); //實現(xiàn)部分
begin
StatusBar1.SimpleText := GetLongHint(Application.Hint);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnHint := DisplayHint;
end;
這樣顯示在狀態(tài)欄里的文本和提示框(就是那個自動出現(xiàn)的黃色小框)里的是一樣的。如果想要在狀態(tài)欄里的提示文本更加詳細(xì)怎么辦?其實,只要控件的Hint屬性這樣寫:MyHint|It‘s just a MyHint!,就可以讓“|”前的內(nèi)容顯示在提示框(Help Hint box)里,“|”的后面的內(nèi)容顯示在狀態(tài)欄里了。
D.ListView使用中的一些要點。以下以一個兩列的ListView為例。
→增加一行:
with ListView1 do
begin
ListItem:=Items.Add;
ListItem.Caption:=‘第一列內(nèi)容‘;
ListItem.SubItems.Add(‘第二列內(nèi)容‘);
end;
→清空ListView1:
ListView1.Items.Clear;
→得到當(dāng)前被選中行的行的行號以及刪除當(dāng)前行:
For i:=0 to ListView1.Items.Count-1 Do
If ListView1.Items[i].Selected then //i=ListView1.Selected.index
begin
ListView1.Items.Delete(i); //刪除當(dāng)前選中行
end;
當(dāng)然,ListView有OnSelectItem事件,可以判斷選擇了哪行,用個全局變量把它賦值出來。
→讀某行某列的操作:
Edit1.Text := listview1.Items[i].Caption; //讀第i行第1列
Edit2.Text := listview1.Items[i].SubItems.strings[0]; //讀第i行第2列
Edit3.Text := listview1.Items[i].SubItems.strings[1]; //讀第i行第3列
以次類推,可以用循環(huán)讀出整列。
→將焦點上移一行:
For i:=0 to ListView1.Items.Count-1 Do
If (ListView1.Items[i].Selected) and (i>0) then
begin
ListView1.SetFocus;
ListView1.Items.Item[i-1].Selected := True;
end;
不過在Delphi6中,ListView多了一個ItemIndex屬性,所以只要
ListView1.SetFocus;
ListView1.ItemIndex:=3;
就能設(shè)定焦點了。
==其他==
•為了優(yōu)化軟件,使其精益求精,當(dāng)用到數(shù)組時經(jīng)常采用動態(tài)數(shù)組。在聲明時,如:A : array of string,然后在使用數(shù)組之前,SetLength(A,3)設(shè)置數(shù)組長度為3,即A[0],A[1],A[2],這樣就可以了。當(dāng)需要擴(kuò)大數(shù)組長度時,再一次:SecLength(A,5),那么,就增加了A[3]和A[4],而前面的A[0],A[1],A[2]里的值不會清空;同樣,如果SecLength(A,3)后再SecLength(A,1)的話,就只剩A[0]了,A[1]和A[2]自動被清除內(nèi)存。注意:動態(tài)數(shù)組是從“0”開始的,所以SetLength(A,1)后High(A)=0的??!
最后當(dāng)不再用這個動態(tài)數(shù)組了,而程序還沒有要退出,那為了節(jié)省內(nèi)存用:A:=nil來釋放掉這個數(shù)組,這下真正達(dá)到了“綠色環(huán)保”:)
•“怎么獲取當(dāng)前程序運(yùn)行的路徑”這個問題經(jīng)常能夠在論壇上看到。的確,這個函數(shù)在編程中不時的要用到的。其實有好幾個函數(shù)都能達(dá)到這個效果:
→GetCurrentDirectory():WinAPI函數(shù),具體用法如下:
var
MyCurrentDir:Array[0..144] of Char; //存儲當(dāng)前絕對路徑
begin
GetCurrentDirectory(SizeOf(MyCurrentDir),MyCurrentDir); //取得當(dāng)前絕對路徑,最后得到的格式如:C:\WINDOWS\SYSTEM
MyCurrentDir:=MyCurrentDir+‘\MySoftName.exe‘;
end;
→GetCurrentDir():GetCurrentDirectory經(jīng)過Delphi封裝后的一個函數(shù),用法簡單:MyCurrentDir:=GetCurrentDir。最后得到的格式如:C:\WINDOWS\SYSTEM
還有就是可以直接得到路徑的函數(shù):ExtractFilePath(ParamStr(0))、ExtractFilePath(Application.exename)等。
•系統(tǒng)的關(guān)機(jī)、重新啟動等操作的消息。這也是一個常有人問的問題,在此我也順便在提一下:
關(guān)機(jī):ExitWindowsEx(EWX_SHUTDOWN,32);
重新啟動:ExitWindowsEx(EWX_REBOOT,32);
注銷:ExitWindowsEx(EWX_LOGOFF,32);
關(guān)閉電源:ExitWindowsEx(EWX_POWEROFF,32);
•在Delphi中,除了使用#39外,要在程序中(如ShowMessage中)顯示“單個單引號”要如何處理?‘‘‘和‘‘‘‘‘都會出現(xiàn)編譯錯誤。其實,是四個單引號表示一個單引號,也就是是 ‘‘‘‘,第二個和第三表明這是一個“‘”,第一個和第四個是表明這是一個字符型。呵呵,很有趣哦:)
•ShowMessage中的漢化問題。ShowMessage中的按鈕都是E文的,讓人很不舒服。其實經(jīng)過我們的一番DIY,也能把它們都弄成中文的。
首先要保存當(dāng)前的工程,然后選Project|Languages|Add...,出現(xiàn)Add Language對話框,選擇你要漢化的工程(也可以自定義文件夾),Next;選最后一項“中文(中國)”,Next;Next;Next;Finish;OK;然后就出現(xiàn)了Translation Manager對話框,在左邊選“中文(中國)|Resource Scripts|Projet1_DRC(這個具體要看你的工程文件名)”,然后右邊的列表里找到“Const_SMsgDlgOK”項,將其的“中文(中國)(translated)”格改為“確定”(原為OK),保存后退出。這下,再運(yùn)行一下程序,哈哈,是不是就是中文按鈕啦!
不過,ShowMessage這種類型的信息對話框非常簡單了,可以在系統(tǒng)調(diào)試期間顯示給開發(fā)人員一些過程信息。但由于過于簡單,所以我建議在軟件的正式版中不要使用這樣的對話框。而且,最好用MessageBox代替ShowMessage以減小軟件的體積,例如,同樣一個DLL文件,采用MessageBox 編譯后的DLL文件大小為58K,而ShowMessage后就變成了301K??!