翻譯|其它|編輯:郝浩|2008-01-22 10:29:08.000|閱讀 1824 次
概述:
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
C++Builder3.0是Borland公司(現(xiàn)已更名為Insprise)于1998年推出的新一代基于C語言的RAD開發(fā)工具。C++Builder3.0的問世,對廣大愛好C語言的用戶來說不啻是個福音。因為以往在Windows下,沒有一種真正基于C語言的可視化編程語言。你如果想用VB或Delphi這一類可視化編程語言去編程,你就不得不去重溫一遍Basic或Pascal語言,沒有了像C語言一樣可以靈活應用的指針,沒有了"++"、"――"這樣一類可愛的運算,總之一切使用起來都不如C語言一樣得心應手?,F(xiàn)在這一切煩惱都不復存在了。C++Builder3.0不僅支持傳統(tǒng)的C語言,也支持Borland的OWL和Microsoft的MFC。可以這樣說,C++Builder3.0是目前Windows下功能最為強大的C語言編譯器。由于C++Builder3.0問世不久,有關資料不是很多,下面結合筆者的使用情況,談談幾點經(jīng)驗、體會。
一、動態(tài)調用窗體Form
在缺省情況下,由File/NewForm生成添加入項目文件中的窗體都具有"AutoCreate"(自動創(chuàng)建)的特性。即只要程序運行,該窗體就存在于內存中了,不管當前它是否被調用。具有這種特性的窗體一般適用于窗體屬性比較固定、經(jīng)常被調用的情況。其優(yōu)點是速度快,缺點是占用內存。在實際程序設計中,會遇見大量類似對話框功能的窗體,它們用于顯示狀態(tài)或輸入信息,僅須在程序中調用一下,完成其功能就行了,無需常駐內存。這時可以通過選擇Project/Options/Forms,將"Auto--Createforms"欄中相應的窗體,如Form1,用">"鍵移動到"Availableforms"欄中,并在程序需調用該窗體處,加入下列語句:
TForm1*myform=newTForm1(this);
myform->ShowModal();
deletemyform;
窗體Form1僅是在需要調用時才調入內存,調用完成后,即用delete清除出內存。這樣可減少程序對內存資源的占用。
二、遍歷窗體控件的方法
要訪問或修改窗體上的控件,方法很簡單,以TEdit為例子:
Edit1->Text="";
Edit2->Text="";
但如果窗體上有十來個像Edit1這樣的控件,需要進行相同的初始化,用上面的方法一個一個地進行,豈不麻煩!所以有必要掌握遍歷窗體控件的方法。在介紹該方法之前,讓我們先了解一下窗體Form的Components和Controls屬性。參見表一。
表一
屬性類型說明
ComponentCountInt目前Form上各類
控件的總數(shù)
ComponentsTCompont*目前Form上指向
所有控件的數(shù)組
ControlCountInt目前Form上某一子
區(qū)域上各類控件的總數(shù)
ControlsTControl*目前Form上指向某一子
區(qū)域上所有控件的數(shù)組
以圖一為例(圖略)說明,F(xiàn)orm1的ComponentCount=6,而Panel1的ControlCount=4.,
其中:數(shù)組對象
Components[0]Panel1
Components[1]Label1
Components[2]Edit1
Components[3]Label2
Components[4]Edit2
Components[5]Button1
數(shù)組對象
Controls[0]Label1
Controls[1]Edit1
Controls[2]Label2
Controls[3]Edit2
下面這段代碼完成了對Panel1上所有TEdit控件的遍歷初始化。讀者稍加修改,即可對其它控件進行遍歷。這里有一個小技巧,我們把需要進行初始化的控件放置在了一Panel1上,與不需要初始化的控件區(qū)分開來,這樣便于編程。
AnsiStringnamestring="TEdit";
for(inti=1;iControlCount;i++)
{
if(Panel1->Controls[i]->
ClassNameIs(namestring))
{
TEdit*p=dynamic_cast
(Panel1->Controls[i]);
P->Text="";
}
}
三、用Enter鍵控制焦點切換的方法
在Windows環(huán)境下,要使一個控件取得焦點,可在該控件上用鼠標單擊一下,或按Tab鍵將焦點移至該控件上。這種控制焦點切換的方法有時不符合用戶的習慣。就圖一而言,用戶就希望用Enter鍵,控制焦點由Edit1切換到Edit2。要實現(xiàn)這樣的功能需借助WinAPI函數(shù)SendMessage來完成。方法是:先設Form1的KeyPreview屬性為true,然后在Form1的OnKeyPress事件中加入如下的代碼。這樣,用戶就可以通過按Enter,鍵控制焦點按定義好的Taborder順序來移動了!
void__fastcallTForm1::
FormKeyPress(TObject*Sender,char&Key)
{
if(Key==VK_RETURN)
{
SendMessage(this->Handle,WM_NEXTDLGCTL,0,0);
Key=0;
}
}
四、為TStringGrid的文字加上顏色
----TStringGrid是C++Builder提供給用戶的一種字符網(wǎng)格控件。美中不足的是,它沒有提供分別修改各單元字體顏色、大小的方法。其實要為TStringGrid實現(xiàn)這樣功能,只需在程序中稍加處理就行了。方法是自定義一個二維數(shù)組cellbuf,它的下標與網(wǎng)格單元列行一一對應,用于存放各網(wǎng)格單元的顏色、文字等信息。
structCellStru
{
AnsiStringmsg;//文字信息
TColorcolor;//文字顏色
};
CellStrucellbuf[MAXCOL][MAXROW];
----初始化cellbuf后,再在字符網(wǎng)格控件StringGrid1的OnDrawCell響應事件中,加入如下的代碼即可。
void__fastcallTForm1::StringGrid1DrawCell
(TObject*Sender,intCol,
intRow,TRect&Rect,TGridDrawStateState)
{
StringGrid1->Canvas->Font->
Color=cellbuf[Col][Row].color;
StringGrid1->Canvas->TextOut(Rect.Left+3,
Rect.Top+3,cellbuf[Col][Row].msg);
}
五、軟件封面的實現(xiàn)
----現(xiàn)代軟件設計的流行做法是,在程序運行完成初始化之前,先調用一幅畫面做為封面,通常是1/4屏幕大小,顯示一下軟件的名稱、作者、版本等信息。要用C++Builder實現(xiàn)這樣的功能,方法很簡單:①自定義一窗體類TSplashForm,將其設置成"透明窗口",即BorderIcons下的所有選項均置成false,BorderStyle=bsNone,F(xiàn)ormStyle=fsStayOnTop,Position=poScreenCenter;②在TSplashForm窗體上放置一TPanel(相當于圖形的鏡框);③在TPanel上放置一TImage控件,調入所需要的圖形;④對WinMain函數(shù)稍加修改,加入如下所示代碼即可。需要指出的是,這段代碼通過函數(shù)FindWindow,搜索內存中是否有窗口標題為"Demo"應用程序存在,若存在,則退出程序的運行。該功能可防止程序的再次運行。在某些場合這樣設計是必須的。
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
try
{
if(FindWindow(NULL,"Demo")!=0)
{
Application->MessageBox
("程序已經(jīng)運行!","警告",MB_ICONSTOP);
return0;
}
TSplashForm*splash=newTSplashForm(Application);
splash->Show();
splash->Update();
Application->Initialize();
Application->CreateForm(__classid(TForm1),&Form1);
splash->Close();
deletesplash;
Application->Run();
}
catch(Exception&exception)
{
Application->ShowException(&exception);
}
return0;
}
六、如何永久清除DBF中的已被刪除的記錄
用table->Delete()刪除的DBF記錄,并沒有真正從DBF數(shù)據(jù)庫中被刪除,而僅僅是做上了一個刪除標記。如何實現(xiàn)類似dBase中的Pack命令的功能呢?請看下面的代碼。 table->Close();
for(;;)
try
{
table->Exclusive=true;
table->Open();
break;
}
catch(...)
{
}
if(DbiPackTable(table->DBHandle,table->
Handle,NULL,szDBASE,true)!=DBIERR_NONE)
Application->MessageBox("不能刪除記錄",
"錯誤",
MB_ICONSTOP);
七、I/O端口讀寫的實現(xiàn)
細心的讀者會發(fā)現(xiàn),C++Builder不再支持如inportb()、outportb()一類I/O端口讀寫指令了。準確地說,在Windows環(huán)境下,BorlandC++僅支持16位應用程序的端口操作,對32位應用程序的端口操作不再支持,而C++Builder開發(fā)出來的程序是32位的。我個人以為,這是C++Builder設計者的敗筆。因為PC機中,I/O地址空間與內存地址空間從來都是各自獨立的。看看Delphi,不就通過Port數(shù)組實現(xiàn)了對I/O端口的訪問了嗎?搞不清楚為什么C++Builder就沒有提供類似的機制?下面這幾個函數(shù)是筆者從網(wǎng)上淘下來的,經(jīng)過驗證,在Windows95環(huán)境下,的確可實現(xiàn)對I/O端口的讀寫。讀者可以借鑒使用。
voidoutportb(unsignedshort
intport,unsignedcharvalue)
{
//movedx,*(&port);
__emit__(0x8b,0x95,&port);
//moval,*(&value);
__emit__(0x8a,0x85,&value);
//outdx,al;
__emit__(0x66,0xee);
}
voidoutportw(unsignedshort
intport,unsignedshortintvalue)
{
//movedx,*(&port);
__emit__(0x8b,0x95,&port);
//movax,*(&value);
__emit__(0x66,0x8b,0x85,&value);
//outdx,ax;
__emit__(0xef);
}
unsignedcharinportb(unsignedshortintport)
{
unsignedcharvalue;
//movedx,*(&port);
__emit__(0x8b,0x95,&port);
//inal,dx;
__emit__(0x66,0xec);
//mov*(&value),al;
__emit__(0x88,0x85,&value);
returnvalue;
}
unsignedshortintinportw(unsignedshortintport)
{
unsignedshortintvalue;
//movedx,*(&port);
__emit__(0x8b,0x95,&port);
//inax,dx
__emit__(0xed);
//mov*(&value),ax
__emit__(0x66,0x89,0x85,&value);
returnvalue;
}
八、軟件的分發(fā)
在Windows下開發(fā)的應用程序一般都比較龐大,程序的運行往往離不開一大堆不知名的系統(tǒng)DLL文件。為了生成能脫離C++Builder環(huán)境、獨立運行的應用程序,讀者須對編譯器進行一定的設置。方法是:置Project/Option/Packages/Runwithruntimepackages為Disable,置Project/Option/Linker/UsesdynamicRTL為Disable,重新編譯一遍程序,這樣生成的EXE文件就可以脫離C++Builder環(huán)境運行了。但如果你的程序中應用了數(shù)據(jù)庫,僅有上述的操作是不夠的--因為,你還得安裝BDE(BorlandDatabaseEngineer)。BDE的安裝比較麻煩,讀者最好是用C++Builder3.0附帶的InstallShieldExpress來制作安裝盤,把應用程序和BDE打包在一起。如果找不到,也可用Delphi3.0附帶的InstallShieldExpress來制作。InstallShield的使用方法,限于篇幅,不再介紹。有條件的讀者可上網(wǎng)查到有關資料。
本站文章除注明轉載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:編程愛好者