C++ Builder开拓履历几则
副标题#e#
Borland C++ Builder 是Inprise公司继Delphi之后推出的又一豪情之作,它使得C++的可视化编程真正成为了大概,这就为那些既不忍心放弃本身心爱的C++语言,又十分憧憬Windows平台下RAD编程的措施员们提供了一个近乎于完美的办理方案。个中坚版本Borland C++ Builder 3.0更是一优秀的全能型的开拓东西。从开拓成果上来说,其成果和此刻如日中天的Microsoft的Visual C++对比八两半斤,而从易用性方面来说,其易用性则要大大优于前者,正因为如此,所以Borland C++ Builder3.0在海内也逐渐获得了一些措施员的认同。可是Borland C++ Builder在海内的应用环境还远不及它的同门师兄Delphi一样普及,所以相对来说Borland C++ Builder3.0的参考资料也较量少。在这里笔者把本身这一年来利用Borland C++ Builder 3.0所总结出来的履历拿出几条来与各人共飨,只但愿能对你在编程时有必然的辅佐,让你少走一些弯路。
1.全局变量的界说
这个问题在尺度的C/C++编程规模可以说基础不能算是一个问题,可是在Borland C++Builder3.0中却有些差异。当一个措施包括一个界说在独立头文件中的全局变量时,措施编译将会很顺利地通过,可是在措施链接时则会呈现找不到全局变量方针模块的错误。这个问题曾令包罗笔者在内的许多Borland C++ Builder 措施员感想狐疑。直到前不久,我才找到了问题呈现的原因息争决问题的要领。
在Borland C++ Builder 3.0中对全局变量的界说回收了界说函数一样的方法,即全局变量不只要有声明部门,还要有实例界说部门。只有这样界说过的全局变量在利用时才不会堕落。
以下举例说明,在措施中要界说一个全局整型变量i,它的声明部门写在Struct.H头文件中,如下所示:
#ifndef StructH
#define StructH
#include //此行必需加上
//------------------
extern int i;//此处为全局变量i的声明
//-------------------
#endif
而它的实例界说部门则应该写在Struct.cpp文件中,详细如下:
//------------------
#include “struct.h”
#pragma package(smart_init)//此行必需加上。
//------------------
int i;//此处为全局变量i的实例界说
//-------------------
只有颠末以上处理惩罚后,在措施中利用自界说全局变量时才不会堕落。
#p#副标题#e#
2.使同一个元件的Hint在StatusBar中与动态提示时有差异的显示内容
这是我在阅读VCL源码时无意中发明的。固然是一个小能力,可是却极端实用,以下详细举例说明:
⑴:在Borland C++ Builder 3.0中新建一个项目,然后在窗口中插手一个Button元件和一个StatusBar元件,并在工具检器中将Button元件的ShowHint属性和StatusBar元件的SimplePanel属性值都置为true。
⑵:将Button元件的Hint属性置为“这是一个按钮的提示信息|这是在提示行上显示的信息”。
⑶:在窗口头文件的窗口类中界说一个函数原型如下:
void __fastcall DisplayHint(TObject *Sender);
然后在CPP文件中编写这个函数的代码如下:
void __fastcall TForm1::DisplayHint(TObject *Sender)
{
StatusBar1->SimpleText=GetLongHint(Application->Hint);
//应用措施在显示动态提示信息时,只会显示“|"以前的部门,而想要显示“|"今后的部门就只有通过挪用GetLongHint函数来实现了。
}
⑷:最后再在窗口的结构函数中插手以下一行代码:
Application->OnHint=DisplayHint;
⑸:生存并编译项目后运行措施。
这时你会发明,当你把鼠标移到Button上时,Button上所显示的动态提示信息和StatusBar上所显示的提示信息是差异的。
下面附送一个为整个应用措施安装动态提示的措施段。它摘自我正在开拓的一个应用措施:
void __fastcall TForm1::DisplayHint(TObject *Sender)
{
// 先对已经存在窗口的Tag属性赋值,然后再通过判定当前窗口的要领来进动作态提示。
//假如将建的窗口也需要动态提示的话,那么可先给窗口的Tag属性赋值,然后再将判定这个Tag属性的代码插手到下面的switch语句中。
switch(Screen->ActiveForm->Tag)
{
case 1 :DFSStatusBar1->Panels->Items[1]->Text=GetLongHint(Application->Hint);break;
case 5 :Form5->StatusBar1->SimpleText=GetLongHint(Application->Hint);break;
case 8 :Form8->StatusBar1->SimpleText=GetLongHint(Application->Hint);break;
case 11:Form11->StatusBar1->SimpleText=GetLongHint(Application->Hint);break;
}
}
3.如何使DateToStr函数转换后的功效为长名目标日期字符串
#p#分页标题#e#
这是我在实际开拓进程中碰着的一个问题。当我把TDateTimePicker元件的Date属性通过DateToStr函数转换后赋给一个Edit元件的Text属性时,Text获得的日期字符串数据只是以yy-mm-dd名目暗示的短名目日期字符串数据。千年虫!眼看就要到二千年了,这怎么能行。原来我想用判定字符串的步伐来办理这个问题,可是厥后颠末深入思考后发明该要领有许多的漏洞。所以只有用一种通用的要领来办理问题了。在这种环境下,我查找了许多的资料,可是很不幸的是,我所查找的资料中没有一个提到办理这个问题的要领。无奈之下我打开了Borland C++ Builder 3.0的辅佐文件,查察了所有关于日期的辅佐信息。此招公然有效,在辅佐文件中我找到了一组用于日期显示的外部变量,个中有两个AnsiString型变量,它们别离是ShortDateFormat和LongDateFormat。从它们的名称就可以看出,它们是用来存储短日期名目和长日期名目标。其时灵机一动,想通过修改这两个变量值的要领来办理问题,于是连忙写了一段代码并运行之,才发明我的想法是可行的。详细代码段如下:
void __fastcall TForm7::WriteLongDate(void)
{
AnsiString temp=ShortDateFormat;
ShortDateFormat=LongDateFormat;
Edit1->Text=DateToStr(DateTimePicker1->Date);
ShortDateFormat=temp;
}
该措施段先生存短日期名目变量,然后将长日期名目变量赋给短日期名目变量,这样做后就使恰当前的短日期名目和长日期名目标暗示方法沟通了。接下来利用日期转字符串函数DataToStr来将日期数据转换为AnsiString型数据,转换后的AnsiString就已经酿成了长名目标日期数据。最后将先前生存的短日期名目变量规复一下即可。就这样,问题被很好地办理了。同理,假如将长名目日期字符串转换为短名目日期数据,也可以利用上述要领,只不外要将上面赋值的顺序反过来即可。
4.措施在编译链接时提示找不到某某文件应该怎么办?
这是一个实际编程事情中常常碰着的问题。造成这个问题的原因许多,很难一一先容,所以我在这里只向各人先容几个造成这个问题的典范原因,以及其办理要领。但愿能对你在办理这个问题时起到抛砖引玉的浸染。
⑴:编译器找不到存在的文件。
这个问题常常呈此刻编译添加新元件的应用措施时。其原因在于项目文件的搜索路径中并没有这个新元件地址路径的信息。这个问题办理起来较量简朴,只需打开Project/Options菜单,在弹出的“选择”窗口中选择“Directories/Conditionals"标签页,然后将新元件的路径信息添加到包括路径(Include Path)和库文件路径(Library Path)中即可。
⑵:编译器要找不存在的文件环境之一
也许你在编程中有过这样的遭遇,当你编译并链接一个新的措施时,编译措施竟然会汇报你,需要你已经卸载了的元件介入编译。不知道你其时的感受怎么样,横竖,当我还不知道这个问题办理步伐的时候,它总给我一种死去的元件阴魂不散的感受。其实造成这个问题的原因是由于新元件在安装时要将其库文件的信息添加到缺省项目文件中的“编译链接所需库文件”部门,而元件在卸载时又不能自动将其删除。这就使得今后所有新建的项目在编译链接时都需要利用这些库文件。为了办理这个问题,我们就只有对缺省项目文件举办编辑了。进入Borland C++ Builder 3.0的BIN目次下,你可以找到一个叫做DEFAULT.BPR的项目文件,这个文件就是缺省项目文件,即所有新建项目文件的父本。打开这个文件后,找到SPARELIBS段,将“死去元件”的“阴魂”Kill掉,即可永绝后患了。
⑶:编译器要找不存在的文件环境之二
这种环境的呈现照旧与新元件的安装有关。当你在安装一些有源码的Delphi元件时,有大概碰着这样的环境:编译器汇报你找不到某某文件,使得挺好的一个元件就是无法利用。其实这个问题的呈现多数是由于元件源码中的一些判定Delphi版本的预编译信息所造成的。由于Delphi的差异版本之间都有着必然的差别,所以许多Delphi元件为了加强本身的可移植性都在元件的源码中插手了判定Delphi版本的预编译信息。然而Borland C++ Builder 3.0的Delphi编译器对这些Delphi版本的信息支持并不是很好,这就造成了Borland C++ Builder 3.0在编译这些元件时凡是是“胡子眉毛一把抓”,自然会堕落(值得留意的是,在编译Delphi元件时的许多其它编译错误也是由于这个原因所造成的)。这时我们就只有利用手工删除这些不需要的预编译信息(一般为{$IFDEF中的内容)的要领来办理这个问题了。
⑷:编译器要找不存在的文件环境之三
#p#分页标题#e#
有一次一个从BC++转到Borland C++ Builder 3.0的伴侣给我打电话问我,说他一时间动了怀旧的情绪,利用Borland C++ Builder 3.0编译了一个OWL措施。可是在编译时编译器却提示找不到OWL所需要的类库文件,问我这是为什么。连忙我便答复了他,汇报他Borland C++ Builder 3.0的默认安装将不安装对OWL和MFC的支持库(这在Borland C++ Builder 3.0安装措施的安装范例界面中已经写得很大白了,只不外是英文的,他没有留意看而已。)。假如需要这些对象的话,就只有在安装时选择定制安装或完全安装来安装对其的支持了。假如你也碰着了以上的问题,那么请你照我上面所说的话去做吧。
5 动态挪用窗体Form
在缺省环境下,由File/NewForm生成添插手项目文件中的窗体都具有"AutoCreate"(自动建设)的特性。即只要措施运行,该窗体就存在于内存中了,不管当前它是否被挪用。具有这种特性的窗体一般合用于窗体属性较量牢靠、常常被挪用的环境。其利益是速度快,缺点是占用内存。在实际措施设计中,会碰见大量雷同对话框成果的窗体,它们用于显示状态或输入信息,仅须在措施中挪用一下,完成其成果就行了,无需常驻内存。这时可以通过选择Project/Options/Forms,将"Auto–Createforms"栏中相应的窗体,如Form1,用">"键移动到"Availableforms"栏中,并在措施需挪用该窗体处,插手下列语句:
TForm1 *myform=newTForm1(this);
myform->ShowModal();
deletemyform;
6 用Enter键节制核心切换的要领
在Windows情况下,要使一个控件取得核心,可在该控件上用鼠标单击一下,或按Tab键将核心移至该控件上。这种节制核心切换的要领有时不切适用户的习惯。就图一而言,用户就但愿用Enter键,节制核心由Edit1切换到Edit2。要实现这样的成果需借助WinAPI函数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;
}
}
7 为TStringGrid的文字加上颜色
TStringGrid是C++Builder提供应用户的一种字符网格控件。美中不敷的是,它没有提供别离修改各单位字体颜色、巨细的要领。其实要为TStringGrid实现这样成果,只需在措施中稍加处理惩罚就行了。要领是自界说一个二维数组cellbuf,它的下标与网格单位列行一一对应,用于存放各网格单位的颜色、文字等信息。
structCellStru
{
AnsiStringmsg; //文字信息
TColorcolor; //文字颜色
};
CellStrucellbuf[MAXCOL][MAXROW];
—-初始化cellbuf后,再在字符网格控件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);
}
8 软件封面的实现
—-现代软件设计的风行做法是,在措施运行完成初始化之前,先挪用一幅画面做为封面,凡是是1/4屏幕巨细,显示一下软件的名称、作者、版本等信息。要用C++Builder实现这样的成果,要领很简朴:①自界说一窗体类TSplashForm,将其配置成"透明窗口",即BorderIcons下的所有选项均置成false,BorderStyle=bsNone,FormStyle=fsStayOnTop,Position=poScreenCenter;②在TSplashForm窗体上安排一TPanel(相当于图形的镜框);③在TPanel上安排一TImage控件,调入所需要的图形;④对WinMain函数稍加修改,插手如下所示代码即可。需要指出的是,这段代码通过函数FindWindow,搜索内存中是否有窗口标题为"Demo"应用措施存在,若存在,则退出措施的运行。该成果可防备措施的再次运行。在某些场所这样设计是必需的。
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
try
{
if(FindWindow(NULL,"Demo")!=0)
{
Application->MessageBox
("措施已经运行!","告诫",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;
}
9 如何永久排除DBF中的已被删除的记录
#p#分页标题#e#
—-用table->Delete()删除的DBF记录,并没有真正从DBF数据库中被删除,而仅仅是做上了一个删除标志。如何实现雷同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);
最后再说一种最糟的环境。由于你的某种误操纵,造成了某些编译器在编译时所需要文件被误删除。这时你独一的办理要领就只有从Borland C++ Builder 3.0的光盘大将你所需要的文件直接拷贝过来。假如你的Borland C++ Builder 3.0只是一个安装版的话,那么你也就只好筹备一杯清茶或一杯咖啡,在从头安装Borland C++ Builder 3.0时逐步咀嚼了.