⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lc_bcb_19.txt

📁 c++ builder 的一些txt文档
💻 TXT
字号:

C++Builder3.0使用经验谈
C++Builder3.0使用经验谈
作者 
 
钟伟
工作单位  成都电子研究所
- C++ Builder 3.0 是Borland 公 司( 现 已 更 名 
为Insprise) 于1998 年 推 出 的 新 一 代 基 于C 语 言 的RAD 开 发 工 
具。C++ Builder 3.0 的 问 世, 对 广 大 爱 好C 语 言 的 用 户 来 说 不 
啻 是 个 福 音。 因 为 以 往 在Windows 下, 没 有 一 种 真 正 基 于C 
语 言 的 可 视 化 编 程 语 言。 你 如 果 想 用VB 或Delphi 这 一 类 可 
视 化 编 程 语 言 去 编 程, 你 就 不 得 不 去 重 温 一 遍Basic 或Pascal 
语 言, 没 有 了 像C 语 言 一 样 可 以 灵 活 应 用 的 指 针, 没 有 
了" + +"、"――" 这 样 一 类 可 爱 的 运 算, 总 
之 一 切 使 用 起 来 都 不 如C 语 言 一 样 得 心 应 手。 现 在 这 
一 切 烦 恼 都 不 复 存 在 了。C++ Builder 3.0 不 仅 支 持 传 统 的C 语 
言, 也 支 持Borland 的OWL 和Microsoft 的MFC。 可 以 这 样 说,C++ 
Builder3.0 是 目 前Windows 下 功 能 最 为 强 大 的C 语 言 编 译 器。 由 
于C++ Builder 3.0 问 世 不 久, 有 关 资 料 不 是 很 多, 下 面 结 合 
笔 者 的 使 用 情 况, 谈 谈 几 点 经 验、 体 会。 
---- 一、 动 态 调 用 窗 体Form 
---- 在 缺 省 情 况 下, 由File/New Form 生 成 
添 加 入 项 目 文 件 中 的 窗 体 都 具 有"Auto Create"( 自 动 
创 建) 的 特 性。 即 只 要 程 序 运 行, 该 窗 体 就 存 在 于 内 
存 中 了, 不 管 当 前 它 是 否 被 调 用。 具 有 这 种 特 性 的 窗 
体 一 般 适 用 于 窗 体 属 性 比 较 固 定、 经 常 被 调 用 的 情 
况。 其 优 点 是 速 度 快, 缺 点 是 占 用 内 存。 在 实 际 程 序 
设 计 中, 会 遇 见 大 量 类 似 对 话 框 功 能 的 窗 体, 它 们 用 
于 显 示 状 态 或 输 入 信 息, 仅 须 在 程 序 中 调 用 一 下, 完 
成 其 功 能 就 行 了, 无 需 常 驻 内 存。 这 时 可 以 通 过 选 择Project/Options/Forms, 
将"Auto--Create forms " 栏 中 相 应 的 窗 体, 如Form1, 用" 
>" 键 移 动 到 "Available forms" 栏 中, 并 在 程 序 需 调 
用 该 窗 体 处, 加 入 下 列 语 句: 
	TForm1	*myform=new TForm1(this);
		myform- >ShowModal();
			delete myform;
---- 窗 体Form1 仅 是 在 需 要 调 用 时 才 调 
入 内 存, 调 用 完 成 后, 即 用delete 清 除 出 内 存。 这 样 可 减 
少 程 序 对 内 存 资 源 的 占 用。 
---- 二、 遍 历 窗 体 控 件 的 方 法 
---- 要 访 问 或 修 改 窗 体 上 的 控 件, 
方 法 很 简 单, 以TEdit 为 例 子: 
---- Edit1- >Text=""; 
---- Edit2- >Text=""; 
---- 但 如 果 窗 体 上 有 十 来 个 像Edit1 这 
样 的 控 件, 需 要 进 行 相 同 的 初 始 化, 用 上 面 的 方 法 一 
个 一 个 地 进 行, 岂 不 麻 烦 ! 所 以 有 必 要 掌 握 遍 历 窗 体 
控 件 的 方 法。 在 介 绍 该 方 法 之 前, 让 我 们 先 了 解 一 下 
窗 体Form 的Components 和Controls 属 性。 参 见 表 一。 
表 一 
  
    属性
    类型
    说明
  
  
    ComponentCount
    Int
    目前Form上各类
    控件的总数
  
  
    Components
    TCompont*
    目前Form上指向
    所有控件的数组
  
  
    ControlCount 
    Int
    目前Form上某一子
    区域上各类控件的总数
  
  
    Controls TControl*
     
    目前Form上指向某一子
    区域上所有控件的数组
  
---- 以 图 一 为 例( 图 略) 说 明,Form1 的ComponentCount=6, 
而Panel1 的ControlCount=4., 
---- 其 中: 数 组 对 象 
Components[0]		Panel1
Components[1]		Label1
Components[2]		Edit1
Components[3]		Label2
Components[4]		Edit2
Components[5]		Button1
数 组		        对 象
Controls[0]			Label1
Controls[1]			Edit1
Controls[2]			Label2
Controls[3]			Edit2
---- 下 面 这 段 代 码 完 成 了 对Panel1 上 所 
有TEdit 控 件 的 遍 历 初 始 化。 读 者 稍 加 修 改, 即 可 对 其 它 
控 件 进 行 遍 历。 这 里 有 一 个 小 技 巧, 我 们 把 需 要 进 行 
初 始 化 的 控 件 放 置 在 了 一Panel1 上, 与 不 需 要 初 始 化 的 
控 件 区 分 开 来, 这 样 便 于 编 程。 
    AnsiString namestring="TEdit";
    for(int i=1;i ControlCount;i++)
    {
        if(Panel1- > Controls[i]- > 
ClassNameIs(namestring))
        {
            TEdit *p=dynamic_cast
 (Panel1- >Controls[i]);
            P- >Text="";
        }
}
---- 三、 用Enter 键 控 制 焦 点 切 换 的 
方 法 
---- 在Windows 环 境 下, 要 使 一 个 控 件 取 
得 焦 点, 可 在 该 控 件 上 用 鼠 标 单 击 一 下, 或 按Tab 键 将 
焦 点 移 至 该 控 件 上。 这 种 控 制 焦 点 切 换 的 方 法 有 时 不 
符 合 用 户 的 习 惯。 就 图 一 而 言, 用 户 就 希 望 用Enter 键, 
控 制 焦 点 由Edit1 切 换 到Edit2。 要 实 现 这 样 的 功 能 需 借 助WinAPI 
函 数SendMessage 来 完 成。 方 法 是: 先 设Form1 的KeyPreview 属 性 为true, 
然 后 在Form1 的OnKeyPress 事 件 中 加 入 如 下 的 代 码。 这 样, 用 
户 就 可 以 通 过 按Enter, 键 控 制 焦 点 按 定 义 好 的Taborder 顺 
序 来 移 动 了 ! 
void __fastcall TForm1::
FormKeyPress(TObject *Sender, char &Key)
{
    if(Key==VK_RETURN)
    {
        SendMessage(this- >Handle,WM_NEXTDLGCTL,0,0);
        Key=0;
    }
}
---- 四、 为TStringGrid 的 文 字 加 上 颜 色 
---- TStringGrid 是C++ Builder 提 供 给 用 户 的 
一 种 字 符 网 格 控 件。 美 中 不 足 的 是, 它 没 有 提 供 分 别 
修 改 各 单 元 字 体 颜 色、 大 小 的 方 法。 其 实 要 为TStringGrid 
实 现 这 样 功 能, 只 需 在 程 序 中 稍 加 处 理 就 行 了。 方 法 
是 自 定 义 一 个 二 维 数 组cellbuf, 它 的 下 标 与 网 格 单 元 列 
行 一 一 对 应, 用 于 存 放 各 网 格 单 元 的 颜 色、 文 字 等 信 
息。 
    struct CellStru
    {
        AnsiString msg;	// 文 字 信 息
        TColor color;		// 文 字 颜 色
};
CellStru cellbuf[MAXCOL][MAXROW];
---- 初 始 化cellbuf 后, 再 在 字 符 网 格 控 
件StringGrid1 的OnDrawCell 响 应 事 件 中, 加 入 如 下 的 代 码 即 可。 
void __fastcall TForm1::StringGrid1DrawCell
      (TObject *Sender, int Col,
      int Row, TRect &Rect, TGridDrawState State)
{
    StringGrid1- >Canvas- >Font- >
          Color=cellbuf[Col][Row].color;
StringGrid1- >Canvas- >TextOut(Rect.Left+3,
       Rect.Top+3,cellbuf[Col][Row].msg);
	}
---- 五、 软 件 封 面 的 实 现 
---- 现 代 软 件 设 计 的 流 行 做 法 是, 
在 程 序 运 行 完 成 初 始 化 之 前, 先 调 用 一 幅 画 面 做 为 封 
面, 通 常 是1/4 屏 幕 大 小, 显 示 一 下 软 件 的 名 称、 作 者、 
版 本 等 信 息。 要 用C++ Builder 实 现 这 样 的 功 能, 方 法 很 简 
单: ① 自 定 义 一 窗 体 类TSplashForm, 将 其 设 置 成" 透 明 窗 
口", 即BorderIcons 下 的 所 有 选 项 均 置 成false,BorderStyle=bsNone,FormStyle=fsStayOnTop,Position=poScreenCenter; 
② 在TSplashForm 窗 体 上 放 置 一TPanel( 相 当 于 图 形 的 镜 框); 
③ 在TPanel 上 放 置 一TImage 控 件, 调 入 所 需 要 的 图 形; ④ 对WinMain 
函 数 稍 加 修 改, 加 入 如 下 所 示 代 码 即 可。 需 要 指 出 的 
是, 这 段 代 码 通 过 函 数FindWindow, 搜 索 内 存 中 是 否 有 窗 
口 标 题 为"Demo" 应 用 程 序 存 在, 若 存 在, 则 退 出 程 
序 的 运 行。 该 功 能 可 防 止 程 序 的 再 次 运 行。 在 某 些 场 
合 这 样 设 计 是 必 须 的。 
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
        if(FindWindow(NULL,"Demo")!=0)
        {
            Application- >MessageBox
        (" 程 序 已 经 运 行!"," 警 告",MB_ICONSTOP);
            return 0;
        }
        TSplashForm *splash=new TSplashForm(Application);
        splash- >Show();
        splash- >Update();
        Application- >Initialize();
        Application- >CreateForm(__classid(TForm1), &Form1);
        splash- >Close();
        delete splash;
        Application- >Run();
    }
    catch (Exception &exception)
    {
        Application- >ShowException(&exception);
    }
    return 0;
}
---- 六、 如 何 永 久 清 除DBF 中 的 已 被 
删 除 的 记 录 
---- 用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);
---- 七、I/O 端 口 读 写 的 实 现 
---- 细 心 的 读 者 会 发 现,C++ Builder 不 再 
支 持 如inportb()、outportb() 一 类I/O 端 口 读 写 指 令 了。 准 确 地 
说, 在Windows 环 境 下,Borland C++ 仅 支 持16 位 应 用 程 序 的 端 口 
操 作, 对32 位 应 用 程 序 的 端 口 操 作 不 再 支 持, 而C++ Builder 
开 发 出 来 的 程 序 是32 位 的。 我 个 人 以 为, 这 是C++ Builder 设 
计 者 的 败 笔。 因 为PC 机 中,I/O 地 址 空 间 与 内 存 地 址 空 间 
从 来 都 是 各 自 独 立 的。 看 看Delphi, 不 就 通 过Port 数 组 实 
现 了 对I/O 端 口 的 访 问 了 吗 ? 搞 不 清 楚 为 什 么C++ Builder 就 
没 有 提 供 类 似 的 机 制 ? 下 面 这 几 个 函 数 是 笔 者 从 网 
上 淘 下 来 的, 经 过 验 证, 在Windows95 环 境 下, 的 确 可 实 现 
对I/O 端 口 的 读 写。 读 者 可 以 借 鉴 使 用。 
void outportb(unsigned short 
int port, unsigned char value)
{
       // mov edx, *(&port);
       __emit__(0x8b, 0x95, &port);
       // mov al, *(&value);
       __emit__(0x8a, 0x85, &value);
       // out dx, al;
       __emit__(0x66, 0xee);
}
void outportw(unsigned short 
int port, unsigned short int value)
{
       // mov edx, *(&port);
       __emit__(0x8b, 0x95, &port);
       // mov ax, *(&value);
       __emit__(0x66, 0x8b, 0x85, &value);
       // out dx, ax;
       __emit__(0xef);
}
unsigned char inportb(unsigned short int port)
{
       unsigned char value;
       // mov edx, *(&port);
       __emit__(0x8b, 0x95, &port);
       // in al, dx;
       __emit__(0x66, 0xec);
       // mov *(&value), al;
       __emit__(0x88, 0x85, &value);
       return value;
}
unsigned short int inportw(unsigned short int port)
{
       unsigned short int value;
       // mov edx, *(&port);
       __emit__(0x8b, 0x95, &port);
       // in ax, dx
       __emit__(0xed);
       // mov *(&value), ax
       __emit__(0x66, 0x89, 0x85, &value);
       return value;
}
---- 八、 软 件 的 分 发 
---- 在Windows 下 开 发 的 应 用 程 序 一 般 
都 比 较 庞 大, 程 序 的 运 行 往 往 离 不 开 一 大 堆 不 知 名 的 
系 统DLL 文 件。 为 了 生 成 能 脱 离C++ Builder 环 境、 独 立 运 行 
的 应 用 程 序, 读 者 须 对 编 译 器 进 行 一 定 的 设 置。 方 法 
是: 置Project/Option/Packages/Run with runtime packages 为Disable, 置Project/Option/Linker/Uses 
dynamic RTL 为Disable, 重 新 编 译 一 遍 程 序, 这 样 生 成 的EXE 文 件 
就 可 以 脱 离C++ Builder 环 境 运 行 了。 但 如 果 你 的 程 序 中 应 
用 了 数 据 库, 仅 有 上 述 的 操 作 是 不 够 的-- 因 为, 你 还 
得 安 装BDE(Borland Database Engineer)。BDE 的 安 装 比 较 麻 烦, 读 者 最 
好 是 用C++ Builder3.0 附 带 的InstallShield Express 来 制 作 安 装 盘, 把 
应 用 程 序 和BDE 打 包 在 一 起。 如 果 找 不 到, 也 可 用Delphi3.0 
附 带 的InstallShield Express 来 制 作。InstallShield 的 使 用 方 法, 限 
于 篇 幅, 不 再 介 绍。 有 条 件 的 读 者 可 上 网 查 到 有 关 资 
料。 
返回

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -