C++Builder 5.0编程指南(1)

一、IDE界面介绍
    打开BCB总是出现下面的四个窗口,并且默认创建一个可以立即执行的空应用程序,这个程序只有一个和窗口设计界面一样的窗口。((图1)

图1
图1

   1. 对象观察窗口(Object Inspector)
   浏览和修改对象的属性(Properties)和事件(Events)。打开查看窗口的快捷键是F11,
    每个对象都有特定的属性和事件,我们将在后面做介绍((图2))。
图2
图2

   2. 代码编辑窗口
   ((图3)
图3
图3

    代码窗口左边的代码浏览器,列出了代码结构,可以通过它快速定位到特定的代码段。代码编辑器具有很强的自动感应功能,只要程序员键入“->”或者“.”符号,立即就显示出成员变量和成员函数的索引,极大提高了代码的书写效率和准确率,使用“Ctrl+空格”组合键也相同的功能。可是在中文Windows系统下“Ctrl+空格”是打开默认中文输入法,这就要在控制面板中的输入法设定中修改热键了。同样,在编写调用某个函数的代码中键入左括号,编辑器将提示函数的参数名和类别,此功能的组合键是“Ctrl+Shift+空格”。
   3.BCB5.0的主菜单和工具栏按钮
    BCB的全部功能都能在主菜单中找到相应的菜单项。下面作一个简单介绍:
   (1)File菜单
   ((图4)
图4
图4

   创建项目的选择窗口:
   包含各种类型的程序单元及一些对象创建向导,New页面包含最常用的项目:
   Application:创建一个新的工程,包含一个窗口和窗口的单元文件(.cpp和.h);
   Batch File:创建扩展名为.bat的批处理文件;
   Component:打开组件创建向导;
   Console Wizard:打开控制台程序创建向导;
   Cpp File:添加一个.cpp文件;
   Data Module:创建一个新的数据模块;
   DLL Wizard:打开DLL(动态连接库)创建向导;
   Form:添加一个空白窗口到当前工程;
   Frame:创建一个组件框架;
   Header File:添加一个头文件;
   Library:创建一个库;
   Package:创建一个组件包,可以封装方法并将包中组件安装到BCB的组件栏中;
   Project Group:创建一个新的工程组;
   Remote Data Module:创建一个远程数据模块;
   Report:创建数据报表;
   Resource DLL Wizard:打开创建资源DLL的向导;
   Text:新建一个文本文件;
   Thread Object:在当前工程中创建一个线程;
   Unit:添加一个单元(包含一个.cpp文件和一个.h文件)。
   (2)Edit菜单
   ((图5)
图5
图5

   (3)Search菜单
   ((图6)
图6
图6

   (4)View菜单
   ((图7)
图7
图7

   (5)Project菜单
   ((图8)
图8
图8

   (6)Run菜单
   ((图9)
图9
图9

   (7)Component菜单
   ((图10)
图10
图10

   (8)Database菜单
   ((图11)
图11
图11

   (9)Tools菜单
   ((图12)
图12
图12

   (10)Help菜单
   BCB带有非常详尽的Help文本,还有非常详细的WinAPI函数文档,在IDE的任何位置按F1键都可以找到相关的资料。
  #1 二、界面设计
    大多数Windows下的应用程序是由Windows提供的基本元素组成,例如应用程序的窗口、按钮或者是菜单。BCB为我们提供了大量的窗口、按钮、文字输入框等,它们就是BCB中的组件。每个组件都由自己特定的功能,程序员只用关注组件具有什么功能、能够实现什么效果,而不必去考虑这个组件是怎样制作,或者它是由什么制作。这样我们编写程序就像搭积木一样,一块一块的将零散的部件通过我们的代码就连接成为一个整体。
    在这里我们首先了解怎样将BCB提供的组件添加到程序的窗口上。
    组件分为可视组件和不可视组件:可视组件在工程设计或者运行阶段是可以显示的,如按钮、窗口等;不可视组件只是提供某种功能的实现而没有可视的界面,如对话框组件。
    在组件栏中选择一个组件(鼠标单击),然后在设计界面的窗口中用鼠标拖出组件的大小,或者双击组件栏上组件的图标,按组件默认大小和位置添加到设计窗口。同时组件也支持复制、粘贴等操作,粘贴的组件和复制的组件有相近的属性。
   1.调整组件的位置
    调整组件位置有很多的技巧,可以用鼠标拖动,也可以在属性编辑窗口中调整组件的位置属性,也可以使用Ctrl+上、下、左、右方向键,或者是Ctrl+Shift+方向键,或者使用Edit菜单中的Align(对齐)功能来实现。
    为了避免误操作改变组件的位置,可以在Edit菜单中选择Lock Controls功能,这时候就只能用修改属性和菜单中的调整功能了。
   2.选择组件
    可以用鼠标框线、Shift或者Ctrl键加鼠标单击组件的方式一次选择多个组件进行控制。在设计窗口的空白处单击鼠标左键不放,拖动鼠标,让虚线框框住一个或多个组件,放开鼠标按键就完成选择,但是一些组件是添加在其它组件中间的,鼠标拖拽会带动组件移动,可以按住Ctrl键完成框选工作来避免。
    当我们需要选择一个组件,然而这个组件恰好被其它组件完全覆盖时,可以在对象观察窗口中选择它,或者选择到这个组件中包含的子组件,然后按下Esc键。同样再次按下Esc键会选择到这个组件的父组件,最终会选择到包含这些组件的窗口。
   3.使用对象观察窗口
    对象观察窗口会显示当前选中组件的属性和事件,如果选中的是多个组件,则显示这些组件相同的属性和事件。
    现在我们学会了把组件放上窗口,在让它们为我们工作以前,我们得先学会一种能管理和指挥它们的语言C/C++。Borland C++ Builder(BCB)是工具,而C/C++才是语言。
  #1 三、什么是C/C++?
    C语言是使用非常广泛的编程语言,C++是在C语言的基础上发展而来的,可以说C++是C的超集。C++兼容C的很多语法,但是也有C没有的限制,不过C编写的代码可以在C++中进行少量修改或者无需修改就可以正常运行。
   1.编写C/C++代码
  void __fastcall TForm1::FormCreate(Tobject *Sender)
    {
   Form1->Caption = "Hello World!";
    }
    这条简单的语句意思是在创建窗口时将窗口(Form1)的标题(Caption)设定为"Hello World!"。其中
  void __fastcall TForm1::FormCreate(Tobject *Sender)
   {
   }
    是由编辑器自动生成的。在设计窗口的空白处双击鼠标,代码窗口中就会定位在窗口的创建函数中。在对象观察窗口的Events(事件)页面,双击某个事件,编辑器也会自动生成该事件的处理函数。关于具体组件的属性和事件将在VCL组件的应用中详细说明,这里我们重点关注C/C++的语法特点。
    C/C++代码的书写给程序员很大的灵活性,代码并不需要写在同一行上,每个语句总是以分号结束。上面的语句可以写成:
  Form1->Caption =
    "Hello World!";
   2.变量、赋值
    变量可以储存一定的数据,变量名由英文字母、数字和下划线组成,必须以英文字母或者下划线开头,一般编译器将下划线开头的变量作为特殊变量或者函数的开始。特别注意的是C/C++是区分大小写的,XYZ和xyz是两个不同的变量。
    变量声明由变量类型、变量名称组成:int a; //声明变量a为整型变量
    双斜杆(//)是行注释符,它后面到行结束都是注释。C/C++也支持多行注释/*(注释开始)和?*/(注释结束)
    声明过的变量如果不赋一个初值,那么变量的值将是不确定的,这和VB等语言不同,必须养成在使用变量或者其它对象前进行初始化。C/C++允许变量在声明的时候赋一个初始值:int a = 100; 声明整型变量a,值为100
    也可以同时声明几个变量:int a, b = 10, c = 2; 声明了a,b,c三个变量,b,c有初始值。
   3.变量的作用域
    变量的作用域决定了变量的使用范围,分为局部变量(Local)、全局变量(global)、静态变量(static)和外部变量(external)。
    局部变量的作用域只是在一个函数的内部,变量值的改变不会影响函数外同名变量。
    Void __fastcall TForm1::FormCreate(Tobject *Sender)
   {
   int x, y; //声明局部变量x, y
   x = 10;
   y = 25;
   ShowMessage((String)(x * y)); //显示x, y相乘的结果
   }
    x, y就是局部变量,只能在函数中使用,函数结束它们就被释放了。
    C/C++的初学者可能会对ShowMessage((String)(x * y))有疑惑。ShowMessage是Windows的API函数,作用是显示一个消息窗口,消息内容是这个函数的参数,参数是字符串型变量,(x * y)是整数型,不能直接赋值,因此需要使用强制转换语句(String)转化。
    静态变量与局部变量不同的是,变量只在第一次调用函数时赋初值,函数完成时保持变量值不变。
   Void teststatic()
    {
   statics int Count = 0; //声明一个静态变量,赋初值为0
   Count = Count + 1; //每调用一次函数Count加1
   ShowMessage((String)Count); //显示函数调用次数
    }
    同时Count又是teststatic函数的私有变量,因此不会被其它函数改变。
    全局变量在整个单元中可以被本单元的所有函数访问和修改,全局变量需要在函数体外声明,或者在单元的头文件中声明(.h),在一个新工程的窗口代码中可以看到有一个:
    TForm1 *Form1;
    Form1是一个全局变量,也是一个指针类型的变量。
    外部变量将局部变量的作用范围扩大到整个应用程序,需要通过extern关键字声明。在代码编辑窗口中点击鼠标右键,在弹出菜单中选择 Open Source/Header File, 打开单元头文件就能看到 extern PACKAGE TForm1 *Form1; 将变量Form1声明为一个外部变量,让整个工程的单元都能够访问它。
   4.变量类型
    C/C++支持一系列基本的数据类型,这些类型是由语言本身定义的,其它的任何数据类型都建立在这些基本类型的基础上。((图13)
图13
图13

  
  signed和unsigned是变量有无符号的修饰词,除了char类型外其它类型都是默认有符号(signed)。浮点类型变量受到计算机处理的精度限制,无法处理非常接近0的数字,只要对精度要求不是很高,我们都认为浮点类型是准确的。、
   5.运算符
    C/C++支持大量的运算符,功能强大,相对其它语言显得很复杂。对于初学者主要建立对这些运算符的印象,并不需要立即把它们都弄明白。
   ((图14)
图14
图14

  #1 四、最常用的控制结构
   控制结构可以用清晰的方式描述判断和循环。这里介绍最常用的if、while、for、do、switch。
    1.If语句
    语法:if(表达式)语句 [else 语句]
     if(表达式){执行代码} [else {执行代码}]
    方括号中的部分是可以省略的。
    例子:
    if(a == 0)ShowMessage("a 等于 0");
  if(a == 0)ShowMessage("a 等于 0"); else ShowMessage("a 不等于 0");
    
    if(a == 0){
   …
    } else {
   …
    }
    大括号{}中间可以由多条语句组成,if语句也可以嵌套使用,如:
    if(表达式){执行代码} else if(表达式){执行代码}
  
    2.while语句
    循环控制语句,原型:
    while(表达式)语句
    while(表达式){执行代码}
    如:
    while(count < 10){ //做十次循环
    …
    count++;
    }
  
    3.Do语句
    循环控制语句,原型:
    do 语句 while(表达式)
    do {执行代码} while(表达式)
    与while不同,do语句判断是否继续循环的控制条件是放在做完一次循环以后,就是说无论怎样,do都要完成第一次循环。当表达式值为假时就停止循环。
    4.For语句
    for循环是一个确定,不像while用一个表达式来控制循环,它的原型:
    for([初始化条件] ; [循环结束条件] ; [增量])执行代码
    
    for(int a = 0; a < 10; a++){…} //做十次循环
    原形中方括号部分可以省略,上面的程序也可以写为:
    int a = 0;
    for(;a++ < 10;a++){…}
  
    5.Switch语句
    条件选择语句,根据控制表达式的值选择执行相应的代码,原型:
    switch(表达式)
    {
    case 值1 :
    执行代码
    [break;]
    case 值2 :
    执行代码
    [break;]
   …
    [default :
     默认执行代码]
    }
    switch先计算表达式的值,然后执行对应的case部分。如果没有对应的case部分就转到default部分,用break表示结束,否则将执行到下面的分枝。Switch只能对整数操作,不支持对字符串和对象的操作。
    
    Char c;
    …
    switch(c)
    {
    case 'a' :
    case 'b' :
    case 'c' :
    ShowMessage("有效值");
     break;
    case 'd' :
    ShowMessage("无效值");
     break;
    default : ShowMessage("不确定值");
    }
    只要c等于'a', 'b'或者'c'都显示有效值。
    
  #1 五、指针
    指针使得C/C++语言变得强大,也让人难以理解,是众多朋友学习C/C++一大障碍。
    我们应该怎么理解指针?
    简单来说指针就是存贮内存地址的变量。
   ((图15)
图15
图15

   看起来指针像个整型变量,它的特殊意义在于告诉处理器在内存的哪个位置可以找到数据。*p就可以访问p指针指向的值,如上面例子中的128。
   【指针和实例】
   int a = 128, b;
   b = a;
   a, b是int型变量,a对b赋值是数据拷贝,修改一个变量的值不会影响另一个变量。
     Int a = 128;
   int *p = &a;
   由于*p和a是指向同一个内存地址的值,所以
   a = 32; 或 *p = 32;
   它们是等价的。
    实际上我们很少用int类型的指针,因为这样意义并不大(除非作为函数可变参数,下一节函数将介绍),只是作为例子帮助大家理解指针。指针在大多数时候用作大量数据的传送。
    使用指针必须先为指针分配内存,且在使用完以后需要释放分配的内存:
    String *vStr;
    vStr = new String; //为vStr分配内存空间
    *vStr = "Hello World!";
    String S = *vStr; //赋值给字符串实例S
    delete vStr; //释放指针
    
    对于例子中的实例S,访问它的成员要使用直接访问符号(.)
    S.Length() //计算字符串的长度
    而指针vStr访问成员就必须使用间接访问符号(->)
    vStr->Length()
    
    【指针与数组】
   int a[100]; //声明包含100个整型变量的数组
   int I = 0;
   while(I < 100)a[I++] = 25; //将数组中的每个元素初始化为25
  
   如果用指针来做:
   int a[100]
   int I = 0;
   int *p = a; //将数组a的开始地址传给指针
   while(I < 100)*p++ = 25;
   p首先指向a[0],*p赋值为25,指针下移指向a[1]
  
  #1 六、函数
    在使用函数前必须对函数进行声明,还需要写函数的具体代码。声明函数的原型:
    函数返回类型 函数名([参数]);
    例如:int add(int a, b);
    函数的实现代码:
     int add(int a, int b) //必须和声明的函数原形一致
    {
     return a + b; //返回a + b的值
    }
   以后我们就可以对函数add进行调用:add(3, 5);
   如果函数不返回任何值,那么它的类型为void
   void doSomething(int param);
   函数不需要return语句返回值,但是可以用return;提前退出函数。
    Void doSomething(int ¶m)
    int a = 100;
    void doSomething1(int ¶m)
    void doSomething2(int param)
    void doSomething1(int ¶m)
    {
     *param = 25;
    }
    void doSomething2(int param)
    {
     param = 25;
    }
    doSomething2(a);
    ShowMessage((String)a); //a等于100,值没有被改变;
    doSomething1(a);
    ShowMessage((String)a); //a等于25;
    
    【函数的重载】
    函数名称相同,有两种或几种不同的参数或返回值,编译器根据调用函数时的参数,选择对应的函数执行。下面的例子是一个类似条件运算符(?:)的函数。
    Int iif(bool express, int truevalue, int falsevalue);
    String iif(bool express, String truevalue, String falsevalue);
    
    int iif(bool express, int truevalue, int falsevalue)
    {
     if(express)return truevalue; else return falsevalue;
    }
    String iif(bool express, String truevalue, String falsevalue)
    {
     if(express)return truevalue; else return falsevalue;
    }
   int a;
   ……
   ShowMessage(iif(a > 2, "a大于2", "a小于等于2"));
   int c = iif(a > 2, a * 10, a);
  
   【怎样声明、使用函数指针】
    一般函数的指针是在调用动态连接库里的函数和回调函数时使用。声明函数指针和声明变量指针有很大差别:
    void(*p)(); //声明一个没有参数,无返回值的函数指针p
   可以将函数 void doSometing(); 的地址赋给p
   p = &doSomething;
   p(); //调用doSomething
   我们可以用更灵活的方式来使用指针:
   int __fastcall doSomething(int param); //doSomething函数的原形
   Pointer p = &doSomething; //声明p为一个指针指向doSomething的地址
   由于Pointer是没有规定类型的指针,所以在使用p调用doSomgthing函数时要先结果类型转换。
   ((int(__fastcall *)(int param))p)(5);
  
  #1 七、枚举、结构、类
    【枚举变量】
    枚举是一系列的条目。每个条目由编译器或者程序员分配一个识别数字,在编程的时候需要定义一系列常量(const),且保证这些常量各不相同,那么使用枚举将是非常有效率的。枚举的语法格式:
    enum [枚举名称] {
     项目名称, 项目名称, ……
    } [枚举变量名称];
   方括号([])中的内容是可以省略的
  
   enum TMyColor {Red, White, Yellow}MyColor;
   MyColor = Red;
  
    enum TMyNum {twelve = 12, thirteen, twenty = 20, twenty_one}; //注意:省略了枚举变量名但是不能省略最后的分号
   twelve指定值为12,那么thirteen就是它前面一个值加1即13
   TMyNum MyNum; //声明MyNum是枚举变量
   MyNum = twelve; 或者可以写成 MyNum = (TMyNum)12;
  
   【结构】
   结构由struct或者union关键字声明,结构包含各种成员,是公有访问类型数据成员的集合。它的语法格式如下:
   struct 名称 [: 基类] {
   数据类型的声明
    }[变量名];
  
   enum Tsex {male , female};
   struct Temployee {
   String name;
   Tsex sex;
   int age;
    };
    定义一个包含雇员的姓名、性别和年龄的结构:
   Temployee employee; //声明变量
   emploree.name = "小丽";
   employee.sex = female;
   employee.age = 21;
  
   结构是具有继承性的,它可以继承基类中的成员:
   struct Tperson : Temployee //从Temployee继承
   {
   String work;
   float income;
   };
   Tperson person;
   person.name = "小丽"; //从Temployee继承过来的成员
   person.work = "秘书"; //Tperson自身的成员
   ……
  
    union和struct在语法上是一致的,不同的是union内部的所有成员都使用相同的内存地址和共同的内存空间,在你需要不同的时候保存不同类型的变量时这将非常有用。
   Enum {Int, Float, Char};
   struct Tcommondata {
   int data_type;
   union {
   int intdata;
   float floatdata;
   char chardata;
   };
   }commondata;
  
   commondata.data_type = Int; //表明存放的是整型变量
   commondata.intdata = 10;
   commondata.data_type = Char; //表明存放的是字符变量
   commondata.chardata = 'A';
  
   struct和union可以包含多个struct或union结构:
   enum {Int, Float, Char};
   struct Tcommondata {
   int data_type;
   union {
   int intdata;
   float floatdata;
   char chardata;
   };
   struct {
   Pointer p;
   } datapoint;
   }commondata;
   ……
   commondata.data_type = Int; //表明存放的是整型变量
   commondata.intdata = 10;
   commondata.datapoint.p = NULL; //赋一个空指针