📄 bcjq030.txt
字号:
---- 在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 的 使 用 方 法, 限 于
篇 幅, 不 再 介 绍。 有 条 件 的 读 者 可 上 网
查 到 有 关 资 料。
if (ad==1) {document.write(''+'');}
if (ad==2) {document.write(''+'');}
if (ad==3) {document.write(''+'');}
C++ Builder开发者®
2000年06月01日 站长:唐朝