美 国 微 软 出 版 社 授 权 的 标 准 、 权 威 、 完 整 的 中 文 图 书
M icrosoft Visual C++ 6.0
程 序 员 指 南
〔 美 〕 Beck Zaratian 著希 望 图 书 创 作 室 译
希 望 图 书 创 作 室 审 校
本 书 配 套 光 盘 包 括 两 部 分 内 容 :
-
. 本 书 英 文 原 版 附 带 光 盘 中 的 例 子 代 码 及 可 执 行 程 序
-
. 与 本 书 配 套 的 中 文 版 电 子 书
北 京 希 望 电 脑 公 司 出 品
1 9 9 8
内 容 提 要
本 书 是 美 国 微 软 出 版 社 授 权 的 M icrosoft Visual Studio 系 列 中 文 版 图 书 之一 , 它 是 Visual C++ 6.0 程 序 员 的 实 用 参 考 书 。 全 书 共 分 成 六 个 部 分 : 第 一 部 分介 绍 Developer Studio 和 AppWizard 的 基 础 知 识 ; 第 二 部 分 介 绍 文 本 、 图 形 和 对话 框 编 辑 器 ; 第 三 部 分 是 编 程 指 南 , 展 示 了 如 何 使 用 ClassWizard 和 Gallery 来加 速 编 程 开 发 工 作 , 创 建 自 己 的 组 件 ; 第 四 部 分 介 绍 ActiveX 控 件 及 其 使 用 ,说明 如 何 用 MFC 或 ATL 来写 ActiveX 控 件 ; 第 五 部 分 讨 论 调 试 器 的 各 种 能 力 ,程序 优 化 的 各 种 选 项 及 原 因 , 如 何 定 制 Visual C++ , 如 何 编 制 宏 和 附 加 实 用 程 序 ; 第 六 部 分 提 供 ASCII 字 符 和 ANSI 字 符 的 标 准 表 格 , 并 简 要 描 述 ClassWizard 支持 的 MFC 类 和 VBScrip t。
书 中 讨 论 的 许 多 主 题 均 以 范 例 程 序 进 行 说 明 , 所 有 范 例 程 序 的 项 目 文 件 都在 配 套 光 盘 上 。本 书 是 从 事 Visual C++ 6.0 应 用 与 开 发 的 所 有 技 术 人 员 极 好 的 工具 书 , 同 时 也 是 大 专 院 校 相 关 专 业 的 师 生 的 自 学 、 教 学 参 考 用 书 。
本 书 配 套 光 盘 包 括 两 部 分 内 容 : 1. 本 书 英 文 原 版 附 带 光 盘 中 的 例 子 代 码 及可 执 行 程 序 ; 2. 与 本 书 配 套 的 中 文 版 电 子 书 。
需 要 本 书 和 配 套 光 盘 及 需 技 术 支 持 的 读 者 请 与 北 京 海 淀 8721 信 箱 书 刊 部 联系 , 邮 政 编 码 : 100080 , 联 系 电 话 : 010-62562329 , 62541992 , 62531267 , 传真 : 010-62579874 。
版 权 声 明
本 书 英 文 版 名 为《 M icrosoft Visual C++ 6.0 Programme r’s Guide 》,由 Microsoft 出版 社 出 版 , 版 权 归 M icrosoft 出 版 社 所 有 。 本 书 中 文 版 由 Microsoft 出 版 社 授 权 出版 。 未 经 出 版 者 书 面 许 可 ,本 书 的 任 何 部 分 不 得 以 任 何 形 式 或 任 何 手 段 复 制 或 传播 。
本 书 封 四 上 贴 有 防 伪 标 签 , 无 标 签 者 不 得 销 售 , 违 者 必 究 !
M icrosoft Visual C++ 6.0 程 序 员 指 南
[ 美 ] Beck Zaratian 著希 望 图 书 创 作 室 译 希 望 图 书 创 作 室 审 校责 任 编 辑 刘 晓 融
北 京 希 望 电 脑 公 司 出 品
北 京 海 淀 路 82 号 ( 100080 )
印 刷
新 华 书 店 、 新 华 书 店 音 像 发 行 所 发 行 、 各 地 书 店 及 软 件 专 卖店 经 销
* * * * *
1998 年 12 月 第 1
版
1998 年 12 月 第 1
次 印 刷
开 本 : 787 × 1092 印 张 : 39.125
字 数 : 916 千 字 印 数 : 1-5000
新 出 音 管 [1998]164 号
ISBN 7-980021-23-1/TP · 16
定 价 : 68.00 元 ( 1CD , 含 配 套 书 )
致 谢
第 二 版 要 比 第 一 版 容 易 写 ,因 为 在 第 二 版 中 问 题 已 解 决 了 一 半 。我 乐 意 写 ( 或者 更 准 确 地 说 , 是 扩 展 ) 这 本 书 的 主 要 原 因 是 , 我 又 一 次 得 到 了 具 有 献 身 精 神 的人 们 的 帮 助 。尽 管 处 理 过 较 早 版 本 的 M icrosoft Press 小 组 已 经 转 向 出 版 书 籍 的 其他 任 务 ,但 他 们 的 贡 献 仍 在 ,他 们 认 真 负 责 的 工 作 态 度 和 敬 业 精 神 在 本 书 留 下 了深 深 的 烙 印 。
在 第 一 版 中 ,项 目 编 辑 Lucinda Rowley 在 百 忙 之 中 花 费 了 许 多 时 间 ,他 审 阅手 稿 具 有 敏 锐 的 观 察 力 ( 在 书 名 为《 M icrosoft Visual C++ Owner's Manual》的 版 本中 , 我 将 Lucinda 誉 为 “ 每 位 作 家 梦 寐 以 求 的 编 辑 ”, 他 的 确 名 符 其 实 )。 手 稿 编辑 Vicky Thulman 推 敲 了 每 个 句 子 , 而 技 术 编 辑 Linda Ebenstein 和 Jim Johnson 确 保 所 述 内 容 的 确 切 。
项 目 编 辑 Saul Candib 和 技 术 编 辑 Jim Fuchs , M ary DeJong 和 M ichael Hochberg 仔 细 审 阅 了 新 材 料 。 旧 金 山 的 Labrecque 出 版 社 在 编 辑 、 版 式 、 校 对 和制 作 管 理 等 方 面 做 了 大 量 工 作 , 为 此 谨 向 Chrisa Hotchkiss、 Curtis Philip s、 Lisa Bravo 、 Andrea Fox 和 Lisa Labrecque 表 示 谢 意 。
我 不 仅 得 到 了 来 自 Press 和 Labrecque 的 帮 助 ,而 且 得 到 微 软 公 司 42 楼 Visual C++ 分 部 的 支 持 。 如 同 以 前 一 样 , Laura Hamilton 充 当 了 联 络 员 的 角 色 , 我 很 感激 , 因 为 如 果 没 有 她 的 帮 助 , 我 将 无 法 写 出 这 本 书 来 。 Laura 是 一 名 高 级 编 辑 ,
她 可 以 保 证 本 书 和 在 线 《 Visual C++ User's Guide》 的 质 量 。
这 个 版 本 离 不 开 Visual C++ 小 组 ( 以 及 其 他 领 域 ) 中 许 多 人 的 帮 助 , 他 们 为 第一 版 做 了 勘 误 , 提 出 了 有 价 值 的 建 议 。 其 他 人 审 阅 了 这 一 版 的 新 材 料 , 集 思 广 益确 保 本 书 的 结 构 严 谨 和 内 容 实 用 。 在 此 谨 向 Dennis Andersen 、 Cathy Anderson 、Chuck Bell、 D iane Berkeley 、 Patricia Cornette 、 Stacey Doerr 、 Chris Flaat、 Jocelyn Garner、 Anita George、 Eric Gunnerson 、 Karl Hilsmann 、 M ark Hopkin s、 Simon Koeman 、 Chris Koziarz 、 Louis Lafreniere 、 Martin Lovell、 M ichael Maio 、 Bruce M cKinney 、 Diane Melde 、 Daryn Robbins、 Steve Ross 、 David Schwartz 、 Scott Semyan 、 Teeri Sharkey 、 George Shepherd 、 Kathy Shoesmith 、 Suzanne Sowinska 、Yefim Siga l 、 Chuck Sphar 、 Yeong-Kan Tam 、 Donn Trenton 和 Laura Wall 表 示 谢意 。 这 些 人 中 的 一 部 分 是 我 认 识 多 年 的 朋 友 , 其 他 则 从 未 见 过 面 , 仅 仅 通 过 电 子邮 件 和 联 邦 快 递 相 互 通 信 。
特 别 值 得 一 提 的 是 微 软 公 司 的 Barbara Ellsworth , 没 有 她 , 本 书 将 无 法 写 成 。感 谢 Barb 。
本 书 中 文 版 的 问 世 渗 透 了 参 与 策 划 、 翻 译 、 录 排 、 审 校 和 出 版 人 员 的 大 量 心血 。 本 书 由 贺 军 、 贺 民 、 王 雷 、 陈 武 、 刘 传 凯 、 高 胜 友 、 佟 大 双 、 程 宏 筠 等 人 翻译 , 邓 蛟 龙 、 陈 代 川 、 龚 亚 萍 、 王 晓 娟 、 吴 安 定 、 孟 丽 艳 、 王 学 龙 、 张 定 军 等 人也 做 了 大 量 的 工 作 ,希 望 图 书 创 作 室 技 术 人 员 对 该 书 进 行 了 仔 细 审 校 ,在 此 深 表感 谢 。
前 言
本 书 是 M icrosoft Visual C++ 6.0 程 序 员 指 南 , 不 是 C++ 语 言 , 也 不 是 MFC 库 , 而 仅 仅 与 Visual C++ 本 身 有 关 。
确 实 , Visual C++ 带 有 程 序 设 计 者 的 指 导 手 册 , 即 在 线 帮 助 。 那 庞 大 的 帮 助 系 统可 能 会 激 励 你 , 使 你 自 信 些 , 因 为 你 想 知 道 的 内 容 会 在 帮 助 系 统 的 某 个 地 方 。 但是 , 在 线 帮 助 的 问 题 是 , 当 你 知 道 你 要 找 什 么 时 , 它 才 能 很 好 地 起 作 用 。 这 本 书弥 补 了 在 线 帮 助 的 不 足 , 但 不 能 取 代 它 。帮 助 系 统 和 书 面 文 字 在 目 的 和 风 格 上 存在 着 固 有 的 差 异 , 因 而 谁 都 不 能 取 代 另 一 个 。 它 们 一 个 是 提 供 有 关 信 息 , 另 一 个则 是 教 你 怎 么 做 。 一 个 范 围 广 泛 , 而 另 一 个 则 有 深 度 。 在 线 帮 助 尽 可 能 简 洁 地 提供 清 晰 的 事 实 ,而 不 是 详 细 的 描 述 ,它 提 供 一 个 步 骤 列 表 ,来 指 导 完 成 一 些 任 务 , 但 很 少 花 时 间 来 进 行 整 体 描 述 。 从 中 你 可 以 知 道 “ 如 何 做 ”, 而 不 是 “ 为 什 么 这样 做 ”。
本 书 试 图 使 你 成 为 Visual C++ 的 熟 练 用 户 。 它 按 材 料 的 逻 辑 层 次 展 开 , 展 示 了 整体 的 各 部 分 之 间 是 如 何 相 互 关 联 的 , 它 用 简 单 的 代 码 来 阐 明 原 理 , 并 常 充 当 指 导老 师 的 角 色 。而 且 ,它 携 带 方 便 。它 确 实 拥 有 在 线 帮 助 所 缺 乏 的 优 点 。另 一 方 面 , 在 线 帮 助 非 常 直 接 , 而 且 范 围 广 泛 。 数 兆 字 节 的 帮 助 文 本 可 以 涉 及 到 Visual C++
的 每 个 细 节 , 而 本 书 仅 讨 论 一 些 要 点 。
首 先 , 从 本 书 上 获 得 Visual C++ 坚 实 的 基 础 知 识 , 然 后 , 当 你 经 验 更 丰 富 , 而 问题 变 得 更 深 奥 时 , 你 可 以 转 向 在 线 帮 助 。 有 意 思 的 是 , 你 对 产 品 越 熟 悉 , 在 线 帮助 就 越 有 用 。
本 书 第 一 版 的 书 名 为 《 M icrosoft Visual C++ Owner’ s M anual 》, 它 成 为 微 软 关 于Visual C++ 5 版 的 正 式 指 南 。但 微 软 把 第 二 版 改 名 为《 程 序 员 指 南 》, 是 为 了 把 它作 为 Visual Studio 98 系 列 丛 书 ( 共 五 本 ) 的 一 部 分 , 其 余 四 本 分 别 为 《 Visual Basic 》、《 Visual J++ 》、《 Visual FoxPro 》和 《 Visual InterDev 》 四 种 开 发 工 具 提 供相 关 文 档 。本 书 独 立 成 册 ,如 果 你 的 兴 趣 仅 局 限 于 Visual C++ ,你 就 找 对 了 地 方 。本 “ 指 南 ” 和 其 他“ 指 南 ” 之 间 的 相 似 之 处 仅 在 于 封 面 , 因 为 其 他“ 指 南 ” 只 是在 线 帮 助 的 副 本 ( 每 个 产 品 所 带 的 在 线 文 档 的 副 本 )。 你 会 发 现 本 书 同 其 他 “ 指南 ” 完 全 不 同 。
微 软 有 充 分 的 理 由 为 本 书 改 名 , 但 我 对 丢 掉 原 来 的 书 名 感 到 遗 憾 。 我 选 择
《 Owner ’ s Manua l》( 用 户 手 册 ) 来 尽 可 能 清 楚 地 表 达 本 书 的 重 点 , 以 便 使 读 者对 哪 些 是 本 书 涉 及 的 内 容 ,哪 些 不 是 ,可 以 有 清 醒 的 认 识 。如 果 是 在 一 百 多 年 前 , 那 容 忍 冗 长 标 题 的 时 代 , 我 可 以 加 上 一 些 东 西 , 如 “ 作 为 教 程 、 伴 侣 和 参 考 书 , 它 深 入 阐 述 M icrosoft Visual C++ 的 知 识 , 它 不 介 绍 C++ 编 程 语 言 和 Microsoft 基础 类 库 ”。 显 然 , 那 个 冗 长 的 标 题 并 不 完 全 精 确 。 Visual C++ 同 C++ 语 言 和 MFC 库 完 整 地 联 系 在 一 起 , 以 致 于 不 可 能 只 谈 论 Visual C++ , 而 不 提 及 其 他 两 者 。 下
面 的 章 节 为 了 说 明 Visual C++ 的 某 个 方 面 而 提 供 了 许 多 范 例 和 程 序 。代 码 必 须 有注 释 , 否 则 它 是 没 有 用 的 。 范 例 程 序 的 说 明 也 扩 展 到 技 术 和 MFC 的 主 题 。 但 这些 事 情 是 相 互 独 立 的 , 并 且 , 不 会 分 散 我 们 如 何 使 用 编 译 器 的 重 点 。 其 他 优 秀 的书 籍 可 用 来 解 释 C++ 编 程 和 MFC 库 。
本 书 描 述 Visual C++ 6 版 , 但 较 早 版 本 的 所 有 者 也 能 从 中 受 益 。 Visual C++ 的 某些 方 面 同 以 前 的 版 本 相 比 有 相 当 大 的 变 动 , 但 其 他 许 多 地 方 变 动 甚 微 ,甚 至 根 本没 有 变 动 。 近 来 , Visual C++ 附 带 发 行 了 一 个 很 小 的 包 裹 , 其 中 有 少 量 传 单 、 一些 印 刷 材 料 及 一 两 个 光 盘 。但 是 ,由 于 你 早 就 阅 读 了 这 些 ,你 可 能 意 识 到 ,Visual C++ 中 有 大 量 的 材 料 。 我 称 它 为 “ 编 译 器 ”, 仅 仅 是 因 为 缺 乏 更 好 的 名 字 。 除 编译 器 本 身 外 , Visual C++ 提 供 了 链 接 器 、 生 成 实 用 程 序 、 调 试 器 、 文 本 编 辑 器 、资 源 编 辑 器 、 开 发 环 境 、 微 软 基 础 类 库 ( MFC )、 运 行 时 间 库 、 成 千 上 万 行 源 代码 和 其 他 许 多 东 西 。 重 申 一 次 : 本 书 不 会 阐 述 每 件 事 情 。 我 的 目 的 是 帮 助 你 掌 握Visual C++ , 而 不 是 在 某 些 细 节 上 纠 缠 。
读 者 要 求
这 类 书 不 能 从 学 习 曲 线 的 零 点 开 始 。如果起点太低 , 对 预 备 知 识 的 讨 论 会 让 人 感到 混 乱 。 若 起 点 太 高 , 则 作 者 会 失 去 多 数 听 众( 除 了 作 为 无 足 轻 重 的 东 西 , 而 给人 留 下 印 象 )。 诀 窍 在 于 , 对 有 各 式 各 样 的 技 术 和 兴 趣 的 读 者 , 我 们 以 同 一 种 方式 来 说 明 ,然 而 ,在 谈 论 深 奥 知 识 时 ,不 能 失 掉 一 个 听 众 ,且 在 提 供 基 础 知 识 时 ,
也 不 会 惹 恼 任 何 一 个 人 。 本 书 没 有 太 多 的 要 求 。 我 假 定 你 已 经 熟 悉 C 和 C++ 编程 语 言 , 以 前 进 行 过 Windows 编 程 , 并 至 少 对 MFC 有 基 本 的 认 识 。 无 论 如 何 , 你 不 必 是 专 家 , 但 如 果 你 理 解 一 些 基 本 概 念 , 如 指 针 、 类 和 消 息 , 你 会 发 现 , 文本 和 范 例 代 码 更 容 易 懂 。 幸 运 的 是 , 关 于 编 译 器 , 这 里 并 没 有 什 么 抽 象 的 东 西 , 它 只 是 一 个 软 件 而 已 。
Visual C++ 简 史
人 们 可 以 举 出 , Visual C++ 的 根 源 不 是 开 始 于 M icrosoft 而 是 Borland 的 事 例 。 一些 读 者 可 能 会 记 起 ,给 DOS 带 来 集 成 开 发 环 境 ,或称 IDE 的 想 法 的 Turbo Pascal 。IDE 仍 是 某 个 领 域 内 的 另 一 个 缩 写 , 它 们 的 状 况 已 经 改 变 了 。 IDE 只 是 意 味 着 , 编 辑 器 和 编 译 器 共 同 工 作 , 二 者 可 从 同 一 个 地 方 访 问 。 在 编 辑 器 中 写 下 源 代 码 , 单 击 Compile ( 编 译 ) 按 钮 来 启 动 编 译 器 。 当 编 译 器 发 现 错 误 时 , 它 将 编 辑 光 标设 到 出 错 语 句 处 , 以 便 于 你 改 正 问 题 。 IDE 的 想 法 是 , 为 程 序 开 发 提 供 一 个 整 体环 境 , 程 序 员 无 须 从 中 离 开 到 其 他 程 序 中 。
C 语 言 正 是 这 个 时 候 诞 生 的 ( 公 元 1987 年 ), Turbo Pascal 发 行 了 Turbo C 。M icrosoft 相 应 地 推 出 相 似 的 产 品 , 称 为 QuickC 。 我 被 邀 做 一 些 与 QuickC 相 关的 编 程 工 作 , 并 在 结 束 时 写 些 指 导 性 文 章 , 这 些 被 包 括 在 产 品 包 装 中 , 题 为 《 C for Yourself 》( 标 题 不 是 我 想 的 )。 QuickC 作 为 一 个 产 品 单 独 发 售 , 但 它 也 包 括在 我 们 称 之 为 Big C 的 Microsoft’ s C 编 译 器 中 。 当 时 , Big C 版 本 号 为 5 。 它 的
竞 争 对 手 包 括 : Computer Innovations、 Datalight 、 Lattice 、 M anx , 这 些 名 字 现 在听 起 来 很 陌 生 。 其 他 有 些 幸 存 下 来 , 著 名 的 有 Borland 和 Watcom ( 现 在 是PowerSoft )。 它 们 优 秀 的 产 品 继 续 同 M icrosoft 公 司 竞 争 着 。
把 QuickC 同 Big C 放 在 一 起 的 目 的 是 , 使 程 序 员 能 在 QuickC 方 便 的 IDE 下 编写 代 码 。 QuickC 编 译 起 来 很 快 , 主 要 是 因 为 它 对 代 码 仅 作 些 微 优 化 ( 本 书 后 面会 谈 及 优 化 , 那 时 我 们 会 看 到 它 是 如 何 影 响 编 译 时 间 的 )。 QuickC 优 化 时 只 是 登记 一 些 变 量 , 插 入 几 条 LEAVE 指 令 , 仅 此 而 已 。 结 果 是 编 译 时 间 很 短 。 程 序 调试 过 后 , 再 在 QuickC 中 运 行 时 , 程 序 员 就 能 用 Big C 创 建 一 个 正 式 版 , 它 在 代码 优 化 方 面 做 得 更 为 正 式 些 。 当 用 Big C 编 译 时 , 程 序 的 大 小 减 少 15% 或 更 多 , 这 并 非 怪 事 。
QuickC 和 Turbo C 给 C 编 程 引 进 了 许 多 东 西 , 但 从 没 有 对 开 发 者 产 生 永 久 性 的影 响 。 首 要 原 因 就 是 二 者 的 编 辑 器 都 不 怎 么 好 ( QuickC 编 辑 器 后 来 合 并 到M icrosoft QuickBasic 中 , 现 在 它 作 为 D O S 编 辑 器 Edit.com 仍 存 在 于 M icrosoft W indows 95 中 ) 。 DOS 下 IDE 的 另 一 个 问 题 就 是 , 它 们 占 据 大 量 内 存 , 只 给 开发 环 境 下 的 程 序 运 行 留 下 很 少 的 空 间 。 你 经 常 不 得 不 离 开 IDE 来 运 行 和 调 试 程序 。 许 多 在 开 发 工 作 中 使 用 QuickC 的 程 序 员 ( 包 括 我 自 己 ) 仅 仅 使 用 它 的 命 令行 版 本 。
随 后 , Windows 3.0 出 现 了 。
W indows 3.0 尤 其 是 3.1 , 为 个 人 计 算 机 引 进 了 正 式 的 IDE 时 代 。 内 存 的 约 束 消
失 了 。 而 且 , 如 果 你 准 备 做 W indows 编 程 , W indows 环 境 看 来 是 天 生 的 好 地 方 。人 们 很 容 易 明 白 ,在 W indows 下 进 行 W indows 编 程 ,会 产 生 更 好 的 结 果 。W indows 是 个 优 秀 的 软 件 , 长 期 在 Windows 下 工 作 , 会 使 你 对 一 个 程 序 应 该 做 什 么 , 不应 该 做 什 么 , 有 更 好 的 认 识 。
让 许 多 人 惊 奇 的 是 , M icrosoft 把 精 力 更 多 地 集 中 在 C 编 译 器 的 内 部 支 持 上 , 而不 是 把 它 的 界 面 升 级 到 一 个 新 的 时 代 。 当 7 版 发 行 时 , 它 仍 然 是 一 个 基 于 DOS 的 产 品 , 它 既 可 以 在 Windows 下 的 DOS 模 式 下 运 行 , 也 可 以 在 扩 展 内 存 管 理 器下 运 行( 它 的 包 装 盒 中 带 有 Qualitas ’s 386Max )。作 为 让 步 , 7 版 提 供 了 一 个 名 为Programme r’ s Workbench 的 字 符 模 式 的 ID E , 它 已 成 为 现 有 标 准 的 累 赘 。 然 而 , Workbench 展 示 了 自 QuickC 时 代 以 来 的 自 然 而 然 的 演 变 结 果 。 许 多 菜 单 中 的 命令 看 起 来 还 是 很 现 代 化 的 , 例 如 New 、 Open 、 Save A s、 Build 和 Open Project 。
7 版 对 编 程 工 作 的 重 要 贡 献 不 是 它 的 IDE ,而是它对 C++ 的 支 持 。M icrosoft 首 次把 编 译 器 指 明 为 “ C/C++ ”, 来 强 调 其 新 的 双 重 性 。 它 看 起 来 就 像 细 胞 分 裂 一 样 。它 不 只 是 简 单 地 扩 展 编 译 器 , 来 辨 认 C++ 超 集 的 新 命 令 , 而 是 牵 涉 到 更 多 的 东西 。C/C++ 7 版 也 引 进 了 M icrosoft Foundation Class 库 1.0 版 , 完 善 了 源 代 码 。如果 没 有 M icrosoft 发 送 给 开 发 者 的 这 套 优 秀 的 预 写 类 , C++ 就 不 会 成 为 现 在 这 么流 行 的 W indows 编 程 工 具 。
微 软 下 一 个 主 要 的 让 步 是 放 弃 了 多 数 产 品 对 DOS 的 依 赖 。 M icrosoft C/C++ 8 版成 为 真 正 的 Windows ID E, 它 就 是 大 家 所 知 道 的 Visual C++ 1 版 。 这 个 名 字 利 用
了 早 期 Visual Basic 的 成 功 , 但 二 者 从 未 互 相 抗 衡 过 。 Visual Basic 允 许 开 发 者 通过 大 量 单 击 鼠 标 和 少 量 代 码 来 建 立 正 在 运 作 的 W indows 程 序 ,而 Visual C++ 仅 仅通 过 向 导 这 样 的 特 殊 动 态 链 接 库 来 创 建 启 动 器 源 文 件 。 在 第 2 章 中 , 我 们 将 看到 : 向 导 挽 救 了 众 多 开 发 过 程 中 重 复 性 的 工 作 , 这 种 对 W indows 程 序 来 说 非 常普 通 的 工 作 是 由 MFC 编 写 的 。
Visual C++ 1.5 版 之 后 ,微 软 决 定 不 再 将 更 多 的 努 力 花 在 支 持 16 位 编 程 上 。Visual C++ 2 版 仍 提 供 对 16 位 的 支 持 , 但 自 从 那 时 起 , Visual C++ 仅 用 来 创 建 32 位 程序 。 没 有 Visual C++ 3 版 。 版 本 号 从 2 跳到 4 来 , 使 Visual C++ 和 MFC 同 步 , 这 样 就 结 束 了 一 个 小 小 的 混 乱 来 源 。 然 而 , 这 种 合 并 是 短 期 的 , 因 为 Visual C++ 和 MFC 又 使 用 了 不 同 的 版 本 号 。
Internet 的 流 行 已 经 明 显 地 影 响 了 产 品 设 计 , 在 发 行 第 4 版 时 , Visual C++ 引 进 了为 Internet 编 程 而 设 计 的 新 类 库 。 5 版 也 增 加 了 一 些 新 类 , 但 注 意 力 更 多 地 集 中在 改 善 产 品 的 界 面 上 , 以 提 供 一 个 更 好 的 在 线 帮 助 系 统 、 更 高 级 的 宏 能 力 和 对 在开 发 者 组 内 进 行 类 和 其 它 代 码 共 享 的 支 持 。 5 版 也 合 并 了 Active Template Library , 并 显 著 地 改 善 了 编 译 器 优 化 代 码 的 能 力 。 在 后 面 的 章 节 中 我 们 将 看 到 :
6 版 作 了 更 进 一 步 的 改 进 。
本 书 内 容
本 书 分 成 六 个 部 分 , 每 个 部 分 讨 论 一 个 与 Visual C++ 及 它 的 开 发 环 境 相 关 的 话题 。 一 直 到 讨 论 文 本 编 辑 器 的 第 3 章 , 我 们 都 有 意 地 保 持 一 些 基 本 的 讨 论 , 这 有助 于 确 保 每 位 读 者 , 不 论 是 新 手 还 是 专 家 , 都 能 成 功 地 操 纵 Visual C++ 开 发 环境 , 及 在 文 本 编 辑 器 中 编 写 源 代 码 。 从 第 4 章 开 始 , 讨 论 逐 渐 变 得 更 专 业 一 些 。
第 一 部 分 : 基 础 知 识
我 们 通 常 所 说 的 Visual C++ 实 际 上 是 它 的 开 发 环 境 , 它 的 名 字 是 M icrosoft Developer Studio 。 二 者 之 间 的 细 小 差 别 并 不 重 要 , 通 常 这 两 个 术 语 可 以 互 换 。 但如 果 你 不 围 绕 Developer Studio 来 进 行 学 习 , 就 不 能 有 效 地 使 用 Visual C++
( Developer Studio 听 起 来 很 像 Visual Studio , 但 它 们 之 间 没 有 关 系 , 因 此 , 在 阅读 本 书 时 , 你 可 以 忘 掉 它 )。
第 1 章 可 以 说 是 方 向 性 的 , 它 介 绍 了 Developer Studio , 并 描 述 了 你 在 这 个 环 境下 工 作 时 将 要 碰 到 的 主 要 的 窗 口 。 这 一 章 也 解 释 了 如 何 使 用 M icrosoft Developer Network( M S D N ), 它 为 包 括 Visual C++ 在 内 的 所 有 微 软 的 程 序 产 品 提 供 在 线 帮助 系 统 。
第 2 章 介 绍 了 AppWizard ,它是用 MFC 来 为 典 型 的 W indows 应 用 程 序 创 建 启 动
器 文 件 的 Visual C++ 向 导 程 序 。在 本 书 中 , 我 们 将 用 AppWizard 来 建 立 一 些 范 例程 序 。
第 二 部 分 : 编 辑 器
Visual C++ 提 供 了 三 个 不 同 的 编 辑 器 : 一 个 用 来 创 建 文 本 源 代 码 , 另 一 个 用 来 创建 菜 单 和 图 形 文 件 , 而 第 三 个 用 来 创 建 对 话 框 。 每 个 编 辑 器 都 用 一 章 来 介 绍 , 首先 是 在 第 3 章 中 讲 述 文 本 编 辑 器 。这 一 章 仔 细 说 明 了 重 要 的 菜 单 命 令 ,展 示 了 打开 文 本 文 档 的 快 捷 方 式 , 并 介 绍 了 宏 。
第 4 章 描 述 了 Visual C++ 多 功 能 的 图 形 编 辑 器 ,它 可 以 用 来 创 建 包 括 菜 单 、位 图 、图 标 和 工 具 栏 在 内 的 资 源 数 据 。 这 一 章 篇 幅 不 小 , 因 为 它 涉 及 到 许 多 材 料 。 随 着内 容 的 深 入 , 将 会 产 生 一 个 名 为 D iskPie1 的 范 例 程 序 。 每 个 部 分 首 先 描 述 如 何用 图 形 编 辑 器 来 创 建 一 个 特 定 的 界 面 元 素 , 如 菜 单 或 工 具 栏 , 然 后 , 通 过 把 该 元素 加 入 到 D iskPie1 程 序 来 举 例 说 明 。 到 这 一 章 的 结 尾 , 这 个 程 序 就 成 为 一 个 以饼 图 形 式 显 示 磁 盘 和 内 存 的 使 用 情 况 的 实 用 程 序 。
第 5 章 讨 论 对 话 框 编 辑 器 ,并 展 示 如 何 用 Visual C++ 来 设 计 对 话 框 和 创 建 基 于 对话 框 的 应 用 程 序 , 如 W indows Character Map 和 Phone Dialer 程 序 。 这 一 章 举 了几 个 例 子 , 包 括 一 个 能 建 立 一 个 属 性 表 ( 也 称 多 选 项 卡 对 话 框 ) 的 例 子 。
第 三 部 分 : 编 程 指 南
第 三 部 分 中 的 几 章 展 示 了 如 何 使 用 Visual C++ 中 的 两 个 重 要 工 具 来 加 速 编 程 开发 工 作 。 第 6 章 介 绍 了 ClassWizard , 尽 管 它 很 难 描 述 , 但 很 容 易 让 人 喜 欢 。 当开 发 MFC 应 用 程 序 时 , 你 会 发 现 , ClassWizard 对 于 创 建 和 维 护 类 是 非 常 有 帮 助的 。
第 7 章 中 描 述 的 Gallery 提 供 了 一 个 附 加 组 件 的 集 合 , 你 只 要 点 几 下 鼠 标 , 就 可以 把 它 们 合 并 到 你 的 项 目 中 去 。 Visual C++ 带 有 许 多 已 经 做 好 的 由 类 的 源 代 码 和ActiveX 控 件 组 成 的 组 件 。 第 7 章 还 演 示 如 何 为 Gallery 来 创 建 你 自 己 的 组 件 。
第 四 部 分 : ActiveX 控 件
第 8 章 介 绍 ActiveX 控 件 , 并 展 示 如 何 在 应 用 程 序 中 使 用 它 们 。 第 9 章 和 第 10 章 分 别 从 不 同 方 向 来 说 明 如 何 用 MFC 或 Active Template Library ( ATL ) 来 写 一个 ActiveX 控件。第 9 章 提 供 了 一 个 名 为 Tower 的 范 例 , 来 带 领 你 一 步 一 步 地 创建 和 编 码 一 个 依 赖 于 MFC 的 ActiveX 控 件 。 然 后 , 第 10 章 用 Active Template Library 来 建 立 一 个 同 样 的 控 件 , 从 而 清 楚 地 说 明 这 两 种 方 法 之 间 的 不 同 之 处 。结 果 可 以 插 入 到 任 何 支 持 ActiveX 控 件 的 应 用 程 序 中 。
第 五 部 分 : 高 级 主 题
第 11 章 讨 论 了 调 试 器 的 重 要 主 题 , 它 是 Visual C++ 最 完 美 的 组 成 部 分 之 一 。 这一 章 说 明 了 调 试 器 的 内 部 特 征 ,描 述 了 调 试 器 窗 口 和 工 具 栏 ,然 后 通 过 修 复 范 例程 序 中 隐 藏 的 缺 陷 来 检 验 调 试 器 的 能 力 。
当 程 序 调 试 过 后 , 你 将 希 望 打 开 编 译 优 化 来 创 建 一 个 发 行 版 。 第 12 章 讨 论 编 译器 优 化 的 一 些 通 常 难 以 理 解 的 主 题 , 同 时 , 展 示 Visual C++ 的 诸 多 优 化 选 项 开 关的 作 用 及 使 用 的 原 因 。
到 第 13 章 的 时 候 ,你 应 已 在 Developer Studio 环 境 上 花 费 了 大 量 时 间 ,这 些 足 够使 你 知 道 自 己 喜 欢 什 么 和 想 要 改 变 什 么 。这 一 章 展 示 了 如 何 定 制 Visual C++ 来 适合 你 的 喜 好 。 它 也 通 过 范 例 演 示 了 如 何 编 制 宏 和 附 加 实 用 程 序 , 来 使 它 们 同Developer Studio 紧 密 地 结 合 在 一 起 。
第 六 部 分 : 附 录
附 录 A 提 供 了 ASCII 字 符 和 ANSI 字 符 的 标 准 表 格 。 你 可 能 会 发 现 附 录 A 中 的ANSI 字 符 表 比 在 线 帮 助 中 的 类 似 信 息 要 有 用 得 多 , 因 为 该 表 显 示 了 字 符 的 八 进制 数 形 式 。 这 样 做 是 有 理 由 的 。 我 们 在 第 5 章 中 看 到 : 在 对 话 框 文 本 中 包 含 大 写ANSI 字 符 需 要 字 符 的 八 进 制 数 形 式 。 有 了 这 些 信 息 , 你 就 可 以 在 对 话 框 显 示 的
文 本 字 符 串 中 添 加 一 些 有 用 的 标 志 , 例 如 和 ¼ 。
附 录 B 简 要 描 述 了 ClassWizard 支 持 的 MFC 类 , 它 可 以 作 为 快 速 参 考 , 用 来 帮助 你 给 新 类 选 择 最 合 适 的 基 类 。
附 录 C 介 绍 了 M icrosoft Visual Basic Scripting Edition , 即 VBScript 。 Visual C++ 把 VBScript 合 并 为 它 的 宏 语 言 , 因 此 , 如 果 你 以 前 没 有 使 用 过 VBScript 或 类 似的 Visual Basic 语 言 , 这 里 可 以 作 为 一 本 初 级 读 物 。 尽 管 在 Visual C++ 中 录 制 宏并 不 需 要 VBScript 的 有 关 知 识 , 但 是 , 你 只 有 用 VBScript 编 程 , 才 能 创 建 一 个多 用 途 的 宏 。
范 例 代 码
本 书 中 几 乎 每 个 范 例 程 序 都 是 以 C++ 语 言 写 的 ,并 使 用 了 MF C( 两 个 例 外 是 第 4 章 中 的 一 个 光 标 演 示 程 序 , 以 及 第 13 章 的 一 个 基 于 控 制 台 的 小 程 序 )。但是,我在 文 中 的 一 些 程 序 片 段 中 还 是 使 用 C 语 言 。 我 发 现 C++ 在 简 明 地 说 明 编 程 意 图方 面 不 如 C 好 ,并 且 除 了 清 楚 和 简 洁 的 优 点 外 ,C 还 在 现 在 的 程 序 员 间 充 当 一 种“ 通 用 语 言 ”。 从 理 论 上 来 说 , C++ 程 序 员 可 以 直 接 理 解 C , 但 反 过 来 就 不 一 定对 。 另 一 方 面 , C 没 有 地 方 来 演 示 MFC 应 用 程 序 。 当 我 认 为 有 些 重 要 的 想 法 , 而 且 , 二 者 间 的 差 别 太 大 而 需 要 解 释 时 , 我 偶 尔 也 会 同 时 给 出 C 和 C++ 代 码 。
本 书 中 诸 多 章 节 讨 论 的 主 题 都 有 很 好 的 范 例 说 明 , 而 我 一 直 试 图 包 括 那 些 有 趣的 、有 用 的 和 能 说 明 问 题 的 范 例 程 序 。一 些 程 序 是 用 AppWizard 创 建 的 , 另 一 些不 是 ,这 样 就 可 以 模 拟 范 围 广 泛 的 编 程 实 践 。 书 中 对 几 乎 每 个 程 序 都 进 行 了 彻 底的 讨 论 。 书 中 也 包 括 了 源 代 码 列 表 , 因 此 , 你 无 须 在 编 辑 器 中 打 开 源 文 件 , 就 可参 加 讨 论 。 程 序 代 码 力 求 清 楚 , 而 不 是 优 美 。 因 此 , 毫 无 疑 问 , 对 一 部 分 代 码 你可 以 在 自 己 的 开 发 工 作 中 采 取 不 同 的 处 理 。例 如 ,我 在 程 序 中 很 少 包 含 有 错 误 检查 标 志 。 程 序 是 在 W indows 95 下 创 建 的 , 但 多 数 是 在 W indows NT 下 测 试 的 。
附 带 光 盘
所 有 范 例 程 序 的 项 目 文 件 都 在 书 后 所 附 的 光 盘 上 。为 了 把 所 有 的 项 目 复 制 到 硬 盘上 , 按 下 列 步 骤 执 行 Setup 程 序 :
-
在 W indows 任 务 栏 上 单 击 Start 按 钮 并 选 择 Run 命 令 。
-
在 Run 对 话 框 中 键 入 “ d:\setup ”, 其 中 d 代 表 光 驱 的 驱
动 器 号 。
Setup 程 序 从 光 盘 上 复 制 3M 多 文 件 到 硬 盘 上 , 它 们 放 在 名 为 Visual C++ Programme r’ s Guide( 或 你 指 定 的 名 字 ) 的 子 目 录 下 。 运 行 Setup 完 全 是 可 选 的 , 如 果 你 愿 意 , 可 以 手 动 地 从 光 盘 上 再 次 获 得 这 些 文 件 。你 会 发 现 所 有 的 文 件 都 位于 Code 子 目 录 下 。
嵌 套 的 子 文 件 夹 指 明 了 描 述 程 序 的 章 节 号 和 项 目 名 。 例 如 , 子 文 件 夹Chapter.05\ M fcTree 中 保 留 了 生 成 第 5 章 中 的 M fcTree 程 序 所 需 的 全 部 文 件 。 每个 项 目 文 件 夹 都 有 一 个 名 为 Release 的 子 文 件 夹 , 该 目 录 包 含 了 程 序 的 可 执 行 文件 。 因 此 , 你 可 以 直 接 试 验 范 例 程 序 , 而 不 必 先 生 成 它 。 如 果 你 想 通 过 生 成 范 例程 序 来 参 加 文 中 的 讨 论 , 启 动 Visual C++ ,从 File 菜 单 中 选 取 Open Workspace 命 令 。 在 硬 盘 上 浏 览 项 目 夹 , 并 双 击 项 目 的 DSW 文 件 。
范 例 程 序 的 项 目 名 保 持 为 八 个 字 符 或 更 少 。这 一 惯 例 适 应 了 那 些 宁 愿 使 用 较 早 版本 的 文 本 编 辑 器 的 读 者 , 这 些 编 辑 器 可 能 不 能 识 别 长 文 件 名 。一 些 老 版 本 的 光 盘驱 动 器 也 不 能 识 别 长 文 件 名 。
附 带 光 盘 包 含 了 一 个 名 为 Index 的 程 序 。 Index 不 是 一 个 范 例 程 序 , 因 此 你 不 会在 书 中 找 到 对 它 的 说 明 。 Index 为 本 书 提 供 了 索 引 , 它 在 所 有 的 章 节 和 附 录 中 进行 全 字 符 搜 索 。 它 保 证 只 要 某 个 主 题 在 书 中 的 某 个 地 方 提 及 过 , 你 就 可 以 找 到它 。 这 个 程 序 实 际 上 是 书 志 学 家 所 称 的“ 词 语 索 引 ” 的 电 子 形 式 : 给 出 一 个 或 更多 的 词 , 程 序 就 会 告 诉 你 , 它 们 出 现 在 哪 一 页 、 哪 一 段 。 使 用 这 个 程 序 需 要 把 文件 Index.exe、 Index.hlp 和 Index.key 从 光 盘 上 复 制 到 硬 盘 上 , 一 定 要 把 这 三 个 文件 放 在 同 一 目 录 下 。 如 果 你 愿 意 的 话 , 也 可 以 直 接 从 光 盘 上 执 行 Index 。 该 程 序外 观 如 下 图 所 示 。
Index 窗 口 中 的 四 个 组 合 框 每 一 个 接 受 一 个 单 词 。 这 些 单 词 可 以 组 成 一 个 短 语 ,
如 “ Active Template Library ”, 或 仅 仅 是 指 定 一 些 一 同 出 现 在 同 一 段 或 同 一 页 的毫 无 关 联 的 几 个 词 。 程 序 也 能 搜 索 单 词 的 复 数 和 由 -ed 和 -ing 形 成 的 派 生 词 , 并能 考 虑 到 单 词 拼 写 上 细 微 的 变 化 。 例 如 , 搜 索 单 词 edit 、 handle 和 debug , 程 序同 时 会 找 出 edits 、 handling 和 debugged 的 出 现 位 置 来 。 搜 索 单 词 的 大 小 写 无 关紧 要 , 不 常 见 的 简 写 可 能 会 导 致 意 外 的 匹 配 。 例 如 , 当 搜 索 只 取 首 字 母 的 缩 写GUID 时 ,Index 会 找 到 单 词 guiding 。单 击 Search 按 钮 或 书 图 标 ,即 可 开 始 搜 索 。
四 个 组 合 框 会 记 住 上 一 个 搜 索 词 , 因 此 你 无 须 再 次 输 入 。 要 调 用 以 前 输 入 过 的 单词 , 点 开 组 合 框 的 下 拉 列 表 , 并 选 中 该 单 词 即 可 。 弹 出 式 帮 助 信 息 解 释 了 程 序 的其 他 特 色 。 单 击 对 话 框 右 上 角 的 小 问 号 按 钮 , 然 后 单 击 控 件 窗 口 或 组 合 框 区 , 即可 获 得 相 关 帮 助 。 Windows NT 3.51 的 用 户 必 须 按 F1 键 才 能 获 得 帮 助 。
Index 把 一 页 中 的 每 一 段 标 识 为 一 个 数 字 , 如 2 或 7 。 当 搜 索 一 页 来 找 出 程 序 指出 的 特 定 的 一 段 时 , 注 意 下 面 的 规 则 , 它 决 定 程 序 认 为 哪 一 段 是 搜 索 到 的 :
-
图 表 的 标 题 组 成 单 独 一 段 , 如 表 格 的 每 一 行 都 是 一 段
。
-
源 代 码 的 每 一 行 ( 包 括 空 行 ) 都 代 表 一 段 。
-
一 页 首 端 的 一 段 的 一 部 分 不 能 作 为 单 独 的 一 段 , 因 为
Index 认 为 这 些文 本 属 于 上 一 页 底 端 的 一 段 。
Index 程 序 能 识 别 布 尔 操 作 符 AND 、OR 或 N O T 。 如 果 你 对 全 文 本 搜 索 中 的 布 尔
逻 辑 有 些 生 疏 的 话 , 第 1 章 描 述 了 当 搜 索 MSDN 在 线 帮 助 系 统 时 如 何 使 用 布 尔操 作 符 。 参 见 表 1-1 的 例 子 。
一 些 术 语 定 义
在 深 入 本 书 前 , 应 定 义 一 些 术 语 , 例 如 生 成 、项 目 、目 标 、配 置 和 应 用 程 序 框 架 。由 于 在 下 面 的 章 节 中 要 用 到 这 些 词 , 因 此 最 好 现 在 说 明 它 们 的 意 义 。
生 成 指 编 译 和 链 接 , 把 一 组 源 文 件 转 变 成 可 执 行 的 应 用 程 序 。 编 译 源 文 件 , 链 接对 象 文 件 , 然 后 项 目 就 生 成 了 。 项 目 有 两 个 相 互 关 联 的 的 含 义 。 它 可 以 指 最 终 的结 果 , 即 生 成 的 应 用 程 序 , 但 更 准 确 的 是 指 创 建 应 用 程 序 所 需 文 件 的 集 合 , 包 括源 文 件 、预 编 译 头 文 件 、资 源 脚 本 、图 形 文 件 和 其 他 建 立 该 程 序 所 需 的 任 何 文 件 。Visual C++ 一 次 仅 允 许 打 开 一 个 项 目 , 这 时 你 已 经 可 以 访 问 所 有 的 项 目 文 件 , 并可 以 进 行 编 辑 、 生 成 和 调 试 。 每 个 项 目 可 以 拥 有 任 意 数 量 的 嵌 套 子 项 目 , 当 开 发一 个 包 含 多 个 可 执 行 元 素 的 程 序 时 , 安 排 这 些 子 项 目 是 非 常 有 意 义 的 。 例 如 , 你
可 以 开 发 一 个 应 用 程 序 作 为 主 项 目 ,而 把 一 个 辅 助 的 动 态 链 接 库 作 为 独 立 的 子 项目 。
生 成 一 个 项 目 后 创 建 的 应 用 程 序 有 两 种 类 型 : 发 行 版 和 调 试 版 。 Visual C++ 有 时
用 术 语“ 目 标 ” 来 指 定 生 成 类 型 。 项 目 的 正 式 目 标 是 提 供 给 最 终 用 户 的 可 执 行 程序 。 调 试 目 标 是 计 划 开 发 过 程 中 的 可 执 行 程 序 。 项 目 设 置 , 就 是 所 说 的 配 置 , 决定 Visual C++ 生 成 项 目 时 创 建 的 可 执 行 文 件 是 发 行 版 的 , 还 是 调 试 版 的 。
- 般 类 的 MFC 库 通 过 提 供 W in32 API 作 为 一 套 类 对 象 ,来 使
W indows 编 程 更 容易 。 使 用 MFC 的 程 序 利 用 测 试 过 的 代 码 作 为 一 个 应 用 程 序 框 架 来 处 理 许 多 任务 , 否 则 , 应 用 程 序 不 得 不 自 己 来 照 顾 这 些 事 。 这 些 隐 藏 服 务 的 唯 一 代 价 是 , 对于 大 多 数 MFC 程 序 来 说 , 可 执 行 文 件 尺 寸 可 能 更 大 , 并 存 在 某 些 内 置 的 公 共 部分 。 应 用 程 序 框 架 通 过 类 来 指 明 应 用 程 序 的 结 构 , 而 不 是 细 节 。 然 而 , MFC 并没 有 严 格 限 制 程 序 员 的 创 造 力 ,许 多 不 同 的 W indows 应 用 程 序 是 用 MFC 编 写 的这 一 事 实 就 可 证 明 这 一 点 。
参 考 资 料
推 荐 参 考 书 可 不 容 易 做 , 我 感 到 责 任 重 大 。 书 是 很 昂 贵 的 , 不 仅 是 在 金 钱 方 面 , 更 主 要 的 是 在 时 间 方 面 。下 面 是 一 些 我 认 为 能 给 使 用 Visual C++ 的 程 序 员 提 供 有价 值 的 资 料 的 书 。 它 们 碰 巧 都 是 M icrosoft Press 出 版 的 , 但 这 只 是 因 为 我 没 有 说出 更 多 的 书 名 。
- 要 开 始 了 解 MFC ,我 相 信 ,没 有 比 Jeff Prosise 的《
Programming Windows
95 with MFC 》 更 好 的 书 了 。 我 喜 欢 这 本 书 。 它 写 得 很 好 , 清 楚 明 了 ,
主 题 明 确 、 一 致 。
-
关 于 MFC 的 另 一 本 好 书 是 David Kruglinski 的 《 Inside Visual
C++ 》 。不 要 被 标 题 愚 弄 了 , 这 本 书 的 重 点 是 MFC , 讨 论 了 Prosise 的 书 中 没有 讨 论 过 的 主 题 , 例 如 数 据 库 管 理 和 OLE 。 讨 论 和 所 有 的 范 例 程 序 都假 定 读 者 正 使 用 Visual C++ 。
-
如 果 你 是 W indows 编 程 新 手 , 想 加 强 基 础 , 并 更 愿 意 用
C 语 言 , 而 不是 C++ 语 言 编 程 , 可 以 考 虑 Charles Petzold 和 Paul Yao 的 《 Programming W indows 95 》。该 系 列 的 最 新 版 本 首 先 出 现 在 大 约 十 年 前 ,这 本 书 仅 仅是 因 为 它 对 W indows 编 程 这 一 主 题 的 清 楚 说 明 而 出 名 的 。注 意 书 中 的警 告 , 尽 管 除 了 最 后 一 章 , 该 书 没 有 提 及 C++ 或 MFC 。
-
David Chappell 的 《 Understanding ActiveX and OLE 》 详 细 介 绍
了ActiveX 。 尽 管 它 对 Visual C++ 没 有 说 什 么 , 对 编 程 也 很 少 提 及 , 这 本值 得 一 读 的 书 对 复 杂 的 主 题 提 供 了 全 面 的 看 法 。
反 馈
如 果 你 对 本 书 的 再 版 有 什 么 建 议 , 写 信 给 我 。 我 会 仔 细 阅 读 收 到 的 电 子 邮 件 的 每一 行 ( 我 对 这 些 事 是 很 勤 奋 的 ), 尽 管 我 不 能 保 证 回 信 。 在 Internet 的beckz@witzendsoft.com 上 可 以 访 问 到 我 。
目 录
第 一 部 分 基 础 知 识
第 1 章 环 境
工 具 栏 和 菜 单
环 境 窗 口在 线 帮 助MSDN 库
在 开 发 环 境 之 外 工 作
第 2 章 AppWizard ( 应 用 程 序 向 导 ) AppWizard ( 应 用 程 序 向 导 ) 的 优 点运 行 AppWizard ( 应 用 程 序 向 导 )
用 AppWizard ( 应 用 程 序 向 导 ) 来 创 建 DLL 文件
第 二 部 分 编 辑 器
第 3 章 文 本 编 辑 器启 动 文 本 编 辑 器文 档
浏 览 文 档文 本 搜 索
编 程 辅 助 工 具Advanced ( 高 级 ) 命 令未 结 合 命 令
宏 的 基 础定 制 编 辑 器
在 Developer Studio 之 外 编 辑 文 本
第 4 章 资 源
系 统 资 源
RC 资 源 脚 本 文 件Resource.h 头 文 件AppWizard 资 源 的 例 子例 程 D iskPie1 简 介
菜 单 和 加 速 键
字 符 串 资 源 和 状 态 栏
位 图 、 工 具 栏 、 图 标 和 光 标向 DiskPie1 添 加 代 码
再 谈 未 结 合 命 令
修 整 资 源 数 据
第 5 章 对 话 框 和 控 件
对 话 脚 本对 话 编 辑 器
例 1 : 修 改 About 对 话
例 2 : 简 单 的 非 模 态 对 话 框
例 3 :向 AppWizard 程 序 添 加 对 话基 于 对 话 的 应 用 程 序
第 三 部 分 编 程 帮 助 工 具
第 6 章 C lass W izard ( 类 向 导 )
访 问 ClassWizard ClassWizard 对话
W izardBa r( 向 导 栏 )
ClassWizard 如 何 识 别 类
用 ClassWizard 创 建 对 话 类
第 7 章 Gallery ( 组 件 集 )
例 子 : 添 加 一 个 属 性 表
例 子 : 添 加 初 始 屏 幕 和 时 钟创 建 自 定 义 的 组 件
第 四 部 分 ActiveX 控 件
第 8 章 使 用 ActiveX 控件
背 景 知 识 简 介控 件 包 容 器
在 包 容 器 和 ActiveX 控 件 之 间 进 行 通 信
编 写 包 容 器 应 用 程 序
在 没 有 对 话 编 辑 器 的 情 况 下 工 作
第 9 章 使 用 MFC 编 写 ActiveX 控件
用 于 创 建 ActiveX 控 件 的 Visual C++ 工 具
ControlWizard
许 可
例 1 : 什 么 都 不 做 的 ActiveX 控 件例 2 : Tower ActiveX 控 件
向 ActiveX 控 件 项 目 添 加 属 性 页
第 10 章 用 ATL 编 写 ActiveX 控 件
ATL 和 包 容 器 应 用 程 序
ATL 和 ActiveX 控 件
示 例 1 : Pulse ActiveX 控 件
例 子 2 : TowerATL ActiveX 控 件对 比 组 件 模 型
第 五 部 分 高 级 主 题
第 11 章 调 试 器调 试 与 发 行调 试 器 的 使 用断 点
断 点 返 回 控 制 权 给 调 试 器 的 方 式建 立 调 试 版 本
调 试 器 界 面
例 子 : 开 发 和 调 试 ShockWave 程 序
特 殊 的 调 试 情 况
第 12 章 编 译 器 优 化
优 化 入 门优 化 开 关
从 调 试 到 发 行
基 准 Visual C++
第 13 章 自 定 义 Visual C++ Options( 选 项 ) 对 话 框Customize ( 自 定 义 ) 对 话 框工 具 栏
添 加 命 令 到 Tools ( 工 具 ) 菜 单宏
Developer Studio 附 加 项
第 六 部 分 附 录
附 录 A ASCII 和 ANSI 文 件 格 式
附 录 B C lassWizard 支 持 的 MFC 类
附 录 C VBScript 初 步
第 一 部 分 基 础 知 识
第 1 章 环 境
Visual C++ 软 件 包 包 含 了 许 多 单 独 的 组 件 , 如 编 辑 器 、 编 译 器 、 链 接 器 、 生 成 实用 程 序 、 调 试 器 , 以 及 各 种 各 样 为 开 发 M icrosoft Windows 下的 C/C++ 程 序 而 设计 的 工 具 。 幸 运 的 是 , 它 还 包 含 有 一 个 名 为 Developer Studio 的 开 发 环 境 。Developer Studio 把 所 有 的 Visual C++ 工 具 结 合 在 一 起 ,集 成 为 一 个 整 体 ,通 过 一个 由 窗 口 、 对 话 框 、 菜 单 、 工 具 栏 、 快 捷 键 及 宏 组 成 的 和 谐 系 统 , 你 可 以 观 察 和控 制 整 个 开 发 进 程 。 集 成 开 发 环 境 就 像 一 间 带 有 监 视 器 、 刻 度 盘 和 操 纵 杆( 它 使个 人 能 操 作 工 厂 中 的 许 多 机 器 )的 控 制 室 。该 环 境 几 乎 就 是 Visual C++ 中 所 能“ 看见 ” 的 所 有 东 西 。 所 有 其 他 事 情 都 在 其 管 理 下 在 幕 后 运 行 。
产 品 Visual C++ 和 它 的 开 发 环 境 Developer Studio 之 间 的 区 别 几 乎 没 有 意 义 , 因为 后 者 完 全 取 代 了 前 者 。 为 避 免 应 付 两 个 不 同 的 名 字 , 本 书 在 一 般 场 合 下 , 用 术语 Visual C++ 来 既 指 代 整 个 产 品 , 又 指 代 它 的 开 发 环 境 。 微 软 自 己 已 经 接 纳 了 这个 做 法 , 而 以 前 版 本 的 用 户 会 注 意 到 , 原 来 标 为 Developer Studio 的 窗 口 标 题 已经 改 为 Visual C++ 。 然 而 , 在 最 后 一 章 讨 论 实 用 程 序 如 何 同 Developer Studio 程序 结 合 起 来 , 而 成 为 环 境 的 一 部 分 时 , 我 们 将 恢 复 原 来 的 名 字 。
开 始 , 我 们 来 概 括 一 下 Visual C++ 环 境 为 帮 助 程 序 开 发 而 设 计 提 供 的 诸 多 服 务 。
圆 括 号 中 的 章 节 号 指 出 了 本 书 中 详 细 讨 论 这 些 服 务 的 地 方 。
-
对 开 发 进 程 的 不 同 方 面 , 从 类 和 源 文 件 的 列 表 到 编 译
器 消 息 , 都 提 供了 观 察 窗 口 ( 第 1 章 )。
-
访 问 在 线 帮 助 的 扩 展 系 统 的 菜 单 ( 第 1 章 )。
-
创 建 和 维 护 源 文 件 的 文 本 编 辑 器( 第 3 章 ), 设 计 对 话
框 用 的 优 秀 对 话框 编 辑 器 ( 第 5 章 ), 并 创 建 其 他 界 面 组 件 , 如 位 图 、 图 标 、 鼠 标 及 工具 栏 的 图 形 编 辑 器 ( 第 4 章 )。
-
为 程 序 创 建 启 动 器 文 件 的 向 导 在 建 立 新 项 目 的 常 规 任
务 上 提 供 一 个 良好 的 开 端 。 Visual C++ 为 不 同 类 型 的 W indows 程 序 提 供 向 导 , 包 括 带有 可 选 数 据 库 和 Automation 支 持 的 标 准 应 用 程 序 ( 第 2 章 )、 动 态 链接 库 、基 于 对 话 框 的 应 用 程 序(第 5 章 )、使 用 Internet Server API(ISAPI) 的 Web 服 务 器 的 扩 展 程 序 及 ActiveX 控 件 ( 第 9 章 和 第 10 章 )。
-
帮 助 MFC 应 用 程 序 创 建 和 维 护 类 的 帮 手 — — ClassWizard (
第 6 章 )。
-
Gallery 维 护 的 内 置 可 执 行 组 件 给 程 序 增 加 方 便 的 特 征
( 第 7 章 )。
-
优 秀 的 调 试 器 ( 第 11 章 )。
-
通 过 对 菜 单 和 工 具 栏 对 命 令 进 行 合 理 和 方 便 的 访 问 。
你 可 以 定 制
Visual C++ 中 已 有 的 菜 单 或 创 建 新 的 菜 单 ( 第 13 章 )。
- 通 过 宏 和 附 加 的 动 态 链 接 库 来 添 加 自 己 的 环 境 工 具 的
能 力 ( 第 13 章 )。 你 可 以 自 己 开 发 这 些 附 加 项 , 或 从 各 种 各 样 的 供 应 商 那 里 购 买 它们 。
图 1-1 显 示 了 一 个 典 型 的 Visual C++ 主 窗 口 。 开 发 环 境 的 外 观 比 以 前 的 版 本 只 有细 微 的 改 变 , 而 它 的 风 格 和 许 多 命 令 仍 维 持 不 变 。 如 果 你 从 较 早 版 本 的 Visual C++ 或 其 他 微 软 产 品 中 熟 悉 了 Developer Studio 环 境 , 可 以 跳 过 这 一 章 , 而 直 接接 触 新 特 征 , 尤 其 是 修 订 过 的 在 线 帮 助 系 统 。 如 果 你 以 前 从 未 用 过 Visual C++ , 你 会 发 现 , 像 任 何 大 的 W indows 程 序 一 样 , 它 需 要 一 些 时 间 来 习 惯 。 不 要 低 估它 的 深 度 , 只 有 当 你 认 为 已 经 发 现 了 Visual C++ 的 每 件 事 情 时 , 才 会 峰 回 路 转 , 出 现 一 番 新 的 景 色 。 但 是 , 它 的 界 面 是 智 能 化 的 , 而 且 , 而 且 非 常 宽 容 , 它 鼓 励你 去 实 践 , 实 践 总 是 最 好 的 教 师 。
图 1-1 Visual C++ 主窗口的典型视图
本 章 是 一 个 起 点 , 它 介 绍 Visual C++ 的 环 境 外 壳 , 并 描 述 开 发 项 目 时 遇 到 的 界 面和 窗 口 。 我 们 不 急 于 在 本 章 中 讨 论 单 独 的 工 具 和 菜 单 命 令 , 因 为 在 后 面 的 几 章中 ,都 介 绍 了 菜 单 和 工 具 栏 及 它 们 包 含 的 各 种 各 样 的 命 令 。同 时 ,Developer Studio 还 充 当 Visual J++ 和 Visual InterDev 的 主 环 境 , 但 这 里 , 我 们 只 集 中 讨 论 这 个 环境 是 如 何 应 用 到 Visual C++ 和 C/C++ 项 目 上 的 。
工 具 栏 和 菜 单
Visual C++ 带 有 一 个 预 先 定 义 好 的 工 具 栏 集 , 单 击 它 们 便 可 以 访 问 它 们 。 如 果 找不 到 需 要 的 工 具 ,可 以 用 自 己 设 计 的 定 制 工 具 栏 来 增 大 工 具 栏 集 。 每 个 工 具 栏 都由 工 具 栏 的 标 题 栏 上 的 名 字 标 识 :
正 如 下 面 部 分 所 描 述 的 那 样 , 工 具 栏 经 常 被 定 位 在 某 个 位 置 上 , 这 时 标 题 栏 消失 。例 如 ,图 1-1 显 示 了 Standard 、Build 和 Edit 工 具 栏 定 位 在 Visual C++ 主 窗 口的 顶 端 时 的 样 子 。 工 具 栏 的 安 排 由 你 决 定 。 你 可 以 在 屏 幕 四 周 移 动 工 具 栏 , 通 过拖 曳 边 框 来 调 整 它 们 的 矩 形 形 状 , 并 使 任 何 一 套 工 具 可 见 或 隐 藏 。 你 可 能 愿 意 让某 些 工 具 栏 ( 如 Standard 和 Build ) 一 直 都 是 可 见 的 , 至 于 其 他 工 具 栏 , 通 常 只在 你 工 作 在 需 要 它 们 的 窗 口 中 时 , 才 变 得 可 见 。 例 如 , 在 默 认 设 置 中 , Debug 工具 栏 只 在 调 试 过 程 中 才 是 可 见 的 。Colors 和 Graphics 工 具 栏( 将 在 第 4 章 中 讨 论 ) 仅 在 图 形 编 辑 器 中 才 是 可 见 的 , 因 为 这 是 你 需 要 它 们 的 唯 一 地 方 。
图 1-2 在 Customize ( 自 定 义 ) 对 话 框 中 打 开 和 关 闭 工 具 栏
图 1-2 显 示 了 Customize ( 自 定 义 ) 对 话 框 中 包 含 的 工 具 栏 名 称 列 表 , 这 里 你 通过 单 击 复 选 框 来 调 整 工 具 栏 的 可 见 性 是 打 开 或 是 关 闭 。 在 Tools ( 工 具 ) 菜 单 中单 击 Customize ( 自 定 义 ) 命 令 即 可 打 开 这 个 对 话 框 ( 第 13 章 对 Customize ( 自定 义 ) 对 话 框 有 更 多 的 叙 述 )。
当 鼠 标 停 留 在 工 具 栏 按 钮 的 上 面 时 ,按钮凸起 。主 窗 口 的 底 端 的 状 态 栏 显 示 了 对按 钮 的 简 短 描 述 , 并 且 , 如 果 光 标 停 留 时 间 长 一 些 , 就 会 出 现 一 个 小 的 弹 出 式 的“ 工 具 提 示 ” 窗 口 , 它 包 含 了 按 钮 的 名 字 。 如 果 需 要 的 话 , Visual C++ 甚 至 可 以显 示 放 大 的 工 具 栏 :
工 具 提 示 和 放 大 的 选 项 都 是 在 图 1-2 显 示 的 Customize( 自 定 义 ) 对 话 框 中 控 制的 。
Visual C++ 菜 单 栏 是 一 种 特 殊 形 式 的 工 具 栏 。 尽 管 只 有 在 全 屏 模 式 下 才 能 隐 藏 菜
单 栏 , 其 他 情 况 下 , 它 就 像 一 个 普 通 的 工 具 栏 。 当 鼠 标 停 留 在 Visual C++ 的 菜 单栏 上 时 , 菜 单 名 像 工 具 栏 一 样 呈 凸 起 状 。 单 击 菜 单 名 来 拉 下 菜 单 时 , 菜 单 名 看 起来 像 是 凹 进 屏 幕 里 。菜 单 打 开 后 , 把 鼠 标 从 一 个 菜 单 名 滑 动 到 另 一 个 会 拉 下 另 一个 菜 单 。
通 过 在 工 具 栏 或 菜 单 栏 上 不 是 按 钮 或 菜 单 名 的 地 方 单 击 , 并 保 持 鼠 标 被 按 下 ,就可 以 把 它 们 拖 动 到 屏 幕 上 新 的 地 方 。 如 果 工 具 栏 的 标 题 栏 不 可 见 , 工 具 栏 上 的 垂直 分 隔 处 正 是 “ 抓 取 ” 工 具 栏 拖 动 的 好 地 方 。 由 于 停 靠 这 一 特 征 , 在 Visual C++ 中 移 动 工 具 栏 , 有 时 并 不 如 你 所 想 像 的 那 样 简 单 。下 一 部 分 深 入 讨 论 重 新 在 屏 幕上 定 位 窗 口 和 工 具 栏 的 秘 密 。
环 境 窗 口
除 许 多 对 话 框 外 , Visual C++ 显 示 两 种 类 型 的 窗 口 , 即 文 档 窗 口 和 停 靠 窗 口 。 文档 窗 口 是 一 般 的 带 边 框 子 窗 口 ,其 中 包 含 有 源 代 码 文 本 和 图 形 文 档 。W indo w( 窗口 ) 菜 单 中 列 出 了 在 屏 幕 上 以 平 铺 方 式 还 是 以 层 叠 方 式 显 示 文 档 窗 口 的 命 令 。所有 其 他 的 Visual C++ 窗 口 , 包 括 工 具 栏 甚 至 菜 单 栏 , 都 是 停 靠 的 。 开 发 环 境 有 两个 主 要 的 停 靠 窗 口 — — Workspace ( 工 作 空 间 ) 窗 口 和 Outpu t( 输 出 ) 窗 口 , 它们 通 过 View ( 查 看 ) 菜 单 中 的 命 令 变 成 可 见 的 窗 口 。 另 一 个 停 靠 窗 口 Debugger
( 调 试 器 ) 窗 口 在 第 10 章 中 讨 论 , 它 在 调 试 过 程 中 显 示 。 这 一 部 分 首 先 看 看 所
有 停 靠 窗 口 的 一 些 共 同 特 征 , 然 后 单 独 地 讨 论 Workspace ( 工 作 空 间 ) 窗 口 和
Outpu t( 输 出 ) 窗 口 。
停 靠 窗 口 可 以 固 定 在 Visual C++ 用 户 区 的 顶 端 、 底 端 或 侧 面 , 或 者 浮 动 在 屏 幕 上任 何 地 方 。 停 靠 窗 口 , 不 论 是 浮 动 着 的 或 是 固 定 着 的 , 总 是 出 现 在 文 档 窗 口 的 上面 。 这 样 , 就 保 证 了 当 焦 点 从 一 个 窗 口 移 到 另 一 个 时 , 浮 动 的 工 具 栏 一 直 都 是 可见 的 , 但 它 也 意 味 着 , 文 档 窗 口 偶 尔 会 看 起 来 像 消 失 了 似 的 。 这 种 情 况 刚 开 始 时可 能 会 使 人 不 安 , 但 是 , 文 档 窗 口 仍 在 那 儿 。 例 如 , 如 果 你 正 在 文 本 编 辑 器 中 编辑 源 代 码 , 此 时 打 开 一 个 占 据 整 个 Visual C++ 用 户 区 的 停 靠 窗 口 , 源 代 码 文 档 就会 消 失 , 它 隐 藏 在 新 窗 口 之 下 。 如 果 覆 盖 的 窗 口 被 定 位 在 该 位 置 上 , 你 就 无 法 使文 档 窗 口 回 到 上 面 来 。唯 一 的 解 决 方 法 是 要 么 关 了 覆 盖 的 窗 口 , 要 么 把 它 拖 到 不挡 眼 的 地 方 去 。 我 们 将 看 到 如 何 快 速 地 打 开 和 关 闭 停 靠 窗 口 。
拖 动 一 个 停 靠 窗 口 时 会 出 现 一 个 移 动 的 轮 廓 ,它 显 示 了 释 放 鼠 标 左 键 时 窗 口 的 新位 置 。这 些 轮 廓 线 是 灰 色 虚 线 , 直 到 它 与 环 境 用 户 区 的 边 界 或 另 一 个 停 靠 窗 口 的边 界 接 触 时 , 它 才 变 成 细 黑 线 。 这 种 变 化 提 示 你 , 若 放 下 窗 口 , 会 使 它 定 位 在 边界 附 近 的 位 置 。 工 具 栏 在 用 户 区 的 顶 端 或 底 端 时 定 位 为 水 平 位 置 , 而 在 左 右 边 界时 则 定 位 为 垂 直 位 置 。 在 拖 动 工 具 栏 时 , 可 通 过 按 Shift 键 来 改 变 工 具 栏 的 放 置方 向 。
把 窗 口 定 位 在 希 望 的 位 置 和 尺 寸 上 , 有 时 会 花 费 一 些 时 间 。要 使 窗 口 占 据 整 个 用户 区 , 向 上 拉 动 边 界 , 直 到 鼠 标 同 用 户 区 的 上 边 界 接 触 , 然 后 释 放 鼠 标 按 键 。 要把 窗 口 恢 复 到 较 小 尺 寸 , 拖 动 窗 口 , 直 到 光 标 接 触 到 用 户 区 的 左 边 界 。 这 迫 使 窗口 成 为 浮 动 的 , 你 可 以 通 过 其 标 题 栏 来 把 它 拖 动 到 其 他 地 方 。
在 屏 幕 上 移 动 一 个 停 靠 窗 口 时 , 窗 口 看 起 来 像 是 有 主 意 似 的 , 顽 强 地 紧 贴 着Visual C++ 主 窗 口 的 某 一 边 界 , 或 任 何 其 他 它 接 触 到 的 定 位 窗 口 。 有 两 个 办 法 可防 止 这 个 问 题 发 生 。第 一 种 办 法 就 是 在 移 动 窗 口 时 按 住 Ctrl 键 ,来 暂 时 禁 止 它 的停 靠 特 征 。 第 二 种 办 法 只 对 窗 口 有 效 , 对 工 具 栏 无 效 , 那 就 是 禁 止 窗 口 的 停 靠 能力 ,直 到 你 再 次 使 它 生 效 。在 窗 口 内 部 右 击 ,从 上 下 文 相 关 菜 单 中 ,选 择 Docking View ( 停 靠 视 图 ) 命 令 来 关 掉 命 令 的 复 选 标 志 。 W indow ( 窗 口 ) 菜 单 也 提 供 对Docking View ( 停 靠 视 图 ) 命 令 的 访 问 , 如 图 1-3 所 示 。
图 1-3 使用 Docking View ( 停 靠 视 图 ) 命 令 切 换 窗 口 的 停 靠 模 式
若 关 掉 窗 口 的 停 靠 特 征 , 在 下 面 几 个 方 面 影 响 窗 口 :
-
窗 口 就 像 一 个 普 通 的 文 档 窗 口 , 标 题 栏 上 有 最 小 化 、
最 大 化 和 关 闭 窗口 的 按 钮 。
-
从 Window ( 窗 口 ) 菜 单 中 选 择 Cascade( 层 叠 ) 或 Tile( 平
铺 ) 命 令时 , 窗 口 同 其 他 打 开 的 文 档 窗 口 一 起 排 列 位 置 。
-
窗 口 不 能 移 到 Visual C++ 主 窗 口 用 户 区 的 外 面 , 当 它 处
在 停 靠 模 式 下时 是 可 以 的 。
-
输 入 焦 点 移 到 该 窗 口 上 时 , 它 可 以 由 W indow ( 窗 口 )
菜 单 上 的 Close
( 关 闭 ) 命 令 关 闭 。 否 则 , Close ( 关 闭 ) 命 令 不 能 影 响 停 靠 模 式 下 的窗 口 , 即 使 它 拥 有 焦 点 。
窗 口 或 工 具 栏 被 定 位 后 , 凸 起 的 硬 节( 有 时 称 为 把 手 ) 出 现 在 窗 口 的 顶 端 或 左 边界 , 如 图 1-4 所 示 。 双 击 把 手 使 窗 口 变 成 浮 动 的 ; 双 击 浮 动 窗 口 或 工 具 栏 的 标 题栏 , 使 它 回 到 原 来 的 位 置 。也 可 以 通 过 把 手 来 把 窗 口 拖 动 到 另 一 个 固 定 的 或 浮 动的 位 置 。
在 Visual C++ 中 创 建 的 窗 口 排 列 , 将 在 项 目 的 整 个 过 程 中 维 持 , 或 直 到 你 改 变 窗口 排 列 方 式 。 下 一 次 打 开 项 目 时 , 窗 口 像 上 次 离 开 时 的 样 子 排 列 。 然 而 , 在 环 境中 运 行 的 实 用 程 序 的 窗 口 并 不 遵 守 这 些 规 则 。这 些 窗 口 既 不 是 文 档 窗 口 , 也 不 是停 靠 窗 口 , 它 们 的 特 征 是 由 实 用 程 序 决 定 的 , 而 不 是 由 Visual C++ 决 定 。
图 1-4 在 停 靠 时 , 窗 口 、 工 具 栏 和 菜 单 栏 中 出 现 一 个 凸 起 的 把 手
Wo rkspace ( 工 作 空 间 ) 窗 口 和 Ou tpu t( 输 出 ) 窗 口
Visual C++ 在 停 靠 的 Workspace ( 工 作 空 间 ) 和 Outpu t( 输 出 ) 窗 口 中 显 示 项 目的 有 关 信 息 , 如 图 1-1 、 图 1-6 和 图 1-7 所 示 。 在 本 书 中 , 自 始 至 终 , 我 们 都 要遇 到 这 些 重 要 的 窗 口 , 尤 其 是 Workspace ( 工 作 空 间 ) 窗 口 , 因 此 , 花 些 时 间 来讨 论 它 们 如 何 工 作 是 值 得 的 。
要 使 Workspace 或 Outpu t( 输 出 ) 窗 口 可 见 , 在 View ( 查 看 ) 菜 单 中 单 击 它 们的 名 字 即 可 , 如 图 1-5 所 示 ( 这 个 命 令 不 是 一 个 开 关 命 令 , 因 此 , 再 单 击 它 一 次不 会 使 窗 口 消 失 )。 窗 口 也 可 以 通 过 Standard ( 标 准 ) 工 具 栏 上 的 按 钮 来 激 活 , 这 些 按 钮 按 下 后 会 使 窗 口 可 见 或 消 失 。
图 1-5 显示 Workspace ( 工 作 空 间 ) 和 Outpu t( 输 出 ) 窗 口 , 工具按钮在 Standard (标准)工
具 栏 上
除 使 用 工 具 栏 按 钮 外 ,还 可 以 用 下 列 方 法 来 隐 藏 Workspac e( 工 作 空 间 )和 Output
( 输 出 ) 窗 口 :
-
如 果 窗 口 是 浮 动 的 , 单 击 窗 口 的 标 题 栏 上 的 Close ( 关
闭 ) 按 钮 。
-
如 果 窗 口 是 固 定 的 , 单 击 窗 口 把 手 上 面 或 右 面 的 X 形
按 钮 ( 图 1-4 )。
-
在 窗 口 内 任 何 地 方 右 击 , 打 开 上 下 文 相 关 菜 单 , 选 择
H ide( 隐 藏 ) 或Close( 关 闭 ) 命 令 。 菜 单 上 出 现 哪 个 命 令 取 决 于 窗 口 的 停 靠 模 式 是 打开 的 还 是 关 闭 的 , 但 两 个 命 令 有 同 样 的 效 果 。
-
如 果 窗 口 的 停 靠 特 征 被 禁 止 , 单 击 窗 口 把 焦 点 移 到 它
上 面 , 然 后 从
W indow ( 窗 口 ) 菜 单 中 选 择 Close ( 关 闭 ) 命 令 。
Workspace ( 工 作 空 间 ) 窗 口 显 示 了 项 目 各 个 方 面 的 信 息 。 在 窗 口 底 端 选 择 相 应的 选 项 卡 来 显 示 项 目 的 类 、 资 源 、 数 据 源 和 文 件 的 列 表 。 在 窗 口 中 单 击 小 的 加 号
( + ) 或 减 号( -) 来 展 开 或 折 叠 列 表 。 例 如 , 展 开 类 的 列 表 会 显 示 出 成 员 函 数 的名 字 ,如 图 1-6 中 的 第 一 屏 所 示 。双 击 列 表 开 头 靠 近 文 件 夹 或 书 本 形 图 标 的 文 字 , 与 单 击 表 头 的 加 号 或 减 号 有 同 样 的 效 果 。
图 1-6 Workspace ( 工 作 空 间 ) 窗 口 的 四 个 窗 格
Workspace ( 工 作 空 间 ) 窗 口 可 以 显 示 多 达 四 个 窗 格 的 信 息 , 如 下 所 述 :
-
C lassView : 列 出 项 目 中 的 类 和 成 员 函 数 。 要 在
Visual C++ 文 本 编 辑 器中 打 开 类 的 源 文 件 , 双 击 列 表 中 的 要 打 开 的 类 或 函 数 。
-
ResourceView : 列 出 项 目 的 资 源 数 据 , 如 对 话 框 和 位
图 。同 ClassView 中 一 样 , 双 击 ResourceView 列 表 中 的 数 据 项 会 打 开 合 适 的 编 辑 器 并 加载 资 源 。
-
FileView : 列 出 项 目 的 源 文 件 。 把 源 文 件 复 制 到 项
目 夹 中 , 不 会 自 动把 文 件 添 加 到 FileView 窗 格 的 列 表 中 。 你 必 须 用 Project( 项 目 ) 菜 单中 的 Add To Project( 添 加 到 项 目 ) 命 令 明 确 地 把 新 文 件 添 加 到 项 目中 。
-
Data View : 显 示 数 据 库 项 目 的 数 据 来 源 信 息 。 Data
View ( 数 据 视 图 ) 选 项 卡 只 出 现 在 Visual C++ 的 企 业 版 的 数 据 库 项 目 中 , 企 业 版 遵 循 开放 式 数 据 库 互 连 标 准 ( ODBC ) 来 同 数 据 源 相 连 。
在 Workspace ( 工 作 空 间 ) 窗 口 中 的 某 项 上 右 击 , 会 显 示 一 个 含 有 常 用 命 令 的 上下 文 相 关 菜 单 。 菜 单 中 的 命 令 取 决 于 单 击 在 哪 一 项 上 。 例 如 , 在 FileView 窗 格中 的 一 个 源 文 件 上 , 右 击 , 会 显 示 一 个 快 速 打 开 或 编 译 文 件 的 上 下 文 相 关 菜 单 。你 也 可 以 开 关 单 个 Workspace ( 工 作 空 间 ) 窗 格 。 在 Workspace ( 工 作 空 间 ) 窗口 的 底 端 的 选 项 卡 上 右 击 来 显 示 上 下 文 相 关 菜 单 ,然 后 从 菜 单 中 选 择 有 关 命 令 来
使 窗 格 可 见 或 消 失 。
Outpu t( 输 出 ) 窗 口 ( 如 图 1-7 所 示 ) 有 四 个 选 项 卡 : Build ( 建 立 )、 Debug ( 调试 )、Find In Files 1( 在 文 件 1 中 查 找 )和 Find In Files 2( 在 文 件 2 中 查 找 )。Build
( 建 立 ) 选 项 卡 显 示 编 译 器 、 链 接 器 和 其 他 工 具 的 状 态 消 息 。 Debug ( 调 试 ) 选项 卡 用 于 通 知 来 自 调 试 器 的 提 示 ,这 些 提 示 对 诸 如 未 处 理 的 异 常 异 常 和 内 存 异 常之 类 的 情 况 提 出 警 告 。 应 用 程 序 通 过 OutputDebugString API 函 数 或 afxDump 类库 产 生 的 消 息 , 也 显 示 在 Debug ( 调 试 ) 选 项 卡 中 。
图 1-7 Outpu t(输出)窗口
在 Outpu t( 输 出 ) 窗 口 中 剩 下 的 两 个 选 项 卡 , 显 示 从 Edi t( 编 辑 ) 菜 单 中 选 中 的Find In File s( 在 文 件 中 查 找 ) 命 令 的 执 行 结 果( 这 个 十 分 有 用 的 特 征 与 UNIX 的grep 命 令 相 似 , 它 将 在 第 3 章 中 详 细 讨 论 )。 默 认 情 况 下 , Find In Files 搜 索 结 果
显 示 在 Outpu t( 输 出 ) 窗 口 的 Find In Files 1 选项卡中,但 Find In Files 对 话 框 中的 一 个 复 选 项 , 允 许 你 把 结 果 转 移 到 Find In Files 2 选 项 卡 中 。Outpu t(输出)窗口 中 还 可 以 包 含 其 他 的 选 项 卡 。 在 第 13 章 中 , 我 们 将 看 到 如 何 给 Visual C++ 添加 能 在 Outpu t( 输 出 ) 窗 口 中 自 己 的 选 项 卡 里 显 示 消 息 的 定 制 工 具 。
在 线 帮 助
Visual C++ 提 供 了 三 个 不 同 的 在 线 帮 助 来 源 :
-
由 WinHlp32 查 看 器 显 示 的 标 准 HLP 文 件 。
-
对 话 框 中 的 弹 出 式 帮 助 信 息 。
-
M icrosoft Developer Network Library ,即 MSDN 。
标 准 的 HLP 文 件 内 容 包 括 环 境 的 命 令 和 窗 口 ,当 Hel p( 帮 助 )菜 单 的 Use Extension Help ( 使 用 扩 展 命 令 ) 命 令 被 选 中 , 或 Visual C++ 不 能 为 帮 助 主 题 确 定 明 确 的 上下 文 时 , 按 F1 键 就 会 显 示 这 些 帮 助 文 件 。 例 如 , 考 虑 文 本 编 辑 器 中 打 开 的 一 个典 型 的 源 文 件 文 档 中 的 这 一 行 :
DECLARE_MESSAGE_MAP() //MFC message map macro
在 这 种 情 况 下 , 按 F1 键 的 效 果 取 决 于 文 本 编 辑 器 中 闪 烁 光 标 所 在 的 位 置 。 如 果光 标 在 宏 名 的 内 部 或 开 始 , 而 扩 展 帮 助 关 闭 了 , 按 F1 键 会 打 开 M S D N 库 窗 口 , 并 显 示 DECLARE_MESSAGE_MAP 宏 的 有 关 信 息 。如 果 光 标 是 停 留 在 一 个 空 行上 , 这 里 没 有 明 确 的 在 线 帮 助 的 上 下 文 。 这 种 情 况 下 , 按 F1 键 会 提 供 文 本 编 辑器 窗 口 本 身 的 有 关 信 息 , 它 们 显 示 在 W inHlp32 查 看 器 中 :
在 线 帮 助 的 第 二 个 来 源 是 弹 出 式 消 息 , 在 这 个 环 境 中 的 许 多 对 话 框 中 都 可 以 使用 。 选 项 卡 和 偶 尔 的 提 示 会 尽 量 解 释 对 话 框 中 的 编 辑 框 和 按 钮 的 用 途 ,但 当 标 签说 明 不 充 分 时 , 总 可 以 通 过 下 列 几 种 方 法 之 一 来 寻 求 特 殊 控 件 的 更 多 解 释 :
-
把 焦 点 移 到 该 控 件 上 , 并 按 F1 键 。 对 于 复 选 框 或 单 选
按 钮 , 通 过 单 击来 给 它 焦 点 , 可 能 会 打 开 或 关 闭 一 个 开 关 选 项 。 如 果 你 不 希 望 这 种 结果 , 当 你 阅 读 完 帮 助 信 息 后 , 要 记 得 把 开 关 恢 复 到 原 来 的 设 置 。
-
在 该 控 件 上 右 击 , 来 打 开 What ’ s This ?( 这 是 什 么 ) 弹
出 式 按 钮 。 如 果
该 控 件 是 一 个 编 辑 框 , 右 击 该 控 件 的 标 签 文 本 , 比 右 击 编 辑 框 本 身 要更 好 一 些 。 单 击 What ’ s This ?( 这 是 什 么 ) 按 钮 , 将 显 示 该 控 件 的 帮 助文 本 。
- 单 击 对 话 框 右 上 角 的 问 号 按 钮 , 然 后 单 击 要 了 解 的 控
件 。
这 三 种 方 法 效 果 完 全 一 样 : 运 行 W inHlp32 , 来 显 示 一 个 如 图 1-8 所 示 的 简 明 的弹 出 式 消 息 。 单 击 鼠 标 或 按 任 意 键 时 , 这 些 消 息 就 消 失 了 。
图 1-8 在典型的 Developer Studio 对 话 框 获 得 帮 助
在 线 帮 助 的 第 三 个 来 源 是 你 在 Visual C++ 中 工 作 时 最 常 用 的 一 个 。M S D N 通 常 是合 乎 逻 辑 的 ,而 且 易 于 使 用 ,但 它 也 十 分 庞 大 。正 如 下 一 部 分 我 们 将 看 到 的 一 样 , 要 充 分 利 用 MSDN 库 还 需 要 进 行 一 些 练 习 。
MSDN 库
一 旦 通 过 预 订 获 得 MSDN 库 后 , 它 就 可 以 为 包 括 Visual C++ 在 内 的 整 套 Visual Studio 开 发 环 境 工 具 提 供 在 线 帮 助 。由 于 所 有 的 工 具 都 可 以 共 享 它 ,M S D N 作 为一 个 应 用 程 序 单 独 运 行 , 而 没 有 同 任 何 单 个 开 发 环 境 结 合 在 一 起 。 要 从 Visual C++ 中 访 问 M S D N , Help ( 帮 助 ) 菜 单 中 的 Use Extension Help ( 使 用 扩 展 帮 助 ) 命 令 必 须 没 有 被 选 中 。
从 Visual C++ 的 Hel p( 帮 助 )菜 单 中 选 择 Content s( 目 录 )、Searc h( 搜 索 )或 Index
( 索 引 ) 命 令 , 会 使 环 境 通 过 执 行 Windows\HH.exe 程 序 来 运 行 MSDN , 该 程 序从 位 于 MSDN98\98VS\1033 文 件 夹 中 的 文 件 MSDNVS98.col 中 加 载 M S D N 目 录列 表 ( 包 含 该 文 件 的 文 件 夹 名 反 映 了 系 统 的 定 位 设 置 , 1033 是 美 国 英 语 的 语 言代 码 )。
M S D N 库 提 供 的 庞 大 信 息 集 几 乎 涉 及 到 微 软 编 程 工 具 和 W in32 编 程 的 每 个 方面 。 它 包 含 了 成 千 上 万 的 主 题 , 这 些 主 题 讨 论 了 从 Visual C++ 到 Visual J++ 、 从MFC 到 ActiveX 和 从 abs 函 数 到 z 排 列 ( z-ordering ) 的 每 件 事 情 。 M S D N 也 包括 了 几 本 微 软 出 版 的 重 要 书 籍 的 全 部 文 字 , 例 如 Bruce McKinney 的 Hardcore Visual Basic 和 Kraig Brockschmidt 的 Inside Ole 第 二 版 。 你 也 可 以 从 中 找 到Knowledge Base ( 知 识 库 ) 主 题 、 M icrosoft Systems Journal 的 最 新 论 点 、 应 用 程序 和 设 备 驱 动 程 序 的 开 发 工 具 包 的 全 部 文 档 、协 议 文 件 、 范 例 源 代 码 及 其 他 许 多东 西 。 这 一 版 的 界 面 并 未 经 过 良 好 的 构 思 , 但 M S D N 中 所 包 括 的 信 息 的 完 整 性
确 实 让 人 吃 惊 。
M S D N 帮 助 系 统 把 文 本 存 在 一 系 列 的“ 伙 伴 ”文 件 中 ,这 些 文 件 通 过 扩 展 名 C H M 来 标 识 ; 该 扩 展 名 指 出 这 些 文 件 是 以 编 译 过 的 H T M L 格 式 写 的 。 CHM 文 件 就 像单 册 的 M S D N 百 科 全 书 ,每 一 个 都 包 含 了 讨 论 一 个 特 殊 主 题 的 论 文 ,如 ActiveX 或 Win32 API 参 考 大 全 。每 个 文 件 都 与 一 个 独 立 的 索 引 文 件 配 对 ,索 引 文 件 有 同样 的 文 件 名 和 CHI 扩 展 名 。 在 安 装 M S D N 的 过 程 中 , 安 装 程 序 把 所 有 的 CHI 索引 文 件 都 复 制 到 硬 盘 上 ,但 只 从 CD-ROM 中 复 制 你 指 定 的 那 些 C H M 文 件 。 C H M 文 件 占 据 大 量 的 磁 盘 空 间 , 因 此 , 你 可 能 会 更 愿 意 只 安 装 那 些 你 最 常 用 的 帮 助 主题 。 在 执 行 过 程 中 , M S D N 访 问 所 有 的 C H M 文 件 , 不 管 它 是 在 硬 盘 上 , 还 是 在光 盘 上 。 如 果 程 序 在 硬 盘 上 找 不 到 需 要 的 C H M 文 件 , 它 会 提 示 用 光 盘 来 代 替 。哪 些 M S D N 主 题 应 该 安 装 到 系 统 中 , 取 决 于 你 估 计 使 用 M S D N 的 频 繁 程 度 、 哪些 主 题 你 最 感 兴 趣 , 以 及 你 是 否 愿 意 使 用 光 盘 。
第 一 次 访 问 MSDN 库 来 搜 索 一 篇 文 章 时 ,程 序 创 建 名 为 MSDNVS98.chw 的 关 键字 文 件 ,该 文 件 中 包 含 了 所 有 文 章 中 使 用 的 关 键 字 列 表 , 及 指 向 它 们 在 文 本 中 的位 置 的 指 针 。 以 这 种 方 法 编 辑 关 键 字 , 会 加 速 特 定 的 词 和 短 语 的 搜 索 过 程 , 一 会儿 , 我 们 就 可 以 看 到 这 一 点 。 创 建 关 键 字 文 件 是 一 次 性 , 只 需 要 几 分 钟 , 在 此 过程 中 出 现 动 画 消 息 , 会 告 诉 你 正 在 做 什 么 :
该 过 程 要 求 系 统 T E M P 文 件 夹 下 有 许 多 兆 可 用 的 磁 盘 空 间 。如 果 环 境 变 量 T E M P 当 前 指 向 一 个 容 量 不 够 的 RAM , 在 MSDN 中 进 行 首 次 搜 索 之 前 , 需 要 在AutoExec.bat 文 件 中 重 新 设 置 该 变 量 , 并 重 新 启 动 计 算 机 。 M S D N 创 建 了 关 键 字文 件 之 后 , 可 以 恢 复 原 来 的 T E M P 设 置 。
图 1-9 展 示 了 典 型 的 M S D N 文 章 , 以 两 窗 格 显 示 。 这 两 个 窗 格 被 设 计 成 可 以 共同 工 作 , 左 边 的 允 许 为 你 希 望 阅 读 的 文 章 输 入 标 准 , 而 右 边 的 则 显 示 找 到 的 文章 。
图 1-9 通过 MSDN Library 应用程序来访问在线帮助
在 右 窗 格 中 , 每 次 都 出 现 主 题 , 它 通 过 超 文 本 链 接 web 连 接 到 其 他 的 相 关 主 题 。
超 文 本 链 接 也 称 超 级 链 接 , 它 是 文 本 中 一 些 特 殊 的 词 和 短 语 。 链 接 带 有 下 划 线 , 并 以 突 出 的 颜 色 显 示 , 这 使 得 它 们 能 很 快 被 识 别 。 当 光 标 移 动 到 MSDN 库 窗 口中 的 超 文 本 链 接 上 时 ,光 标 变 成 手 的 形 状( 图 1-10 )。在 链 接 上 单 击 ,会 从 M S D N 窗 口 中 清 除 掉 当 前 主 题 , 而 代 之 以 超 文 本 链 接 所 指 向 的 新 主 题 。这 个 效 果 很 像 在Internet 上 浏 览 Web 网 页 。
图 1-10 单 击 一 个 超 文 本 链 接 可 以 从 一 个 M S D N 文 章 跳 到 另 一 个
M S D N 窗 口 右 半 部 分 的 界 面 是 非 常 友 好 的 ,如 果 需 要 阅 读 帮 助 文 本 的 话 ,只 要 上下 滚 动 窗 口 即 可 ,此 外 ,还 可 单 击 超 文 本 链 接 ,来 查 看 感 兴 趣 的 主 题 。在 窗 口 中 ,
- 次 只 显 示 一 个 主 题 , 因 此 , 窗 口 总 是 保 持 干 净 整 洁 。
为 了 观 察 更 多 的 区 域 , 你可 以 通 过 单 击 H ide( 隐 藏 ) 工 具 按 钮 来 关 掉 窗 口 左 边 的 一 栏 , 这 样 , 整 个 窗 口会 由 于 保 持 固 定 的 大 小 而 收 缩 。 你 会 发 现 , 通 过 拖 动 左 边 或 右 边 的 垂 直 分 隔 条 , 更 容 易 关 掉 或 展 开 左 边 的 一 栏 , 这 样 也 维 持 了 MSDN 窗 口 的 整 体 大 小 。
窗 口 左 边 的 一 栏 中 有 四 个 选 项 卡 : Contents ( 目 录 )、 Index ( 索 引 )、 Search ( 搜索 ) 和 Favorites ( 收 藏 )。 每 个 选 项 卡 提 供 一 种 不 同 的 在 线 帮 助 浏 览 方 式 。
Contents ( 目 录 ) 选 项 卡
M S D N 的 主 题 组 依 照 标 题 和 副 标 题 的 排 列 方 式 形 成 一 个 目 录 表 。它 就 像 一 本 书 的目 录 表 一 样 , 仅 仅 是 交 互 式 的 。 开 始 , 可 搜 索 一 个 大 概 的 主 题 , 然 后 逐 层 打 开 越来 越 明 确 的 信 息 路 径 , 来 寻 找 你 感 兴 趣 的 主 题 。 当 你 头 脑 中 有 一 个 大 概 的 主 题 , 如 调 试 器 或 用 OpenGL 编 程 ,而 你 又 想 要 看 一 看 这 个 主 题 有 哪 些 文 档 时 , 目 录 表是 非 常 有 用 的 。
从 Visual C++ 的 Help ( 帮 助 ) 菜 单 中 选 择 Contents ( 目 录 ) 命 令 , 会 打 开 M S D N 窗 口 , 并 显 示 目 录 列 表 。 展 开 列 表 , 直 到 找 到 要 搜 索 的 标 题 , 这 可 以 通 过 双 击 标题 ( 通 过 书 形 图 标 来 识 别 ), 或 单 击 小 的 加 号 ( + ) 按 钮 来 完 成 , 如 图 1-9 所 示 。目 录 列 表 中 的 文 章 标 题 位 于 一 连 串 分 层 的 末 端 ,每 个 标 题 通 过 一 张 折 起 一 个 角 的
纸 形 图 标 来 区 别 。 双 击 列 表 中 的 标 题 , 会 在 MSDN 窗 口 的 右 边 一 栏 中 打 开 该 文章 。
默 认 情 况 下 , 目 录 列 表 概 括 了 MSDN 的 全 部 文 章 。 你 可 以 通 过 把 目 录 表 的 一 个分 支 定 义 为 一 个 信 息 子 集 , 来 缩 短 显 示 的 目 录 。子 集 允 许 你 集 中 一 些 特 殊 类 别 的主 题 。 例 如 , 下 面 是 如 何 创 建 一 个 只 属 于 MFC 参 考 的 文 章 子 集 :
-
从 MSDN 的 Vie w( 查 看 )菜 单 中 选 择 Define Subse t( 定 义 子
集 )命 令 。
-
在 Define Subse t( 定 义 子 集 ) 对 话 框 中 , 通 过 双 击 名 为
MSDN Library Visual Studio 6.0 的 标 题 来 展 开 目 录 列 表 ,然 后 ,同 样 ,展 开 Visual C++ Documentation ( Visual C++ 文 档 ) 和 Reference ( 参 考 ) 副 标 题 。 选 择名 为 M icrosoft Foundation Class Library and Template s( M icrosoft 基 础类 库 和 模 板 ) 的 副 标 题 , 并 单 击 Add ( 添 加 ) 按 钮 来 创 建 子 集 。
-
在 Define Subset( 定 义 子 集 ) 对 话 框 的 底 部 的 编 辑 框 中
键 入 新 子 集 的名 字 , 然 后 单 击 Save ( 保 存 ) 和 Close ( 关 闭 ) 按 钮 。
使 用 在 线 帮 助 时 , 要 在 各 个 子 集 间 切 换 , 只 需 从 名 为 Active Subset ( 有 效 子 集 ) 的 下 拉 列 表 中 选 择 一 个 子 集 即 可 :
Index ( 索 引 ) 选 项 卡
搜 索 在 线 帮 助 时 , 通 常 首 先 要 求 助 于 Index ( 索 引 ) 选 项 卡 , 尤 其 当 你 对 要 寻 找的 主 题 相 当 清 楚 时 。 Index ( 索 引 ) 选 项 卡 显 示 了 整 套 M S D N 文 件 的 全 面 索 引 , 就 像 一 本 书 的 索 引 一 样 。要 找 到 一 个 索 引 条 目 ,在 对 话 框 顶 部 的 编 辑 框 中 键 入 关键 字 即 可 。在 你 键 入 关 键 字 的 时 候 ,列 表 框 中 的 索 引 自 动 滚 动 到 该 关 键 字 所 在 的位 置 。 例 如 , M S D N 索 引 包 含 条 目 “ exception handling( 异 常 处 理 )”、“ handling exception s( 处 理 异 常 )” 和 “ C++ exception handling ( C++ 异 常 处 理 )”。 因 此 , 输 入 这 些 词 条 中 的 任 意 一 个 , 都 可 以 找 到 有 关“ 异 常 处 理 ” 的 主 题 。 找 到 所 要 的
索 引 条 目 后 , 双 击 它 。 如 果 该 条 目 仅 对 应 一 篇 文 章 , M S D N 会 立 刻 显 示 它 ; 否 则会 显 示 Topic Found( 找 到 的 主 题 ) 对 话 框 , 其 中 列 出 了 该 条 目 指 向 的 所 有 文 章 , 如 图 1-11 所 示 。 通 过 双 击 列 表 中 的 标 题 , 或 选 中 该 标 题 , 并 单 击 D ispla y( 显 示 ) 按 钮 , 均 可 在 对 话 框 中 打 开 一 篇 文 章 。
图 1-11 提供 MSDN 文章全面索引的 Index ( 索 引 ) 选 项 卡
Search ( 搜 索 ) 选 项 卡
M S D N 帮 助 文 件 集 不 仅 仅 是 被 动 的 , 它 还 包 含 一 个 搜 索 引 擎 , 该 引 擎 扫 描MSDNVS98.chw 关 键 字 文 件 , 来 确 定 哪 些 主 题 文 件 包 含 了 指 定 的 词 或 短 语 , 这个 过 程 称 为 全 文 本 搜 索 。 全 文 本 搜 索 从 M S D N 的 Search ( 搜 索 ) 选 项 卡 中 启 动
( 图 1-12 ), 它 允 许 你 寻 找 包 含 指 定 词 或 短 语 的 主 题 。 M S D N 搜 索 引 擎 是 非 常 优秀 的 , 它 能 理 解 词 的 派 生 、 通 配 符 、 布 尔 逻 辑 组 合 及 NEAR 运 算 符 。 尽 管 要 有效 地 使 用 这 些 特 征 , 要 求 认 真 地 考 虑 和 进 行 计 划 , 它 们 允 许 你 精 选 搜 索 参 数 , 来增 加 只 寻 找 你 最 感 兴 趣 的 那 些 主 题 的 机 会 。
图 1-12 利 用 Search (搜索)选项卡可以搜索包含特定词或短语的主题
讨 论 过 Searc h( 搜 索 ) 选 项 卡 中 可 用 的 各 种 各 样 的 选 项 之 后 , 我 们 将 集 中 讨 论 如何 用 通 配 符 和 运 算 符 来 精 炼 搜 索 内 容 。
在 选 项 卡 的 顶 部 键 入 要 搜 索 的 词 或 短 语 ,用 双 引 号 把 短 语 括 起 来 , 以 区 别 于 单 个词 ( 单 引 号 会 被 忽 略 )。 例 如 , 搜 索 图 1-12 所 示 的 词 , 会 找 到 那 些 只 包 含 短 语“ exception handling ” 的 主 题 。 键 入 同 样 的 单 词 , 而 不 带 双 引 号 , 就 表 示 你 想 搜索 包 含 单 词 “ exception ” 和 “ handling ” 的 主 题 , 它 们 不 一 定 要 作 为 一 个 短 语 同时 出 现 。 不 能 搜 索 引 号 。
利 用 Searc h( 搜 索 ) 选 项 卡 中 的 三 个 复 选 项 , 你 可 以 进 一 步 指 定 如 何 和 在 哪 里 搜索 。 Search Previous Results ( 搜 索 以 前 的 结 果 ) 复 选 项 , 可 将 搜 索 过 程 限 制 在 已经 出 现 在 Search ( 搜 索 ) 选 项 卡 中 的 那 些 主 题 范 围 内 。 打 开 M atch Similar Words
( 匹 配 类 似 的 词 ) 复 选 项 , 会 让 MSDN 接 受 在 文 本 框 中 键 入 词 的 合 乎 文 法 的 派生 词 。 派 生 词 包 括 通 常 的 后 缀 , 如 s、 ed 和 ing, 例 如 , 它 迫 使 MSDN 认 为 edits 和 edited 同 关 键 字 edit 是 相 匹 配 的 。 这 样 来 放 宽 搜 索 标 准 , 当 然 会 找 到 更 多 的 主题 。 Match Similar Words 选 项 对 编 辑 框 中 所 有 的 搜 索 词 都 适 用 , 打 开 这 个 选 项时 , 搜 索 短 语 handle exception , 会 找 到 包 含 相 近 的 派 生 词 , 如 handled exceptions 的 主 题 。MSDN 甚 至 能 识 别 那 些 不 包 含 整 个 关 键 字 的 派 生 词 , 例 如 ,搜 索 关 键 字handling 时 , 会 找 到 handler 和 handled 。
打 开 Search Titles Only ( 只 搜 索 主 题 ) 复 选 项 , 会 极 大 地 限 制 搜 索 范 围 , 因 为 它使 M S D N 只 扫 描 文 章 标 题 , 不 扫 描 文 章 中 的 正 文 。 这 样 , 打 开 该 选 项 时 , 搜 索短 语 exception handling, 会 找 到 如 “ Exception Handling Topics(SEH )” 和 “ Type- Safe Exception Handling ” 之 类 的 标 题 , 但 不 能 找 到 其 他 的 相 关 主 题 , 例 如“ Compiler Warning C4530 ”, 尽 管 后 者 在 文 中 提 到 了 异 常 处 理 。
搜 索 完 成 后 ,MSDN 列 出 所 有 提 到 过 给 定 搜 索 字 符 串 的 文 章 的 标 题 ,同 时 在 列 表的 右 上 角 显 示 找 到 的 文 章 数 目 。列 表 是 按 搜 索 字 符 串 在 主 题 文 档 中 的 出 现 次 数 递减 的 次 序 排 列 的 。 要 想 按 标 题 或 文 章 位 置 排 列 , 单 击 相 应 列 表 栏 顶 部 的 按 钮 即可 。 双 击 Search( 搜 索 ) 选 项 卡 中 的 列 表 条 目 , 会 显 示 该 文 章 , 文 中 的 匹 配 字 符串 以 高 亮 显 示 , 这 使 你 可 以 很 快 地 找 到 字 符 串 的 出 现 位 置 。文 本 中 经 常 重 复 出 现的 高 亮 字 符 串 看 起 来 有 点 分 散 注 意 力 ,它 使 文 章 外 表 就 像 一 篇 笔 记 。要 从 显 示 中
去 掉 高 亮 ,从 Vie w( 查 看 )菜 单 中 执 行 H ighlight(s 高 亮 )命 令 两 次 ,或 单 击 Previous
( 前 一 个 ) 和 Nex t( 下 一 个 ) 工 具 按 钮 , 来 临 时 转 到 另 一 篇 文 章 , 再 返 回 来 。你 也 可 以 用 Edit ( 编 辑 ) 菜 单 中 的 Find In This Topic ( 在 此 主 题 中 查 找 ) 命 令 在显 示 的 文 章 中 查 找 文 本 。
下 面 是 在 Search ( 搜 索 ) 选 项 卡 中 设 计 搜 索 参 数 的 一 些 基 本 的 规 则 和 告 诫 :
-
搜 索 过 程 不 区 分 大 小 写 , 因 此 用 输 入 搜 索 短 语 时 , 用
大 写 或 小 写 都 可以 。
-
默 认 情 况 下 , M S D N 只 能 查 找 整 个 单 词 。 例 如 , 搜 索
key 不 会 找 到
keyboard 。 通 配 符 可 以 克 制 这 种 默 认 动 作 , 就 像 前 面 解 释 的 那 样 。
- 可 以 搜 索 字 母 和 数 字 的 任 意 组 合 , 包 括 单 个 字 符 ( a
, b , c , 1 , 2 , 3 等 ), 但 不 包 括 简 单 的 单 词 , 如 an , and , as , at, be , bu t, by , do , for, from , have, he , in , it, near, no t, of, on , or, she, that, the ,
there , these , they , this , to , w e , when , which, w ith 和 you 。 M S D N 在 匹 配 文 本 时 会 忽 略 这 些 词 , 因 此 , 搜 索 handle exceptions 时 , 也 会找 到 包 含 短 语“ handle the exception ”或“ handle an exception ” 的 主 题 。
- MSDN 允 许 搜 索 字 符 串 中 有 省 略 号 ,但 它 忽 略 其 他 标 点
符 号 ,如 句 号 、逗 号 、 分 号 、 冒 号 及 连 字 号 。 这 使 搜 索 字 符 串 时 可 以 不 管 上 下 文 , 但它 也 提 供 了 出 现 错 误 匹 配 的 机 会 。 例 如 , 搜 索 短 语 exception handling 时 , 可 能 会 找 到 包 含 下 面 文 本 的 毫 不 相 干 的 主 题 : M essages are an exception. Handling a message...
通 配 符 和 运 算 符
搜 索 字 符 串 可 以 用 标 准 的 问 号 ( ? ) 和 星 号 ( * ) 通 配 符 来 组 成 一 个 一 般 的 表 达式 , 这 些 通 配 符 可 以 代 替 不 在 双 引 号 之 内 的 字 符 。问 号 通 配 符 在 表 达 式 中 代 表 单个 字 符 , 因 此 , 搜 索 字 符 串 80?86 时 , 可 以 找 到“ 80286 ”、“ 80386 ”和 “ 80486 ”
( 但 没 有“ 8086 ”)。 星 号 通 配 符 可 以 代 表 任 意 次 序 的 零 个 到 多 个 字 符 。 例 如 , 搜索 *wnd* 可 以 找 到 如 “ wnd ”、“ CWnd ”、“ H W N D ” 和 “ wndproc ” 之 类 的 文 本 。星 号 通 配 符 使 M S D N 可 以 找 到 包 含 有 共 同 的 词 根 的 所 有 单 词 。 例 如 , 查 找 诸 如“ keyboard ”、“ keystroke” 和 “ keypress ” 之 类 的 单 词 时 , 可 以 键 入 key* 来 代 替key ,作 为 搜 索 字 符 串 。自 然 ,这 种 方 法 可 能 会 发 现 诸 如“ keyword ”和“ key_type ” 之 类 的 不 相 干 的 搜 索 结 果 。 运 算 符 可 以 进 一 步 提 炼 搜 索 标 准 ,来 减 少 这 种 不 希 望发 生 的 结 果 。
M S D N 能 识 别 布 尔 运 算 符 AND 、 O R 、 N O T 及 近 程 运 算 符 NEAR 。 描 述 这 些 运算 符 作 用 的 最 好 办 法 是 通 过 表 1-1 中 例 子 来 说 明 。 NEAR 运 算 符 认 为 , 当 字 符 串之 间 相 隔 不 超 过 八 个 可 标 识 单 词 时 , 字 符 串 是 “ 近 程 的 ”。 M S D N 没 有 为 近 程 的确 定 提 供 另 外 的 标 准 。
表 1-1 在 M S D N 的 Search 选 项 卡 中 字 符 串 运 算 符 的 效 果
运 算 符 例 子 结 果
AND debug AND window 搜 索 文 中 含 有 debug 和
w indow 的 主 题 , 但 只 含 有 一个 的 主 题 不 包 括 在 内
O R mfc OR “ foundation library ”
搜 索 含 有 该 字 符 串 中 的 任 何一 个 或 两 个 的 主 题
NOT ellipse NOT cdc 搜 索 仅 含 有 第 一 个 给 定 字 符
串 ,而 不 含 有 第 二 个 字 符 串 的主 题 。左 边 的 例 子 指 明 了 那 些既 包 含 有 ellipse 又 包 含 有 cdc 的 主 题 应 该 被 跳 过 ,这 样 就 忽略 了 关 于 CDC::Ellipse 函 数 的主 题
续 表
NEAR handl* NEAR exception 搜 索 文 中 给 定 字 符 串 相 隔 不 超
过 八 个 单 词 的 主 题
要 用 运 算 符 连 接 两 个 单 词 , 在 单 词 之 间 用 空 格 分 开 , 并 键 入 运 算 符 , 如 表 1-1 所示 ; 字 母 的 大 小 写 无 关 紧 要 。 你 也 可 以 单 击 靠 近 组 合 框 的 箭 头 按 钮 ( ◗ ), 来 从小 的 弹 出 式 菜 单 中 选 择 要 用 的 运 算 符 。
运 算 符 没 有 确 定 的 优 先 权 ,M S D N 按 从 左 到 右 的 次 序 求 表 达 式 的 值 。如 果 要 用 运算 符 来 明 确 地 组 合 字 符 串 , 可 以 使 用 圆 括 号 。 M S D N 忽 略 双 引 号 内 部 的 圆 括 号 , 因 此 ,不 能 搜 索 带 圆 括 号 的 注 释 。在 没 有 其 他 运 算 符 、圆 括 号 或 双 引 号 的 情 况 下 , Search ( 搜 索 ) 选 项 卡 把 搜 索 字 符 串 中 的 空 格 视 为 A N D 运 算 符 。 因 此 在 Search
( 搜 索 ) 选 项 卡 中 输 入 下 列 搜 索 字 符 串 中 的 任 意 一 个 , 都 会 产 生 同 样 的 效 果 :
debug AND window AND breakpoint (debug AND window) breakpoint debug window AND breakpoint debug window breakpoint
早 先 版 本 的 InfoViewer 帮 助 系 统 允 许 使 用 C 语 言 中 布 尔 运 算 符 的 等 同 符 号 : 用符 号 & 、 竖 线 ( |) 和 惊 叹 号( !) 来 分 别 代 替 A N D 、 O R 和 N O T 。 M S D N 忽 略 这些 字 符 , 因 此 它 们 都 等 同 于 AND 运 算 符 。
搜 索 策 略
搜 索 在 线 帮 助 的 方 法 不 是 取 决 于 要 搜 索 的 东 西 ,更 多 的 是 取 决 于 如 何 能 描 述 好 想要 搜 索 的 东 西 。 如 果 能 用 一 两 个 明 确 的 关 键 字 说 明 要 搜 索 的 主 题 , 通 过 M S D N 索 引 来 搜 索 通 常 是 最 有 效 的 方 法 。就 像 一 本 书 的 索 引 一 样 ,M S D N 索 引 在 关 键 字和 一 个 相 对 较 小 的 相 关 文 章 列 表 之 间 建 立 了 联 系 ,这 使 你 可 以 快 速 找 到 所 需 要 的信 息 。另 一 方 面 ,全 文 本 搜 索 覆 盖 范 围 更 宽 ,它 比 索 引 提 供 更 多 的 文 章 以 供 选 择 。搜 索 结 果 取 决 于 你 如 何 仔 细 地 用 短 语 描 述 搜 索 字 符 串 , 并 充 分 利 用 搜 索 运 算 符 。经 过 一 次 全 文 本 搜 索 之 后 , 在 搜 索 列 表 中 仔 细 地 寻 找 最 适 合 于 自 己 的 问 题 的 文章 , 将 是 一 个 单 调 乏 味 的 过 程 。
如 果 该 主 题 对 你 来 说 是 陌 生 的 , 你 可 能 需 要 概 述 信 息 , 并 了 解 一 般 的 背 景 知 识 。这 种 情 况 下 ,MSDN 目 录 列 表 可 能 是 最 好 的 求 助 对 象 。首 先 看 看 目 录 列 表 的 整 体结 构 来 了 解 其 内 容 。 有 时 , 少 量 索 引 或 全 文 本 搜 索 能 帮 助 你 找 到 感 兴 趣 的 列 表区 。 用 这 种 办 法 找 到 一 个 感 兴 趣 的 主 题 后 , 你 可 以 通 过 单 击 M S D N 工 具 栏 上 的Locat e( 定 位 ) 按 钮 , 来 确 定 该 主 题 标 题 在 目 录 列 表 中 的 出 现 位 置 。 Previou s( 前一 个 ) 和 Nex t( 下 一 个 ) 按 钮 选 择 列 表 中 相 邻 的 文 章 , 它 使 你 能 够 通 过 按 顺 序排 列 的 相 关 文 章 来 浏 览 整 个 列 表 。许 多 主 题 开 头 都 有 几 行 非 常 有 帮 助 的 超 文 本 链
接 , 它 们 能 带 你 到 一 个 主 页 、 一 个 主 题 综 述 、 一 个 常 见 问 题 列 表 等 等 。
Favorites ( 收 藏 ) 选 项 卡
在 帮 助 文 本 中 从 一 篇 文 章 跳 到 另 一 篇 文 章 时 ,你 会 不 可 避 免 地 想 要 回 到 早 先 阅 读过 的 文 章 。 图 1-13 所 示 的 Favorites( 收 藏 ) 选 项 卡 这 时 就 有 用 了 , 它 维 护 着 一个 标 记 选 择 过 的 文 章 的 书 签 列 表 , 这 样 , 你 就 可 以 很 快 地 返 回 到 以 前 阅 读 过 的 文章 了 。 这 些 标 记 就 像 一 个 由 Web 浏 览 器 维 护 着 的 书 签 , 并 且 你 会 发 现 , 它 们 对你 在 探 究 在 线 帮 助 时 折 回 原 来 的 位 置 很 有 帮 助 。如果不删除 ,添 加 到 该 列 表 中 的标 题 会 一 直 保 留 , 因 此 , 当 你 启 动 M S D N 程 序 时 , Favorite s( 收 藏 ) 选 项 卡 保 持上 次 离 开 时 的 样 子 。
当 前 文 章( 即 显 示 在 右 边 窗 格 中 的 文 章 ) 的 标 题 出 现 在 Favorite s( 收 藏 ) 选 项 卡的 底 部 。 单 击 Ad d( 添 加 ) 按 钮 , 将 该 标 题 添 加 到 列 表 中 ; 双 击 列 表 中 的 一 个 标题 会 回 到 该 文 章 。
图 1-13 Favorites ( 收 藏 ) 选 项 卡 保 持 想要重新访问的文章列表
访 问 万 维 网
通 过 嵌 入 Internet Explorer 浏 览 器 , M S D N 可 以 接 触 到 其 他 Web 站 点 上 的 信 息 来源 , 不 论 它 们 在 哪 里 。 文 章 可 以 包 含 Internet 地 址 ( 通 用 资 源 定 位 符 或 URL )作为 超 文 本 链 接 , 因 此 , MSDN 可 以 像 打 开 其 他 任 何 库 中 的 文 章 一 样 来 打 开 一 个Web 网 页 。
图 1-14 通过 MSDN 来 访 问 Web 站 点
要 指 定 目 标 Web 网 点 , 从 G o ( 转 向 ) 菜 单 中 选 择 URL 命 令 , 并 输 入 网 点 的 网址 。 图 1-14 演 示 了 一 个 范 例 。
在 开 发 环 境 之 外 工 作
大 多 数 Visual C++ 工 具 只 有 在 Developer Studio 环 境 内 部 才 是 可 用 的 ,但 编 译 器 、链 接 器 、 资 源 编 辑 器 和 生 成 程 序 例 外 。 这 些 程 序 像 32 位 控 制 台 实 用 程 序 一 样 运行 。 通 过 编 译 和 链 接 来 生 成 应 用 程 序 时 , Visual C++ 用 生 成 程 序 来 执 行 两 个 编 译器 和 一 个 链 接 器 。它 们 的 输 出 消 息 通 常 送 到 系 统 的 标 准 输 出 设 备 , 这 些 消 息 被 捕获 , 并 显 示 在 环 境 的 Outpu t( 输 出 ) 窗 口 中 。 不 用 环 境 也 可 以 生 成 应 用 程 序 , 从命 令 行 执 行 四 个 程 序 NMake.exe 、 CL.exe、 Link.exe 和 RC.exe 即 可 。
但 在 Developer Studio 之 外 工 作 是 不 切 实 际 的 。 本 章 开 头 的 特 征 列 表 说 明 了 环 境给 程 序 开 发 带 来 的 好 处 , 尤 其 ( 不 是 唯 一 ) 是 对 使 用 MFC 库 的 C++ 开 发 工 作 。除 非 你 有 遗 留 下 来 的 C 语 言 源 文 件 以 及 还 要 使 用 的 生 成 文 件 , 你 一 定 会 发 现 , 在 环 境 内 部 的 开 发 工 作 更 容 易 ,且 更 具 创 造 性 。第 3 章 解 释 如 何 使 用 旧 的 文 本 编辑 器( 如 果 你 愿 意 的 话 ),但 Developer Studio 远 不 只 是 一 个 文 本 编 辑 器 而 已 。 没有 了 它 , Visual C++ 就 去 掉 了 精 华 部 分 。 本 书 的 每 一 章 都 描 述 了 如 何 使 用 环 境 的某 些 部 分 来 创 建 和 维 护 C/C++ 程 序 。 本 章 仅 仅 是 个 开 头 。
第 2 章 A p p W izard ( 应 用 程 序 向 导 )
Visual C++ 最 显 著 的 技 术 之 一 就 是 它 的“ 向 导 ”。每 个 向 导 擅 长 为 一 种 特 殊 类 型 的程 序 建 立 项 目 , 它 在 创 建 新 项 目 时 提 供 一 个 很 好 的 开 端 , 这 样 , 你 就 不 必 从 头 做起 了 。 它 像 其 他 动 态 链 接 库 一 样 , 在 Developer Studio 环 境 下 运 行 , 并 且 要 求 你提 供 新 程 序 的 特 征 ,然 后 生 成 启 动 器 源 文 件 , 其 中 这 些 新 特 征 的 大 部 分 通 用 代 码都 已 经 替 你 写 好 了 。 Visual C++ 为 专 业 项 目 , 如 ActiveX 控 件 和 Developer Studio 附 加 实 用 程 序 , 提 供 了 各 种 各 样 的 向 导 。甚 至 有 向 导 来 帮 助 你 建 立 自 己 的 定 制 向导 。 在 后 面 的 章 节 中 , 我 们 会 遇 到 其 中 一 些 类 型 的 项 目 , 但 本 章 着 重 讨 论 Visual C++ 的 主 向 导 : AppWizard ( 应 用 程 序 向 导 )。 除 了 措 辞 上 有 所 差 别 外 , 第 6 版 的AppWizard ( 应 用 程 序 向 导 ) 同 以 前 的 版 本 没 有 什 么 改 变 。 如 果 以 前 你 曾 经 使 用过 AppWizard ( 应 用 程 序 向 导 ), 可 以 跳 过 这 一 章 。
AppWizard ( 应 用 程 序 向 导 ) 的 优 点
AppWizar d( 应 用 程 序 向 导 ) 擅 长 为 使 用 微 软 基 础 类 库 的 典 型 的 C++ Windows 应用 程 序 建 立 开 发 项 目 。
如 果 你 想 用 C 来 写 程 序 , 或 不 愿 意 使 用 MFC , 请 忘 掉 AppWizard ( 应 用 程 序 向导 )。用 W in32 Application Wizard 来 代 替 AppWizar d( 应 用 程 序 向 导 ), 不 会 对 你有 什 么 影 响 。 较 早 版 本 的 AppWizard ( 应 用 程 序 向 导 ) 是 专 门 为 创 建 基 于 文 档 / 视 图 结 构 的 应 用 程 序 而 设 计 的 ,这 种 结 构 中 程 序 的 数 据 由 文 档 对 象 来 维 护 , 并 通过 视 图 对 象 提 供 给 用 户 。 MFC 本 身 就 倾 向 于 这 样 一 种 程 序 结 构 。 在 Visual C++ 的 较 晚 版 本 中 , AppWizard ( 应 用 程 序 向 导 ) 已 经 变 得 更 加 灵 活 了 , 它 在 没 有 内置 文 档 支 持 的 时 候 ,也 能 准 备 应 用 程 序 , 这 个 选 项 对 许 多 不 读 取 或 创 建 文 件 的 较小 的 程 序 来 说 , 是 非 常 合 适 的 。 你 可 以 把 这 种 简 洁 的 逻 辑 形 式 称 为“ 视 图 单 一 结构 ”, 用 来 代 替 文 档 /视 图 结 构 , 因 为 这 样 创 建 的 应 用 程 序 包 含 一 个 处 理 显 示 的 视图 类 , 但 没 有 为 文 档 对 象 提 供 通 信 类 。 AppWizard ( 应 用 程 序 向 导 ) 也 能 创 建 一个 不 依 赖 于 文 档 /视 图 的 基 于 对 话 框 的 应 用 程 序 , 它 通 过 对 话 框 来 与 用 户 交 流 。第 5 章 描 述 如 何 在 Visual C++ 中 使 用 AppWizard ( 应 用 程 序 向 导 ), 来 创 建 基 于对 话 框 的 应 用 程 序 , 及 不 使 用 AppWizard ( 应 用 程 序 向 导 ) 时 又 如 何 创 建 。
在 生 成 的 项 目 中 ,每 个 类 都 有 它 自 己 的 执 行 文 件 和 头 文 件 。文 件 中 的 全 部 源 代 码从 空 的 存 根 函 数 到 完 全 成 型 的 程 序 元 素 , 如 工 具 栏 和 用 户 可 从 Help ( 帮 助 ) 菜单 中 调 用 的 About ( 关 于 ) 对 话 框 , 都 应 该 包 括 在 内 。 AppWizard ( 应 用 程 序 向导 ) 为 各 种 各 样 的 程 序 特 征 提 供 了 代 码 , 这 些 特 征 包 括 :
-
单 文 档 、 多 文 档 和 对 话 框 界 面 。
-
停 靠 工 具 栏 、 状 态 栏 和 打 印 机 支 持 。
-
带 有 典 型 的 操 作 命 令 , 如 Open ( 打 开 )、 Save ( 保 存
)、 Prin t( 打 印 )、
Cu t( 剪 切 )、 Copy ( 复 制 ) 和 Paste ( 粘 贴 ) 的 菜 单 。
-
上 下 文 相 关 帮 助 的 启 动 器 文 件 。
-
显 示 程 序 信 息 和 MFC 图 标 的 Abou t( 关 于 ) 对 话 框 。
-
数 据 库 支 持 。
-
对 复 合 文 档 、 Automation 和 ActiveX 控 件 的 OLE/ActiveX 支 持
。
-
对 消 息 应 用 编 程 接 口 ( MAP I ) 和 W indows Sockets 的 支 持
。
在 这 一 章 中 , 我 们 将 着 眼 于 如 何 用 AppWizard( 应 用 程 序 向 导 ) 来 创 建 一 个 预 先载 有 这 些 和 其 他 一 些 特 征 的 新 项 目 。 为 使 你 了 解 AppWizard( 应 用 程 序 向 导 ) 可节 省 你 多 少 工 作 , 图 2-1 演 示 了 从 AppWizard ( 应 用 程 序 向 导 ) 生 成 的 项 目 文 件中 生 成 的 一 个 典 型 的 应 用 程 序 ,它 只 有 一 个 窗 口 。这 个 例 子 中 不 需 要 再 做 其 他 的编 程 工 作 。
图 2-1 AppWizard ( 应 用 程 序 向 导 ) 创 建 的 基 本 应 用 程 序
AppWizard ( 应 用 程 序 向 导 ) 仅 在 建 立 项 目 的 开 头 运 行 一 次 , 它 在 开 始 时 , 提 供足 够 多 的 选 项 , 但 随 后 就 不 再 提 供 了 。 然 而 , 你 并 不 是 完 全 漫 无 目 的 地 漂 游 , 因为 AppWizard ( 应 用 程 序 向 导 ) 建 立 项 目 的 方 式 允 许 你 使 用 其 他 的 Visual C++ 工具,如 ClassWizard 来 继 续 开 发 过 程 。 例 如 , 当 查 看 AppWizard( 应 用 程 序 向 导 ) 源 文 件 时 ,你 会 注 意 到 一 些 特 殊 的 注 释 语 句 。在 第 6 章 中 ,我 们 将 看 到 ClassWizard 用 这 些 注 释 来 监 控 项 目 的 类 。
AppWizard ( 应 用 程 序 向 导 ) 为 项 目 生 成 的 源 文 件 的 数 目 取 决 于 你 指 定 的 特 征 。表 2-1 显 示 了 一 个 典 型 的 列 表 。 表 中 每 个 执 行 文 件 都 有 一 个 相 应 的 同 名 头 文 件 。
表 2-1 AppWizar d( 应 用 程 序 向 导 ) 生 成 的 典 型 的 源 文 件 , 斜 体 的 项 目 表 示 项目 名
文 件 说 明
project.cpp 主 应 用 程 序 源 文 件
ProjectView.cpp 程 序 的 视 图 类 源 代 码
ProjectDoc.cpp 程 序 的 文 档 类 源 代 码
MainFrm.cpp 类 CMainFrame 的 源 代 码 。这 个 类 是 从 MFC 的 CFrame W nd 或 CMDIFrameWnd 派 生 来的 , 它 控 制 程 序 的 主 窗 口
续 表
StdAfx.cpp 用 来 建 立 一 个 名 为 project.pch 的 预 编 译 头 文件 。 预 编 译 头 文 件 采 用 MFC 的 编 译 形 式 , 它 包 括 项 目 引 用 的 文 件 ,这 些 文 件 带 有 前 缀“ Afx ”。对 象 的 计 算 结 果 数 据 使 预 编 译 头 文件 很 大 , 通 常 超 过 6 M B 。 但 头 文 件 通 过 节省 对 未 变 动 的 代 码 的 编 译 工 作 ,从 而 显 著 地缩 短 了 编 译 时 间
project.rc 包 含 项 目 的 资 源 数 据 ( 在 第 4 章 中 讨 论 )
Resource.h 包 含 #define 语 句 来 为 项 目 声 明 常 量
刚 开 始 时 , 你 可 能 试 图 想 放 弃 AppWizard ( 应 用 程 序 向 导 ), 它 对 于 核 心 编 程 人员 来 说 限 制 太 严 。 而 且 , 如 果 你 有 规 律 地 创 建 一 些 相 同 类 型 的 项 目 , 对 你 来 说 , 通 过 复 制 和 修 改 以 前 的 项 目 源 文 件 来 开 始 一 个 新 项 目 , 比 起 用 AppWizar d( 应 用程 序 向 导 ) 来 创 建 一 套 新 文 件 来 说 , 要 容 易 得 多 。 但 Visual C++ 中 的 向 导 技 术 已经 成 熟 到 这 种 地 步 : 它 不 知 何 故 , 看 起 来 相 当 容 易 , 以 致 于 不 用 AppWizard( 应用 程 序 向 导 ) 简 直 是 一 种 错 误 。 在 不 到 60 秒 的 时 间 内 , 你 就 可 以 完 成 一 个 开 发项 目 的 单 调 乏 味 的 常 用 设 置 过 程 , 而 直 接 开 始 代 码 开 发 。 并 且 , 你 可 以 依 赖AppWizard ( 应 用 程 序 向 导 ) 写 的 源 代 码 , 它 保 证 是 没 有 错 误 的 , 这 是 你 在 项 目
间 剪 切 和 粘 贴 代 码 所 不 能 保 证 的 。 如 果 你 所 计 划 的 程 序 正 是 AppWizar d( 应 用 程序 向 导 ) 所 指 定 的 类 型 , 请 不 要 犹 豫 。 你 通 过 用 AppWizard ( 应 用 程 序 向 导 ) 来建 立 项 目 , 可 以 节 省 大 量 时 间 。
运 行 AppWizard ( 应 用 程 序 向 导 )
通 过 环 境 的 File( 文 件 ) 菜 单 中 的 New ( 新 建 ) 命 令 可 开 始 一 个 AppWizard ( 应用 程 序 向 导 ) 项 目 :
单 击 New ( 新 建 ) 显 示 New ( 新 建 ) 对 话 框 的 Projec t( 项 目 ) 选 项 卡 , 其 中 列出 了 Visual C++ 中 的 向 导 。要 运 行 向 导 来 为 一 个 典 型 的 Windows 应 用 程 序 创 建 项目 , 选 择 标 有 MFC AppWizard(exe) 的 图 标 , 如 图 2-2 所 示 。现 在 我 们 集 中 讨 论 这个 AppWizard ( 应 用 程 序 向 导 )。 通 过 MFC AppWizard ( 应 用 程 序 向 导 ) (dll) 图标 调 用 的 AppWizard ( 应 用 程 序 向 导 ), 为 你 建 立 动 态 链 接 库 开 发 项 目 , 下 一 章我 们 将 讨 论 这 个 问 题 。
图 2-2 要 为 典 型 的 应 用 程 序 创 建 项 目 , 需 选 择 MFC AppWizard(exe) 图标
为 项 目 输 入 一 个 名 字 。 正 如 前 面 提 到 过 的 那 样 , AppWizard ( 应 用 程 序 向 导 ) 用项 目 名 来 区 别 项 目 中 不 同 的 文 件 , 因 此 , 项 目 名 要 适 当 地 短 一 些 。 项 目 一 旦 建 立以 后 , 就 没 有 办 法 改 变 它 的 名 字 。 默 认 情 况 下 , Visual C++ 把 AppWizard ( 应 用程 序 向 导 ) 项 目 放 在 Common\MsDev98\MyProjects 目 录 下 ; 如 果 你 想 用 其 他 目录 ,在 Locatio n( 位 置 ) 文 本 框 中 指 定 一 个 路 径 。直 到 你 选 择 列 表 中 的 一 个 图 标 , 并 输 入 一 个 项 目 名 , O K ( 确 定 ) 按 钮 才 能 用 。
单 击 OK ( 确 定 ) 时 , AppWizard ( 应 用 程 序 向 导 ) 以 对 话 框 的 形 式 提 供 多 达 6 个 步 骤 。 在 每 个 步 骤 中 , 对 话 框 的 左 边 显 示 一 个 图 片 , 来 给 出 设 置 的 视 觉 提 示 。在 每 一 步 中 , 单 击 Finish( 完 成 ) 按 钮 , 将 结 束 AppWizard( 应 用 程 序 向 导 ),并 接 受 剩 下 步 骤 中 的 默 认 设 置 。 为 了 在 一 系 列 步 骤 中 前 进 或 后 退 , 单 击 Next ( 下一 步 ) 或 Back ( 后 退 ) 按 钮 即 可 。
步 骤 1 : 程 序 界 面
如 图 2-3 所 示 , AppWizard ( 应 用 程 序 向 导 ) 的 第 一 步 指 定 了 应 用 程 序 的 类 型 , 选 择 单 文 档 界 面 (SDI) 、 多 文 档 界 面 (MDI) 或 基 于 对 话 框 的 界 面 。 要 创 建 不 需 要 文档 对 象 来 从 磁 盘 文 件 中 读 取 数 据 的 简 单 的 W indows 应 用 程 序 , 把 标 为Document/View Architecture Support ( 文 档 /视 图 结 构 支 持 ) 复 选 项 禁 用 即 可 。
图 2-3 在 AppWizard (应用程序向导)的第一步中选择应用程序的界面
对 于 一 次 只 处 理 一 个 文 档 对 象 的 SDI 应 用 程 序 , 请 打 开 Single Documen t( 单 文档 ) 单 选 按 钮 。 这 个 选 项 对 那 些 不 能 明 确 地 遵 循 文 档 /视 图 结 构 的 应 用 程 序 也 是适 用 的 。一 个 SDI 应 用 程 序 的 一 般 性 维 护 程 序 ,比 起 相 应 的 MDI 应 用 程 序 来 说 , 要 小 得 多 , 因 此 , SDI 应 用 程 序 的 可 执 行 文 件 要 更 小 一 些 。
MDI 应 用 程 序 的 优 点 是 能 一 次 处 理 任 意 数 量 的 文 档 , 它 在 每 个 分 离 的 窗 口 中 显示 一 个 文 档 。用 户 可 以 在 不 同 的 文 档 窗 口 中 工 作 ,并 把 每 个 文 档 单 独 保 存 为 一 个文 件 。 在 后 两 章 中 我 们 将 看 到 , Visual C++ 本 身 就 是 M D I 应 用 程 序 的 一 个 例 子 , 它 能 在 不 同 的 编 辑 窗 口 中 显 示 文 本 或 非 文 本 数 据 。
第 三 种 界 面 选 项 创 建 一 个 基 于 对 话 框 的 应 用 程 序 。这 种 选 择 对 于 那 些 不 需 要 一 个主 窗 口 的 小 实 用 程 序 非 常 适 合 ,因 为 用 户 通 过 对 话 框 就 可 与 程 序 交 流 。基 于 对 话框 的 界 面 并 不 像 听 起 来 那 样 限 制 严 格 ,第 5 章 演 示 了 如 何 创 建 显 示 一 个 属 性 表 的基 于 对 话 框 的 应 用 程 序 ,该 对 话 框 能 接 受 并 显 示 大 量 信 息 。W indows 所 带 的 Phone D iale r( 电 话 拨 号 程 序 ) 实 用 程 序 就 是 基 于 对 话 框 的 应 用 程 序 的 一 个 例 子 。
因 为 第 5 章 将 详 细 讨 论 基 于 对 话 框 的 应 用 程 序 ,这 里 就 不 再 讨 论 基 于 对 话 框 的 界面 这 一 选 项 。 然 而 , 本 章 中 大 部 分 信 息 对 基 于 对 话 框 的 应 用 程 序 也 是 适 用 的 。
AppWizard ( 应 用 程 序 向 导 ) 的 步 骤 1 还 要 求 你 提 供 程 序 界 面 的 语 种 。 可 选 的 语言 取 决 于 你 安 装 到 系 统 上 的 AppWizard( 应 用 程 序 向 导 ) 库 ; 单 击 文 本 框 附 近 的箭 头 按 钮 , 可 显 示 可 选 的 语 言 。 每 种 语 言 都 依 赖 它 自 己 的 动 态 链 接 库 , 默 认 情 况下 , 这 些 动 态 库 都 安 装 在 Common\MsDev98\bin\ide 文 件 夹 中 。 库 文 件 名 以
Appw z xxx .dll 的 形 式 表 示 , 其 中 xxx 表 示 一 个 三 位 的 语 言 代 码 。 例 如 , enu 代 表美 国 英 语 , deu 代 表 德 语 , 而 fra 代 表 法 语 。 图 2-4 显 示 了 在 三 种 不 同 语 言 中 由AppWizard ( 应 用 程 序 向 导 ) 生 成 的 应 用 程 序 的 File ( 文 件 ) 菜 单 的 样 子 。
图 2-4 在三种不同的语言中的应用程序的 File( 文 件 ) 菜 单
步 骤 2 : 数 据 库 支 持
在 图 2-5 中 所 示 的 AppWizard ( 应 用 程 序 向 导 ) 的 第 二 步 中 , 要 求 你 提 供 项 目 所需 要 的 数 据 库 支 持 种 类 。 这 一 步 和 下 面 的 步 骤 假 定 你 在 第 一 步 中 选 择 了 带 文 档 / 视 图 支 持 的 Single Document ( 单 文 档 ) 或 Multiple Documents ( 多 文 档 ) 选 项 。
图 2-5 在 AppWizard (应用程序向导)的步骤 2 中 选 择 数 据 库 支 持
如 果 你 的 项 目 不 使 用 数 据 库 ,单 击 Nex t( 下 一 步 )按 钮 跳 过 这 一 步 ,进 到 步 骤 3 。如 图 2-5 所 示 , 四 个 单 选 按 钮 决 定 了 AppWizard ( 应 用 程 序 向 导 ) 添 加 到 项 目 的数 据 库 支 持 程 度 :
-
None ( 无 ): 在 生 成 项 目 时 , 把 数 据 库 支 持 的 库 文
件 排 除 在 外 。 如 果你 的 项 目 不 使 用 数 据 库 , 选 择 None ( 无 ) 单 选 按 钮 , 来 避 免 在 项 目 文件 增 加 不 必 要 的 代 码 。 你 可 以 以 后 再 往 项 目 中 添 加 数 据 库 支 持 。
-
Header files only ( 只 有 头 文 件 ): 在 生 成 过 程 中 , 包
含 数 据 库 头 文 件和 库 文 件 , 但 AppWizard( 应 用 程 序 向 导 ) 不 为 数 据 库 类 生 成 源 代 码 。你 必 须 自 己 写 所 有 的 源 代 码 。 这 个 选 项 适 用 于 那 些 开 始 时 不 使 用 数 据
库 , 但 你 打 算 以 后 添 加 数 据 库 支 持 的 项 目 。
-
**Database view without file suppor t( 数 据 库 视 图 , 没 有 文
件 支 持 )**:包含 数 据 库 头 文 件 和 库 文 件 , 同 时 也 创 建 一 个 记 录 视 图 和 记 录 集 。 生 成的 应 用 程 序 支 持 文 档 , 但 不 支 持 串 行 操 作 。
-
**Database view with file support( 数 据 库 视 图 , 具 有 文 件 支
持 )**: 设 置同 上 , 除 了 生 成 的 应 用 程 序 既 支 持 数 据 库 文 档 , 又 支 持 串 行 操 作 。
如 果 你 用 最 后 两 个 选 项 中 的 一 个 来 包 含 数 据 库 视 图 , 那 么 , 除 非 你 指 出 数 据 源 , 否 则 不 能 继 续 到 下 一 步 。
数 据 来 源
要 指 定 数 据 来 源 , 单 击 Data Sourc e( 数 据 来 源 ) 按 钮 显 示 图 2-6 所 示 的 Database Options( 数 据 库 选 项 ) 对 话 框 。
图 2-6 在 Database Options( 数 据 库 选 项 ) 对 话 框 中 确 定 数 据 来 源
Database Option s( 数 据 库 选 项 )对 话 框 提 示 输 入 数 据 源 是 遵 循 开 放 式 数 据 库 互 接
(ODBC )标 准 , 还 是 微 软 的 数 据 访 问 对 象 (DAO )标 准 , 或 OLE 数 据 库 (OLE DB) 标 准 。 ODBC 功 能 在 数 据 库 管 理 系 统 , 如 M icrosoft Access、 Oracle 或 dBase 的特 定 的 驱 动 程 序 中 实 现 。Visual C++ 提 供 了 一 个 ODBC 驱 动 程 序 的 集 合 ; 其 他 的可 从 经 销 商 那 里 买 到 。 要 查 看 Visual C++ 中 包 含 的 驱 动 程 序 列 表 , 参 看 标 题 为“ ODBC Driver Lis t” 的 在 线 帮 助 文 档 。
选 择 ODBC 作 为 程 序 的 数 据 源 类 型 时 , AppWizard( 应 用 程 序 向 导 ) 生 成 代 码 来调 用 “ ODBC 驱 动 管 理 ”, 并 通 过 它 来 调 用 合 适 的 驱 动 程 序 。 驱 动 程 序 用 结 构 化查 询 语 言 (SQL ) 来 同 目 标 数 据 库 管 理 系 统 发 生 联 系 。 ODBC 支 持 保 证 应 用 程 序 能访 问 不 同 格 式 和 不 同 结 构 的 数 据 。
选 择 ODBC 会 激 活 一 个 列 有 ODBC 数 据 源 管 理 器 中 注 册 过 的 所 有 数 据 来 源 的 下拉 列 表 。 数 据 源 既 包 含 数 据 , 也 包 含 访 问 数 据 所 需 的 信 息 。 要 注 册 数 据 源 , 或 取消 数 据 源 的 注 册 , 在 Control Panel( 控 制 面 板 ) 中 双 击 32 位 ODBC 图 标 来 运 行管 理 器 。 在 安 装 过 程 中 , Visual C++ 通 常 会 装 入 数 据 源 管 理 器 , 但 如 果 你 是 定 制
安 装 Visual C++ 的 ,你 的 系 统 中 可 能 会 没 有 数 据 源 管 理 器 。如 果 Control Pan e (l 控
制 面 板 ) 中 没 有 32 位 ODBC 图 标 , 需 重 新 运 行 Visual C++ 安 装 程 序 , 并 安 装 必要 的 ODBC 数 据 库 支 持 文 件 。
DAO 是 微 软 产 品 如 Access 和 Visual Basic 的 标 准 。 DAO 用 M icrosoft Jet 数 据 库引 擎 来 提 供 一 套 访 问 对 象 , 包 括 数 据 库 对 象 、 表 定 义 和 查 询 定 义 对 象 及 记 录 集 对象。尽管 DAO 在 M D B 文 件( 例 如 那 些 由 M icrosoft Access 创 建 的 文 件 ) 上 工 作
得 最 好 , 一 个 D A O 程 序 也 能 通 过 Microsoft Jet 来 访 问 ODBC 数 据 源 。
OLE DB 是 一 种 新 的 数 据 访 问 方 法 , 它 允 许 一 个 称 为“ 使 用 者 ” 的 客 户 应 用 程 序从 任 何 装 备 了 被 称 为 “ 供 应 者 ” 的 数 据 翻 译 器 的 数 据 源 中 取 回 数 据 。“ 供 应 者 ” 对 应 用 程 序 来 说 , 就 像 一 组 组 分 对 象 模 型 (COM )对 象 , 它 通 常 不 创 建 数 据 , 而 作为 一 个 中 间 人 以 自 己 所 带 的 格 式 访 问 数 据 , 并 以 可 识 别 的 形 式 把 数 据 传 递 给“ 使用 者 ”。图 2-7 说 明 了 “ 使 用 者 ” 如 何 同“ 供 应 者 ”( 而 不 是 同 原 始 的 数 据 源 创 立者 ) 通 信 。
图 2-7 在 OLE DB 中,在数据客户与提供者之间的典型交互
OLE DB 的 优 点 是 在 “ 使 用 者 ” 和 “ 供 应 者 ” 间 不 需 要 任 何 关 于 数 据 格 式 的 预 定协 议 。 至 少“ 供 应 者 ” 负 责 把 数 据 翻 译 成 “ 使 用 者 ” 理 解 的 形 式 , 通 常 是 表 格 式的 格 式 。“ 供 应 者 ” 也 能 对 未 加 工 的 数 据 进 行 改 进 , 例 如 , 按 照 指 定 的 标 准 进 行查 询 处 理 和 排 序 。 在 AppWizard ( 应 用 程 序 向 导 ) 的 Database Option s( 数 据 库选 项 ) 对 话 框 中 选 择 OLE DB 选 项 , 是 创 建 一 个 使 用 数 据 的 应 用 程 序( 而 不 是 数据 供 应 者 ) 的 第 一 步 。 这 个 选 项 从 称 为 “ OLE DB 使 用 者 模 板 ” 的 类 库 中 生 成 代码 , 该 类 库 提 供 了 对 OLE DB 类 对 象 , 例 如 CDataSource 和 CSession 的 包 装 。Visual C++ 提 供 了 另 一 个 向 导( ATL COM AppWizard ) 来 帮 助 编 写“ 供 应 者 ” 应用 程 序 。 第 10 章 对 ATL COM AppWizard 和 Active Template Library 有 更 多 的 描述 , 尽 管 它 是 从 编 写 ActiveX 控 件 的 角 度 , 而 不 是 从 OLE DB 供 应 者 的 角 度 上 来说 的 。
记 录 集 类 型
通 过 在 Database Option s( 数 据 库 选 项 )对 话 框 中 的 Recordset Typ e( 记 录 集 类 型 ) 部 分 中 选 择 三 个 单 选 按 钮 中 的 一 个 , 可 以 指 定 程 序 使 用 的 记 录 集 类 型 。三 个 单 选按 钮 作 用 描 述 如 下 :
-
Snapsho t( 快 照 ): 快 照 记 录 集 保 持 快 照 创 建 时 的 数
据 视 图 。 快 照 是 静态 的 , 这 意 味 着 , 记 录 集 不 会 反 映 出 原 始 数 据 的 改 变 , 除 非 通 过 调 用类 CRecordset 或 CDaoRecordset 的 Requery 函 数 来 刷 新 它 。
-
Dynaset ( 动 态 集 ): 动 态 记 录 集 的 内 容 是 动 态 的 ,
这 意 味 着 , 记 录 集自 动 更 新 , 来 反 映 记 录 的 最 新 改 变 。 然 而 , 动 态 设 备 保 持 一 套 固 定 的记 录 。 一 旦 动 态 集 建 立 , 其 他 用 户 创 建 的 新 记 录 就 不 会 添 加 到 这 个 集
合 中 去 。
- Table ( 表 ): Table ( 表 ) 选 项 只 有 数 据 源 类 型 选 择
为 D A O 时 才 是 可用 的 。 该 选 项 允 许 程 序 使 用 DAO 对 象 以 表 的 形 式 来 操 作 数 据 。 当 选
择 Tab l(e 表 )单 选 按 钮 ,并 单 击 O K( 确 定 )按 钮 ,来 关 闭 Database Options
( 数 据 库 选 项 ) 对 话 框 时 , 另 一 个 对 话 框 就 会 出 现 。 在 这 个 对 话 框 中 , 你 可 以 选 择 程 序 使 用 的 列 表 。
步 骤 3 : OLE 和 ActiveX 支 持
在 AppWizar d( 应 用 程 序 向 导 )的第三步 ( 图 2-8) 中,设置程序的 OLE 和 ActiveX 支 持 类 型 。 对 话 框 上 半 部 分 的 五 个 单 选 按 钮 控 制 着 AppWizard ( 应 用 程 序 向 导 ) 添 加 到 程 序 中 的 复 合 文 档 支 持 的 类 型 。 下 面 是 这 些 选 项 的 说 明 :
图 2-8 在 AppWizard ( 应 用 程 序 向 导 ) 的 第 三 步 中 指 定 OLE 、 ActiveX 支 持
-
None ( 无 ): AppWizard( 应 用 程 序 向 导 ) 不 为 复 合 文
档 支 持 生 成 任 何代 码 。
-
Containe r( 包 容 器 ): AppWizar d( 应 用 程 序 向 导 ) 创
建 能 包 含 链 接 和嵌 入 对 象 的 程 序 。
-
M ini-serve r( 微 型 服 务 器 ): 程 序 充 当 一 个 微 型 服
务 器 , 它 能 创 建 复 合文 档 对 象 , 集 成 应 用 程 序 能 把 这 些 对 象 合 并 到 自 己 的 文 档 中 。 这 样 的文 档 对 用 户 来 说 , 就 像 单 一 文 档 一 样 , 但 实 际 上 它 是 由 不 同 的 来 源 形
成 的 。 微 型 服 务 器 直 接 把 数 据 写 在 集 成 应 用 程 序 的 文 档 中 , 而 不 是 写在 磁 盘 文 件 中 , 因 此 , 对 微 型 服 务 器 创 建 的 对 象 集 成 应 用 程 序 能 嵌 入 , 但 不 能 链 接 。 微 型 服 务 器 应 用 程 序 不 能 作 为 独 立 的 程 序 运 行 , 而 必 须由 集 成 应 用 程 序 来 启 动 。 M icrosoft Draw 就 是 微 型 服 务 器 的 一 个 例 子 。
- Full-server ( 全 服 务 器 ): AppWizard ( 应 用 程 序 向 导
) 创 建 的 程 序 能充 当 一 个 全 服 务 器 应 用 程 序 , 它 具 有 微 型 服 务 器 的 全 部 特 性 , 再 加 上附 加 的 性 能 。 像 微 型 服 务 器 一 样 , 全 服 务 器 应 用 程 序 能 由 集 成 应 用 程
序 来 启 动 , 但 它 也 能 作 为 一 个 独 立 的 Windows 应 用 程 序 来 运 行 。AppWizard ( 应 用 程 序 向 导 ) 增 加 了 对 把 数 据 存 储 到 磁 盘 文 件 中 的 支持 , 因 此 , 全 服 务 器 应 用 程 序 能 像 支 持 嵌 入 一 样 支 持 链 接 。
- Both container and serve r( 包 容 器 和 服 务 器 ): AppWizar
d( 应 用 程 序向 导 ) 生 成 代 码 使 程 序 既 能 像 集 成 应 用 程 序 那 样 嵌 入 对 象 , 又 能 像 服
务 器 应 用 程 序 那 样 提 供 对 象 。
通 过 集 成 应 用 程 序 或 服 务 器 应 用 程 序 来 选 择 一 个 复 合 文 档 选 项 ,会 让 你 为 活 动 文档 选 择 附 加 支 持 。活 动 文 档 在 客 户 和 服 务 器 之 间 提 供 一 个 比 普 通 的 嵌 入 文 档 更 高程 度 的 集 成 , 它 允 许 由 一 个 应 用 程 序 维 护 的 文 档 出 现 在 另 一 个 应 用 程 序 的 窗 口中 。图 2-9 显 示 了 这 种 集 成 的 一 个 例 子 ,其 中 Internet Explore r( 本 例 中 的 包 容 器 ) 打 开 了 一 个 由 服 务 器 Microsoft Word 创 建 的 文 档 。
如 果 你 希 望 你 的 包 容 器 或 服 务 器 程 序 能 串 行 化 复 合 数 据 , 也 就 是 说 ,把 文 档 和 对象 保 存 到 磁 盘 上 ,打 开 单 选 按 钮 ,来 请 求 对 复 合 文 件 的 支 持 。尽 管 从 概 念 上 来 说 , 复 合 文 档 是 单 纯 的 文 档 , 实 际 上 , 它 代 表 不 同 文 件 的 组 合 , 一 个 文 件 包 含 文 档 , 而 其 他 文 件 则 包 含 链 接 到 文 档 的 对 象 。当 保 存 复 合 文 档 时 ,包 容 器 负 责 把 自 己 的文 档 对 象 写 到 磁 盘 上 。然 后 它 给 服 务 器 传 递 一 个 请 求 , 来 把 包 容 器 正 在 使 用 的 各个 对 象 保 存 到 同 一 个 “ 存 储 器 ” 中 。
图 2-9 Active 文 档 包 容 器 和 服 务 器 在 一 起 工 作 的 例 子
第 三 步 的 对 话 框 底 部 的 两 个 复 选 项 询 问 ,是 否 要 求 Automation 和 ActiveX 控 件 支持 。 默 认 情 况 下 , AppWizard ( 应 用 程 序 向 导 ) 激 活 ActiveX Controls ( ActiveX 控 件 ) 选 项 ; 如 果 程 序 不 会 嵌 入 ActiveX 控 件 , 请 清 除 该 复 选 项 。 这 个 决 定 并 不是 不 可 取 消 的 , 以 后 , 你 可 以 轻 易 通 过 包 含 一 行 代 码 , 来 向 MFC 程 序 中 添 加ActiveX 控 件 支 持 。 要 了 解 如 何 向 已 存 在 的 MFC 程 序 中 添 加 ActiveX 控 件 支 持 ,
请 参 阅 第 8 章 。
步 骤 4 : 用 户 界 面 特 征
在 图 2-10 中 所 示 的 AppWizar d( 应 用 程 序 向 导 )的 第 四 步 中 可 以 控 制 AppWizard
( 应 用 程 序 向 导 ) 为 程 序 创 建 哪 些 用 户 界 面 元 素 。
图 2-10 在 AppWizard ( 应 用 程 序 向 导 ) 的 第 四 步 中 选 择 程 序 的 用 户 界 面 特 征
AppWizard ( 应 用 程 序 向 导 ) 自 动 为 程 序 主 窗 口 的 菜 单 系 统 、 工 具 栏 及 状 态 栏 生成 代 码 和 数 据 。 工 具 栏 包 含 与 菜 单 命 令 效 果 一 样 的 按 钮 , 而 状 态 栏 则 显 示 命 令 和工 具 栏 按 钮 的 描 述 信 息 。当 光 标 在 菜 单 命 令 或 工 具 栏 按 钮 上 停 留 一 段 时 间 后 ,帮助 信 息 会 出 现 在 状 态 栏 上 , 如 下 图 所 示 :
没 有 选 中 命 令 时 , 状 态 栏 显 示 诸 如“ Ready ”、“ For Help, press F1 ” 或 任 何 其 他 信息 。 状 态 栏 也 包 括 了 键 盘 的 Caps Lock 、 Num Lock 和 Scroll Lock 键 的 指 示 器 。当 程 序 运 行 时 , MFC 框 架 自 动 更 新 指 示 器 , 因 此 , 你 不 需 要 添 加 其 他 代 码 来 并入 这 一 特 征 。
Normal ( 常 规 ) 和 Internet Explorer Rebars 单 选 按 钮 为 应 用 程 序 的 工 具 栏 提 供 两种 不 同 的 风 格 。 选 择 ReBars 选 项 , 会 用 MFC 的 新 的 CReBar 类 来 为 工 具 栏 生 成代 码 , 最 终 会 生 成 Visual C++ 、Internet Explorer 及 其 他 应 用 程 序 中 的 平 面 的 工 具
栏 风 格 。 平 面 的 工 具 栏 是 可 以 调 整 大 小 的 , 因 此 使 用 速 记 词 “ rebar ”, 只 有 当 鼠标 移 到 按 钮 上 面 时 , 该 按 钮 才 凸 起 。 菜 单 、 工 具 栏 和 状 态 栏 的 主 题 将 在 第 4 章 详细 讨 论 。
打 印 支 持
默 认 情 况 下 AppWizar d( 应 用 程 序 向 导 ) 激 活 Printing And Print Preview( 打 印 和打 印 预 览 ) 复 选 项 。 这 个 选 项 向 应 用 程 序 的 视 图 类 中 添 加 启 动 器 代 码 , 它 跨 过 了MFC 的 Cview 的 三 个 虚 拟 函 数 :
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//CDemoView printing
BOOL CDemoView::OnPreparePrinting(CPrintInfo*pInfo)
{
// default prepartation
return DoPreparePrinting(pInfo);
}
void CDemoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo/)
{
//TODO: add extra initialization before printing
}
void CDemoView::OnEndPrinting(CDC* /*pDC*/,CPrintInfo* /*pInofo*/)
{
// TODO:and cleanup after printing
}
这 些 为 在 文 档 /视 图 程 序 中 打 印 提 供 了 功 能 框 架 , 但 在 程 序 打 印 文 档 之 前 , 你 还需 要 做 更 多 的 工 作 。 要 更 好 地 了 解 如 何 向 MFC 程 序 中 添 加 打 印 功 能 , 参 阅 Jeff Prosise 的《 Programming Windows 95 with MFC 》的第 10 章 。 MSDN 在 线 帮 助 也提 供 了 由“ Printing and Print Preview Topics ”开 始 的 一 系 列 主 题 信 息 。选 中 Search Titles Only 复选项,并在 M S D N 的 Searc h( 搜 索 ) 选 项 卡 中 键 入 该 标 题 , 即 可 找到 该 主 题 。
在 线 帮 助
激 活 Context-Sensitive Help ( 上 下 文 相 关 ) 复 选 项 , 会 告 诉 AppWizard ( 应 用 程
序 向 导 ) 你 希 望 程 序 提 供 在 线 帮 助 。 AppWizard ( 应 用 程 序 向 导 ) 会 向 项 目 中 添加 源 代 码 和 一 系 列 文 件 来 帮 助 你 创 建 一 个 完 整 的 帮 助 系 统 。 AppWizard ( 应 用 程序 向 导 ) 会 仔 细 地 说 明 它 添 加 到 程 序 中 的 所 有 的 命 令 和 工 具 栏 按 钮 , 例 如 New 、Open 、 Cut 和 Paste 。 这 些 说 明 清 晰 完 整 , 你 不 需 要 再 做 更 多 的 工 作 , 只 需 要 通过 说 明 那 些 自 己 添 加 到 程 序 中 的 命 令 来 加 强 帮 助 文 件 。 本 部 分 首 先 描 述 了AppWizard ( 应 用 程 序 向 导 ) 创 建 的 帮 助 系 统 , 然 后 简 要 解 释 如 何 用 自 己 的 帮 助文 本 来 加 强 帮 助 系 统 。
当 程 序 需 要 上 下 文 相 关 帮 助 时 , AppWizard ( 应 用 程 序 向 导 ) 在 项 目 文 件 夹 中 创建 一 个 名 为 HLP 的 子 文 件 夹 。 HLP 子 文 件 夹 中 的 文 件 之 一 是 名 为 AfxCore.rtf 的主 题 文 件 。 如 果 程 序 要 求 打 印 支 持 , AppWizard ( 应 用 程 序 向 导 ) 还 添 加 另 一 个名 为 AfxPrint.rtf 的 主 题 文 件 。 以 多 信 息 文 本 格 式 写 的 AfxCore.rtf 和 AfxPrint.rtf 包 含 了 描 述 AppWizar d( 应 用 程 序 向 导 ) 给 项 目 添 加 的 特 征 的 帮 助 文 本 。HLP 子文 件 夹 也 包 含 一 个 与 该 项 目 同 名 , 而 扩 展 名 为 HPJ 的 帮 助 项 目 文 件 。 当 你 生 成项 目 时 ,Visual C++ 在 启 动 编 译 器 之 前 ,先 执 行 名 为 M akeHelp.bat 的 批 处 理 文 件 。M akeHelp.bat 运 行 Makehm.exe Help Maintenance 实 用 程 序 , 它 读 入 项 目 的Resource.h 文 件 中 的 标 志 定 义 , 并 创 建 扩 展 名 为 H M 的 帮 助 映 像 文 件 。 然 后 该 批处 理 文 件 运 行 Hcrtf.exe 帮 助 编 译 器 , 来 收 集 取 自 帮 助 映 像 文 件 、 项 目 的 HPJ 文件 及 RTF 文 件 中 的 文 本 ,它 用 这 些 来 创 建 一 个 W indows WinHlp32 帮 助 文 件 查 看器 能 读 取 的 HLP 文 件 。
AppWizard ( 应 用 程 序 向 导 ) 也 写 一 些 源 代 码 来 运 行 WinHlp32 , 并 加 载 项 目 的
HLP 文 件 来 响 应 用 户 的 帮 助 请 求 。 整 个 帮 助 界 面 是 通 过 在 项 目 的 MainFrm.cpp
文 件 中 将 四 个 入 口 添 加 到 消 息 映 像 中 实 现 的 , 如 下 所 示 :
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
.
.
.
ON_COMMAND(ID_HELP_FINDER,CFrameWnd::OnHelpFinder)
ON_COMMAND(ID_HELP,CFrameWnd::OnHelp) ON_COMMAND(ID_CONTEXT_HELP,CFrameWnd::OnContextHelp
)
ON_COMMAND(ID_ DEFAULT _HELP_ CFrameWnd::OnHelpFinder) END_MESSAGE_MAP()
映 像 中 的 每 个 入 口 指 向 由 MFC 框 架 提 供 的 三 个 函 数 之 一 。 调 用 这 些 函 数 用 以 响
应 不 同 的 事 件 , 每 个 函 数 都 调 用 W inHlp32 , 并 显 示 项 目 帮 助 文 件 中 的 相 应 文 本 。
下 面 的 列 表 描 述 了 什 么 时 候 调 用 函 数 :
被 调 用 的 函 数 当 用 户 做 如 下 事 情 的 时 候
OnHelpFinder 从 Hel p( 帮 助 )菜 单 中 选 择 Help Topics
( 帮 助 主 题 ) 命 令 时
OnHelp 按 F1 键 来 接 受 关 于 当 前 上 下 文 的 帮 助时
OnContextHelp 按 Shift+F1 或 单 击 工 具 栏 上 的 Hel p( 帮助 ) 按 钮 时
从 Help ( 帮 助 ) 菜 单 中 选 择 Help Topic s( 帮 助 主 题 ) 命 令 , 会 在 W inHlp32 查 看器 中 显 示 一 个 典 型 的 Help Topics( 帮 助 主 题 ) 对 话 框 , 如 图 2-11 所 示 。 用 户 可以 浏 览 Help Topic s( 帮 助 主 题 ) 对 话 框 来 寻 找 想 得 到 的 主 题 帮 助 。
图 2-11 Help Topics ( 帮 助 主 题 ) 对 话 框
AppWizar d( 应 用 程 序 向 导 )在 程 序 的 工 具 栏 上 也 添 加 了 一 个 Hel p( 帮 助 ) 按 钮 , 它 同 Developer Studio 对 话 框 右 上 角 的 小 问 号 按 钮 相 类 似 。 单 击 Help ( 帮 助 ) 按
钮 , 会 把 鼠 标 形 状 改 变 为 一 个 带 问 号 的 箭 头 。 然 后 , 用 户 可 以 单 击 程 序 窗 口 的 任何 部 分 , 包 括 菜 单 命 令 、 状 态 栏 和 工 具 栏 按 钮 :
调 用 Help ( 帮 助 ) 工 具 , 将 引 起 程 序 执 行 WinHlp32 , 它 显 示 一 个 描 述 所 单 击 元素 的 帮 助 窗 口 。 例 如 , 通 过 像 上 面 所 说 的 那 样 单 击 Save 按 钮 以 获 取 帮 助 时 , 会显 示 图 2-12 所 示 的 帮 助 窗 口 。
通 过 描 述 其 他 程 序 自 身 的 特 征 ,可 以 加 强 帮 助 系 统 , 在 一 个 能 识 别 多 信 息 文 本 格式 的 字 处 理 程 序 中 加 载 AfxCore.rtf 。 不 要 使 用 W indows 所 带 的 WordPad 实 用 程序 。 尽 管 WordPad 能 读 取 多 信 息 文 本 文 档 , 但 它 不 保 存 帮 助 编 译 器 所 需 要 的 信息 。多 信 息 文 本 文 档 也 是 以 普 通 的 ASCII 格 式 写 的 ,因此,在紧急时候你可以通
过 文 本 编 辑 器 来 作 小 小 的 改 动 。
创 建 自 己 的 帮 助 文 本 的 第 一 步 是 搜 索 字 符 串 “ <<YourApp>> ”, 并 用 应 用 程 序 名来 取 代 它 。 双 击 文 档 中 的 角 括 号 (<<>> ), 会 装 入 提 示 你 应 添 加 的 文 本 类 型 的 占 位符 文 本 。 用 新 的 文 本 来 取 代 提 示 和 角 括 号 。 去 除 应 用 程 序 不 用 的 所 有 主 题 , 并 从AppWizard ( 应 用 程 序 向 导 ) 放 在 文 件 中 的 文 本 中 取 出 对 重 要 格 式 的 提 示 。 文 件中 的 主 题 必 须 由 硬 分 页 符 分 隔 开 。
图 2-12 程 序 的 Sav e(保存)命令的帮助窗口
写 作 帮 助 文 件 这 个 主 题 范 围 广 泛 , 这 里 不 可 能 将 它 完 全 说 清 楚 。在 线 帮 助 描 述 了如 何 用 Visual C++ 提 供 的 Help Workshop 实 用 程 序 来 构 造 由 AppWizard ( 应 用 程
序 向 导 ) 生 成 的 帮 助 系 统 。
Advanced ( 高 级 ) 按 钮
在 AppWizar d( 应 用 程 序 向 导 ) 第 四 步 的 对 话 框 的 右 下 角 , 是 一 个 Advance d( 高级 ) 按 钮 , 单 击 它 , 将 显 示 一 个 标 题 为“ Advanced Option s( 高 级 选 项 )” 的 两 页的 对 话 框 。 在 第 一 页 Document Template String s( 文 档 模 板 字 符 串 ) 中 , 可 以 改写 储 存 在 W indows 和 MFC 框 架 使 用 的 程 序 数 据 中 的 某 些 字 符 串 。如 果 在 第 三 步中 选 中 了 Active Document Server ( 活 动 的 文 档 服 务 器 ) 复 选 项 , 你 必 须 在Document Template Strings 页 中 为 应 用 程 序 的 文 档 文 件 指 定 一 个 文 件 扩 展 名 。 在该 页 的 第 一 个 编 辑 框 中 键 入 扩 展 名 , 如 下 页 图 所 示 。
系 统 把 带 这 种 扩 展 名 的 文 件 识 别 为 属 于 你 的 服 务 器 应 用 程 序 的 文 件 ,这 种 方 法 与它 用 M icrosoft Word 来 关 联 D O C 文 件 的 方 法 一 样 。 AppWizard ( 应 用 程 序 向 导 ) 用 适 合 于 应 用 程 序 的 字 符 串 来 填 写 剩 下 的 编 辑 框 ,你 可 以 接 受 它 们 ,或 按 你 的 想法 来 修 正 它 们 。 我 们 将 在 第 4 章 中 详 细 讨 论 这 些 字 符 串 。
对 话 框 的 第 二 页 W indow Styles ( 窗 口 风 格 ) 允 许 你 控 制 程 序 主 窗 口 的 外 观 , 而且 , 如 果 你 在 第 一 步 中 选 择 了 Multiple Documen t( 多 文 档 ) 选 项 , 在 这 里 还 可 以控 制 程 序 的 文 档 窗 口 的 外 观 。选择 Window Style s( 窗 口 风 格 )页 顶 部 的 Use Split W indow ( 使 用 分 隔 窗 口 ) 复 选 项 , 会 在 SDI 项 目 的 M ainFrm.cpp 文 件 中 添 加 下面 这 个 函 数 :
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
{
return m_wndSplitter.Create(this,
2, 2,
Csize(10, 10), pContext);
}
MDI 项 目 在 它 的 ChildFrm.cpp 文 件 中 接 收 到 类 似 的 OnCreateClient 函 数 。 对 于
SDI 应 用 程 序 ,OnCreateClient 函 数 启 用 程 序 主 窗 口 中 的 分 隔 条 。程 序 的 Vie w( 查
看 ) 菜 单 中 的 Spli t( 分 隔 ) 命 令 打 开 分 隔 条 , 它 允 许 程 序 在 同 一 窗 口 的 一 个 、 两个 或 四 个 窗 格 中 显 示 数 据 。 对 于 M D I 应 用 程 序 , AppWizar d( 应 用 程 序 向 导 ) 把Split( 分 隔 ) 命 令 放 在 程 序 的 W indow ( 窗 口 ) 菜 单 中 , 它 控 制 每 个 子 窗 口 的 分隔 条 。 图 3-4 显 示 了 Visual C++ 文 本 编 辑 器 中 使 用 分 隔 条 的 例 子 。
步 骤 5 : 使 用 MFC 库
图 2-13 所 示 的 AppWizard ( 应 用 程 序 向 导 ) 的 第 五 步 询 问 你 想 创 建 的 程 序 的 风格 、 你 是 否 需 要 附 加 的 源 代 码 注 释 , 及 你 希 望 程 序 如 何 链 接 到 MFC 库 。
图 2-13 选择源文件注释和 MFC 库选项
项 目 风 格
AppWizard ( 应 用 程 序 向 导 ) 提 供 了 两 种 程 序 风 格 , 它 们 由 步 骤 5 对 话 框 顶 部 的两 个 单 选 按 钮 来 决 定 。 默 认 按 钮 为 MFC Standar d( MFC 标 准 ), 对 于 创 建 带 有 从CView 派 生 而 来 的 视 图 类 的 普 通 的 W indows 应 用 程 序 , 它 是 正 确 的 选 择 。 本 书中 后 面 的 章 节 在 用 AppWizard ( 应 用 程 序 向 导 ) 来 创 建 范 例 程 序 时 采 用 MFC Standard( MFC 标 准 ) 设 置 , 因 此 , 这 里 花 些 时 间 来 讨 论 一 下 第 二 个 单 选 按 钮 的作 用 是 值 得 的 。 按 钮 标 题 为 W indows Explorer( W indows 资 源 管 理 器 ), 是 因 为这 时 AppWizard ( 应 用 程 序 向 导 ) 创 建 的 应 用 程 序 有 着 与 大 家 熟 知 的 W indows 所 带 的 Explorer( 资 源 管 理 器 ) 实 用 程 序 相 似 的 外 观 和 用 户 界 面 。
Explorer( 资 源 管 理 器 ) 形 式 的 应 用 程 序 的 主 窗 口 被 分 隔 成 相 邻 的 两 个 窗 格 , 每一 个 窗 格 显 示 不 同 的 内 容 , 而 且 每 一 个 窗 格 都 由 它 自 己 的 类 来 控 制 。左 窗 格 的 视图 类 派 生 自 MFC 的 CTreeView , 它 使 该 窗 格 适 合 于 显 示 一 个 通 过 树 形 层 次 相 关联 的 条 目 列 表 , 例 如 公 司 的 职 员 列 表 、 家 谱 表 或 硬 盘 上 的 目 录 和 文 件 列 表 。 对 应于 右 边 窗 格 的 视 图 类 派 生 自 CListView , 它 被 设 计 用 来 显 示 在 某 些 方 面 属 于 左 边窗 格 当 前 选 中 的 选 项 的 条 目 列 表 。 像 Explore r( 资 源 管 理 器 ) 一 样 , 程 序 的 工 具
栏 包 含 了 四 个 调 整 窗 格 外 观 的 附 加 按 钮 ,它 允 许 用 户 选 择 大 图 标 或 小 图 标 的 不 同排 列 。 下 面 显 示 了 一 个 典 型 的 Explorer( 资 源 管 理 器 ) 形 式 的 应 用 程 序 的 外 观 :
左 边 窗 格 中 包 含 的 树 形 视 图 控 制 中 的 条 目 有 小 的 加 号 和 减 号 来 展 开 或 折 叠 列表 。应 用 程 序 通 过 在 窗 口 的 CREATESTRUCT 结 构 中 设 置 风 格 标 志 ,来 添 加 按 钮和 分 层 线 :
BOOL CLeftView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT;
return CTreeView::PreCreateWindow(cs);
}
我 们 还 没 有 讨 论 过 使 你 能 检 查 和 修 改 程 序 的 Visual C++ 编 辑 器 ,但 如 果 你 对 回 顾上 述 简 单 程 序 的 源 代 码 感 兴 趣 ,可 以 在 附 带 光 盘 的 Code\Chapter.02\Demo 文 件 夹下 找 到 这 些 项 目 文 件 。 Demo 项 目 是 用 AppWizard ( 应 用 程 序 向 导 ) 来 创 建 的 , 它 在 第 一 步 中 选 择 了 Single Document( 单 文 档 ) 选 项 , 而 在 第 五 步 中 选 择 了W indows Explorer( 资 源 管 理 器 ) 选 项 , 并 且 接 受 了 剩 下 的 AppWizard ( 应 用 程序 向 导 ) 的 默 认 选 择 。 Demo 是 一 个 基 础 项 目 , 它 仅 创 建 了 由 AppWizard ( 应 用程 序 向 导 ) 生 成 的 Explore r( 资 源 管 理 器 ) 形 式 的 应 用 程 序 所 需 的 典 型 的 代 码 。第 3 章 和 第 4 章 更 进 一 步 地 描 述 了 如 何 用 Visual C++ 编 辑 器 来 访 问 和 查 看 项 目 , 例 如 那 些 在 附 带 光 盘 上 找 到 的 项 目 。
源 文 件 注 释
要 求 源 文 件 注 释 会 使 AppWizar d( 应 用 程 序 向 导 ) 在 生 成 的 源 代 码 中 添 加 有 用 的所 做 事 项 的 注 解 。 这 些 注 解 外 观 类 似 于 下 面 的 注 释 , 它 建 议 你 添 加 的 源 代 码 ,
应 使 一 个 特 征 或 函 数 变 得 可 操 作 :
void CDemoDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
//TODO:add storing code here
}
else
{
//TODO: add loading code here
}
}
选 择 添 加 源 文 件 注 释 , 也 会 使 AppWizar d( 应 用 程 序 向 导 ) 在 项 目 文 件 夹 中 放 置一 个 ReadMe.txt 文 件 。 ReadMe 文 件 作 为 整 个 项 目 的 目 录 列 表 , 提 供 了 对
AppWizard ( 应 用 程 序 向 导 ) 生 成 的 所 有 文 件 的 简 要 说 明 。链 接 到 MFC 库
第 五 步 中 的 第 三 个 选 项 决 定 程 序 如 何 链 接 到 MFC 。默 认 情 况 下 ,As A Shared DLL
( 作 为 共 享 的 DLL ) 单 选 按 钮 被 选 中 , 这 意 味 着 AppWizar d( 应 用 程 序 向 导 ) 建立 应 用 程 序 , 来 动 态 地 链 接 到 包 含 在 单 独 文 件 中 的 MFC 库 。 这 种 链 接 方 式 显 著地 减 小 了 应 用 程 序 的 可 执 行 文 件 的 大 小 , 并 能 更 有 效 地 利 用 系 统 资 源 。
然 而 , 动 态 链 接 到 MFC 要 求 提 供 M fc nn .dll 库 文 件 , 文 件 名 中 的 nn 代 表 MFC 的 版 本 号 。 文 件 通 常 是 在 W indows System 或 System32 文 件 夹 下 。 如 果 你 的 应 用程 序 动 态 链 接 到 MFC , 而 且 应 用 程 序 通 常 是 用 在 那 些 可 能 没 有 M fc nn .dll 库 的 系统 上 ,你 应 该 把 这 个 库 文 件 作 为 应 用 程 序 包 的 一 部 分 提 供 给 用 户 。 如 果 应 用 程 序使 用 Unicode , 则 应 用 Mfcnnu.dll 文 件 来 代 替 上 述 的 库 文 件 。 微 软 允 许 你 自 由 地把 这 些 库 文 件 附 在 应 用 程 序 中 。应 用 程 序 的 安 装 程 序 可 以 搜 索 用 户 硬 盘 上 已 有 的MFC 库 文 件 , 并 把 文 件 复 制 到 System 文 件 夹 中 ( 如 果 文 件 夹 中 还 没 有 的 话 )。如 果 还 没 有 Msvcrt.dll 文 件 , 则 还 要 复 制 它 , 因 为 MFC 使 用 C 运 行 时 库 的 共 享版 。 库 文 件 同 旧 的 应 用 程 序 保 持 向 上 兼 容 , 因 此 如 果 用 户 的 System 文 件 夹 中 已经 包 含 有 更 新 版 本 的 MFC 和 C 运 行 时 库 文 件 , 你 的 安 装 程 序 就 不 需 要 再 复 制 这些 文 件 。
如 果 你 的 动 态 链 接 应 用 程 序 打 算 在 国 外 发 行 , 在 那 里 , 它 可 能 会 运 行 在 不 同 语 言的 系 统 上 , 那 么 你 需 要 考 虑 更 多 的 事 情 。 MFC 库 文 件 包 含 了 字 符 串 数 据 , 例 如
程 序 能 访 问 的 对 话 框 文 本 和 帮 助 信 息 。你 必 须 保 证 应 用 程 序 不 会 访 问 和 显 示 以 用户 母 语 以 外 的 语 言 写 的 库 文 件 字 符 串 。有 两 个 办 法 来 解 决 这 个 问 题 。最 简 单 的 办法 是 写 程 序 时 使 用 自 己 专 用 的 字 符 串 数 据 , 而 不 访 问 由 库 文 件 提 供 的 文 本 (第 4 章 更 详 细 地 讨 论 了 这 个 问 题 )。然后,你在分发 M fc nn .dll 时 , 就 可 以 不 用 考 虑 用户 的 区 域 设 置 了 。
第 二 种 解 决 办 法 是 改 写 安 装 程 序 , 使 它 询 问 主 机 系 统 的 当 地 语 言 、 把 重 新 分 配 的M fc nnxxx .dll 文 件 复 制 到 System 文 件 夹 中 , 并 重 命 名 为 M fc nn loc.dll( 文 件 名 中的 xxx 代 表 主 机 语 言 的 三 位 代 码 , 例 如 deu 代 表 德 语 而 fra 代 表 标 准 的 法 语 )。要了 解 这 个 主 题 的 更 多 信 息 , 参 见 在 线 帮 助 的 Technical Notes 56 和 57 , 你 可 以 通过 MSDN 索 引 中 的 “ MFC components ” 条 目 来 找 到 它 。
如 果 你 愿 意 把 应 用 程 序 静 态 链 接 到 MFC , 选 择 标 题 为 “ As A Statically Linked Library ( 作 为 静 态 链 接 库 )” 的 单 选 按 钮 。 静 态 链 接 意 味 着 , 应 用 程 序 不 依 赖 于MFC 库 文 件 的 存 在 ,尽 管 它 可 能 仍 需 要 Msvcrt.dll 文 件 。 静 态 链 接 的 代 价 是 可 执行 文 件 更 大 , 而 且 , 对 内 存 的 利 用 可 能 不 够 充 分 。 在 Visual C++ 的 学 习 版 中 , 静态 链 接 到 MFC 是 不 可 能 的 。
你 在 第 五 步 中 选 择 的 MFC 链 接 选 项 仅 仅 是 项 目 的 初 始 设 置 , 你 可 以 在 开 发 过 程中 的 任 何 时 候 选 择 一 个 不 同 的 选 项 。 在 生 成 项 目 之 前 , 从 Projec t( 项 目 ) 菜 单 中选 择 Settings( 设 置 ) 命 令 , 并 在 对 话 框 的 Genera l( 常 规 ) 选 项 卡 中 选 择 静 态 或动 态 链 接 。
步 骤 6 : 类 和 文 件 名
AppWizar d( 应 用 程 序 向 导 ) 的 第 六 步( 也 是 最 后 一 步 )逐条列举 AppWizar d( 应用 程 序 向 导 )将 为 项 目 创 建 的 类 。要 改 变 类 的 名 字 ,在 列 表 中 选 中 它 ,并 在 Class Nam e( 类 名 ) 文 本 框 中 输 入 一 个 新 名 字 。 其 他 的 文 本 框 显 示 了 AppWizard ( 应用 程 序 向 导 ) 为 类 源 代 码 创 建 的 文 件 名 。 这 些 名 字 只 是 一 个 建 议 , 你 可 以 为 列 表中 除 应 用 程 序 类 ( 图 2-14 中 名 字 为 CDemoApp 的 类 ) 外 的 所 有 类 输 入 一 个 新 的 名字 。 包 含 应 用 程 序 类 的 源 文 件 的 名 字 取 自 项 目 , 因 此 不 能 被 改 变 。
图 2-14 在 AppWizard 的 第 六 步 中 指 定 类 名
单 击 Finish ( 完 成 ) 按 钮 后 , AppWizard ( 应 用 程 序 向 导 ) 显 示 一 个 摘 要 表 , 其中 列 出 了 所 选 的 项 目 特 征 ( 图 2-15) 。 这 个 摘 要 是 你 取 消 项 目 的 最 后 机 会 。 单 击O K ( 确 定 ) 会 使 AppWizard ( 应 用 程 序 向 导 ) 在 摘 要 表 底 部 所 列 的 目 录 下 创 建项 目 。
图 2-15 在 AppWizard (应用程序向导)中选择的项目特征列表
用 AppWizard ( 应 用 程 序 向 导 ) 来 创 建 DLL 文 件
如 果 你 要 开 发 一 个 动 态 链 接 库 , 而 不 是 一 个 普 通 的 W indows 应 用 程 序 , 在 New
( 新 建 ) 对 话 框 中 选 择 MFC AppWizard(dll) 图 标 ( 参 见 图 2-3) 。 这 个 特 殊 的AppWizar d( 应 用 程 序 向 导 ) 仅 显 示 图 2-16 所 示 的 一 个 步 骤 , 它 询 问 诸 如 你 的 动态 链 接 库 应 如 何 链 接 到 MFC 之 类 的 信 息 。
图 2-16 使 用 AppWizard ( 应 用 程 序 向 导 ) 设 置 DLL 项目
这 个 向 导 提 供 了 三 个 不 同 的 链 接 选 项 ,每 个 都 有 优 点 和 缺 点 。前 两 个 选 项 使 动 态链 接 库 能 被 任 何 W in32 程 序 访 问 。 第 三 个 选 项 限 制 较 严 , 因 为 它 创 建 的 动 态 链接 库 只 能 用 在 使 用 MFC 的 应 用 程 序 和 其 他 库 文 件 上 。 下 面 描 述 了 各 个 链 接 选项 :
-
Regular DLL with MFC statically linked ( 具 有 静 态 链 接 MFC 的
常 规DLL ): 动 态 链 接 库 静 态 地 链 接 到 MFC , 这 使 它 能 不 依 赖 于 MFC 库 文件 的 存 在 , 而 运 行 在 任 何 的 W in32 系 统 上 。
-
Regular DLL using shared MFC DLL ( 使 用 共 享 MFC DLL 的 常 规DLL
): 运 行 你 的 动 态 链 接 库 需 要 访 问 正 确 版 本 的 MFC 库 文 件 。 这 样就 减 小 了 最 终 的 可 执 行 文 件 大 小 , 但 正 如 前 面 解 释 过 的 那 样 , 这 可 能需 要 在 你 的 产 品 中 附 带 MFC 库 文 件 。如 果 你 的 动 态 链 接 库 是 设 计 用 在动 态 链 接 到 同 一 版 本 的 MFC 的 应 用 程 序 上 时 ,你 尤 其 需 要 考 虑 这 个 选项 ,因 为 这 样 一 个 MFC 的 实 例 就 可 以 既 用 作 调 用 的 应 用 程 序 ,又 作 为你 的 库 文 件 。
-
MFC Extension DLL(using shared MFC DLL )( MFC 扩 展 DL L( 使 用
共享 MFC DLL )):这 个 选 项 同 前 述 的 选 项 有 些 类 似 ,最 重 要 的 差 别 是 调用 过 程 也 必 须 动 态 链 接 到 正 确 版 本 的 MFC 库 文 件 。 一 个 MFC Extension DLL 提 供 的 类 加 强 或 补 充 了 原 有 的 类 的 功 能 。 要 了 解 编 写MFC Extension DLL 的 详 细 信 息 , 参 考 Technical Note 33 , M S D N 在 线
帮 助 中 的 “ DLL Version of MFC ”。
如 果 你 想 把 动 态 链 接 库 用 在 诸 如 M icrosoft Excel 和 Visual Basic 之 类 的Automation 客 户 上 , 选 中 Automation 复 选 项 。 选 中 W indows Sockets ( W indows 套 接 字 )复 选 项 来 添 加 对 在 Internet 或 其 他 任 何 使 用 TCP/IP 协 议 的 网 络 系 统 上 进行 通 信 的 支 持 。 选 择 W indows Sockets 支 持 会 使 AppWizard ( 应 用 程 序 向 导 ) 增加 一 个 对 MFC 的 AfxSocketInit 函 数 的 调 用 :
BOOL CDemoApp::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED); return FALSE;
}
return TRUE;
}
当 然 , 你 必 须 自 己 写 实 际 的 通 信 代 码 。
管 理 模 块 状 态
为 保 持 动 态 链 接 库 的 简 易 特 性 , AppWizard ( 应 用 程 序 向 导 ) 为 库 文 件 项 目 生 成的 代 码 比 起 它 为 普 通 的 应 用 程 序 所 写 的 源 代 码 来 更 简 洁 。 项 目 的 CPP 文 件 包 含一 个 消 息 映 像 和 类 的 构 造 器 。文 件 还 包 括 一 个 注 释 块 , 它 解 释 库 文 件 中 输 出 函 数可 能 需 要 调 用 MFC 的 AFX_MANAGE_STATE 宏 。 这 取 决 于 你 的 动 态 链 接 库 是静 态 还 是 动 态 链 接 到 MFC 库 。 静 态 链 接 到 MFC 库 不 需 要AFX_MANAGE_STATE 宏 , 但 是 , 因 为 项 目 的 链 接 设 置 在 开 发 过 程 中 很 容 易 改变 , 在 开 始 的 时 候 , 最 好 先 假 设 使 用 MFC 的 动 态 链 接 库 是 动 态 链 接 到 MFC 库文 件 的 。 因 此 , 调 用 MFC 的 输 出 函 数 , 应 该 像 下 面 这 样 通 过 调 用AFX_MANAGE_STATE 宏 来 开 始 :
extern “ c ” _declspec( dllexport ) void WINAPI ExportedFunction()
{
#ifdef _AFXDLL
AFX_MANAGE_STATE( AfxGetStaticModuleState() ); #endif
}
在 每 个 线 程 的 局 部 存 储 器 的 内 部 , MFC 维 持 了 一 个 指 向 被 称 为 “ 模 块 状 态 ” 的结 构 的 指 针 , 该 结 构 中 包 含 了 MFC 库 当 前 正 在 维 护 的 过 程 模 块 的 特 定 信 息 。 当应 用 程 序 进 入 到 动 态 链 接 库 的 输 出 函 数 中 时 , 模 块 状 态 属 于 调 用 它 的 应 用 程 序 , 而 不 是 属 于 你 的 库 文 件 。 在 把 执 行 权 转 移 到 MFC 时 , 输 出 函 数 应 首 先 把 指 针 改变 为 指 向 DLL 自 己 的 模 块 状 态 。 这 就 是 使 用 AFX_MANAGE_STATE 宏 的 目 的 , 它 临 时 把 模 块 状 态 指 针 指 向 当 前 的 模 块 ( 即 你 的 动 态 链 接 库 ), 然 后 , 当 输 出 函数 完 成 , 并 返 回 到 调 用 它 的 应 用 程 序 时 , 这 个 宏 恢 复 原 来 的 指 针 。AFX_MANAGE_STATE 宏 在 由 MFC 库 文 件 自 己 调 用 的 输 出 函 数 中 并 不 是 必 不可 少 的 , 例 如 , 在 消 息 映 像 中 列 出 的 InitInstance 和 句 柄 函 数 , 这 是 因 为 MFC 在调 用 函 数 之 前 已 经 正 确 设 置 好 了 模 块 状 态 。
AFX_MANAGE_STATE 宏 应 该 放 在 函 数 的 开 头 附 近 , 甚 至 要 在 对 象 变 量 定 义 之前 , 因 为 它 们 的 构 造 器 本 身 可 能 就 包 括 对 MFC 库 文 件 的 调 用 。程 序 段 中 的 #ifdef 条 件 块 保 证 编 译 器 只 为 动 态 链 接 到 MFC 的 库 文 件 包 含 宏 代 码 。 如 果 链 接 是 静 态
的 , Visual C++ 编 译 器 没 有 预 定 义 _AFXDLL 常 量 。 要 更 详 细 地 了 解AFX_MANAGE_STATE 宏 ,请 参 考 Technical Note 58 ,MSDN 在 线 帮 助 中 的“ MFC Module State Implementation ” 。
第 二 部 分 编 辑 器
第 3 章 文 本 编 辑 器
Visual C++ 提 供 了 一 个 专 门 为 “ 代 码 剪 切 ” 而 设 计 的 文 本 编 辑 器 。 这 个 编 辑 器 与各 种 环 境 工 具( 诸 如 调 试 器 )组 成 一 个 完 整 的 统 一 体 ,并 提 供 了 大 量 复 杂 的 特 征 , 包 括 Undo/Redo ( 撤 销 /重 做 )、 可 定 制 的 快 捷 键 命 令 和 对 W in32 和 MFC 参 考 的快 速 访 问 。
作 为 一 个 程 序 员 , 你 一 定 已 用 过 了 一 种 或 几 种 编 辑 器 。 本 章 将 介 绍 Visual C++ 文本 编 辑 器 最 重 要 的 几 个 方 面 ,讲 述 一 些 有 用 的 和 隐 含 的 特 性 ,并 展 示 怎 样 有 效 地使 用 编 辑 器 。即 使 你 仍 愿 使 用 现 有 的 编 辑 器 来 完 成 大 多 数 编 码 任 务 ,也 应 浏 览 一下 本 章 , 以 便 了 解 Visual C++ 的 强 大 功 能 。 不 久 你 将 发 现 , 如 果 只 想 修 改 编 译 器错 误 , 那 么 , 在 编 辑 文 本 时 , 将 文 本 保 持 在 Developer Studio 环 境 中 将 是 很 方 便的 。 在 本 章 的 最 后 , 还 有 一 些 有 用 的 建 议 。
由 于 Visual C++ 是 一 个 基 于 W indows 的 软 件 , 它 将 其 文 本 文 件 以 ANSI 格 式 存储 。 有 关 ANSI 标 准 和 ASCII 及 ANSI 码 表 , 请 参 考 附 录 A 。
启 动 文 本 编 辑 器
刚 进 入 Visual C++ 时 ,看 不 到 文 本 编 辑 器 ,也 不 会 在 任 何 菜 单 下 看 到“ Start the text edito r( 启 动 文 本 编 辑 器 )”或 “ edito r( 编 辑 器 )” 之 类 的 选 项 。 在 Visual C++ 通向 对 象 的 环 境 中 , 只 需 给 出 文 件 类 型 , 而 不 必 管 应 该 使 用 哪 一 个 工 具 。 在 这 个 环境 中 , 除 了 文 本 编 辑 器 , 还 有 其 他 几 个 编 辑 器 。 只 需 指 出 想 创 建 或 修 改 的 是 一 个文 本 文 件 , 而 不 是 其 他 类 型( 比 如 说 , 图 表 文 件 ), Visual C++ 将 会 根 据 文 件 类 型自 动 启 动 相 应 的 编 辑 器 。
进 入 编 辑 器 后 , 如 果 想 创 建 一 个 新 文 件 , 请 单 击 File( 文 件 ) 菜 单 , 再 选 择 New
( 新 建 )。 在 如 图 3-1 所 示 的 New 对 话 框 中 , Visual C++ 按 字 母 顺 序 列 出 可 以 创建 的 文 件 类 型 。
图 3-1 在 New 对 话 框 中 选 择 文 档 类 型
输 入 文 件 名 , 然 后 在 列 表 中 选 定 其 类 型 , 如 Active Server Page、 C/C++ Header File 、 C++Source File 、 HTML Page 、 Macro File 、 SQL Script File 或 Text File 。再单 击 O K( 确 定 ) 就 会 发 现 ,文 本 编 辑 器 以 一 个 空 文 档 窗 口 的 形 式 出 现 在 屏 幕 上 。此 时 菜 单 和 工 具 栏 都 基 本 不 变 ,但 会 有 一 声 短 促 的 喇 叭 声 。为 了 保 持 工 作 的 连 续性 , Visual C++ 采 用 通 用 的 外 观 和 动 作 , 以 便 使 软 件 易 学 易 用 。 例 如 , 如 果 新 文档 满 屏 显 示 , 那 么 , 除 了 文 档 本 身 外 , 只 有 很 少 的 几 条 可 视 线 索 能 表 明 此 时 是 在文 本 编 辑 器 中 , 而 不 是 在 Visual C++ 的 主 窗 口 中 。 其 中 之 一 是 在 菜 单 栏 的 左 边 缘有 一 个 小 页 标 ; 另 一 个 是 在 主 窗 口 顶 部 标 题 栏 中 有 文 档 名 称 ,它 指 出 了 文 档 的 类型 。 如 果 在 New ( 新 建 ) 对 话 框 中 没 有 给 出 文 档 名 称 , 编 辑 器 将 自 动 给 此 新 文 档赋 一 个 临 时 名 称 , 像 Text1 或 Cpp1 , 直 到 给 文 档 赋 了 新 名 称 为 止 。
在 本 章 后 面 会 看 到 , Visual C++ 的 菜 单 在 各 种 编 辑 器 中 是 通 用 的 。 虽 然 表 面 的 菜单 和 工 具 栏 基 本 不 变 , 但 在 内 部 会 有 一 些 变 化 。 例 如 , 在 使 用 文 本 编 辑 器 时 , 许多 在 主 窗 口 中 呈 灰 色 的 命 令 被 激 活 ,而 变 为 正 常 体 。对 不 同 的 编 辑 器 ,Visual C++ 会 自 动 激 活 相 应 的 命 令 。 例 如 , 由 于 文 本 只 对 文 本 编 辑 器 有 效 , 因 此 , Find( 查找 ) 命 令 在 使 用 文 本 编 辑 器 时 被 激 活 , 而 呈 正 常 体 , 而 在 使 用 图 形 编 辑 器 时 , 则因 未 被 激 活 ,而 呈 灰 色 。图 3-2 中 简 要 列 出 了 使 用 文 本 编 辑 器 时 可 用 的 菜 单 命 令 。
图 3-2 文 本 编 辑 器 菜 单
除 了 上 图 中 所 列 的 命 令 外 , 还 有 一 些 命 令 是 可 用 的 。 例 如 , 如 果 在 编 辑 器 中 删 除了 文 本 , 却 又 想 恢 复 它 , 可 使 用 Edit ( 编 辑 ) 菜 单 下 的 Undo ( 撤 销 ) 和 Redo
( 重 做 ) 命 令 , Undo ( 撤 销 ) 能 记 忆 最 近 一 次 删 除 操 作 。 如 果 要 恢 复 更 早 删 除
的 文 本 , 连 续 单 击 Undo ( 撤 销 ), 或 重 复 按 Ctrl+Z 直 到 恢 复 到 需 要 的 文 本 为 止 。不 过 , 有 时 会 多 击 一 次 , 或 多 按 一 次 , 从 而 多 恢 复 了 无 用 的 文 本 , 这 时 候 , 可 以使 用 Edit ( 编 辑 ) 下 的 Redo ( 重 做 ) 命 令 来 取 消 最 近 一 次 Undo ( 撤 销 ) 操 作 。
文 档
这 一 节 是 本 章 最 长 的 一 节 , 讲 述 怎 样 创 建 、 打 开 、 浏 览 、 存 储 和 打 印 文 本 文 档 。如 序 言 中 提 到 的 那 样 , 如 果 已 使 用 过 基 于 W indows 的 文 本 编 辑 器 或 字 处 理 器 , 那 么 本 节 所 讲 的 一 些 知 识 只 是 对 已 有 知 识 的 复 习 。 但 是 , 即 使 对 于 有 经 验 的W indows 用 户 , 在 它 们 了 解 了 Visual C++ 的 细 节 后 , 它 们 仍 能 在 浏 览 和 打 印 文 档方 面 获 益 。
打 开 文 档
Visual C++ 文 本 编 辑 器 支 持 多 文 档 操 作 ,所 以 可 以 同 时 打 开 多 个 文 档 。再 使 用 New
( 新 建 )命 令 ,就 可 以 创 建 另 一 个 新 文 档 ,系 统 自 动 默 认 文 档 名 为 Text2 或 Cpp2 。如 果 是 满 屏 显 示 ,则 正 在 使 用 的 文 档 名 称 显 示 在 屏 幕 顶 端 标 题 栏 中 。可 以 通 过 按Ctrl+F6 在 已 打 开 的 文 档 间 进 行 切 换 , 也 可 通 过 从 W indow( 窗 口 ) 菜 单 中 挑 选 所需 的 文 件 的 名 称 来 实 现 切 换 。
同 一 个 文 档 只 能 创 建 一 次 。 当 将 一 个 新 文 档 存 到 盘 上 时 , 从 那 一 刻 起 , 它 将 成 为一 个 文 件 , 想 再 次 对 它 进 行 处 理 时 , 就 必 须 打 开 它 , 而 不 能 再 创 建 它 。 用 下 述 办
法 可 打 开 一 个 已 存 在 的 文 件 :
- 单 击 标 准 工 具 栏 中 的 Open ( 打 开 ) 按 钮 。
-
按 Ctrl+O 。
-
选 择 File 下 拉 菜 单 中 的 Open ( 打 开 ) 命 令 。
-
选 择 File 下 拉 菜 单 中 的 Recent File ( 最 新 文 件 ) 命 令 ,
再 选 择 所 需 文 件
的 名 称 。
前 三 种 办 法 都 会 出 现 Ope n( 打 开 ) 对 话 框 ,在 对 话 框 中 , 可 以 通 过 浏 览 各 个 文 件 夹来 寻 找 想 要 打 开 的 文 件 。 最 后 一 种 方 法 不 需 要 对 话 框 , 系 统 自 动 列 出 最 近 编 辑 过的 文 件 列 表 , 称做 MRU 列 表 ,从 这 个 列 表 中 , 可 以 直 接 打 开 所 需 要 的 文 件 .
最 近 编 辑 的 文 件 列 表
在 默 认 情 况 下 , MRU 列 表 包 含 最 近 编 辑 过 的 四 个 文 件 , 这 四 个 文 件 并 不 只 是 文本 编 辑 器 编 辑 过 的 ,也 包 含 其 他 任 意 一 种 编 辑 器 编 辑 过 的 文 件 。拉 下 Fil e( 文 件 ) 下 拉 菜 单 ,将 鼠 标 光 标 放 在 Recent File 命 令 行 上 , 就 可 显 示 M R U 列 表 。在 表 中 挑选 文 件 名 , 就 可 在 相 应 的 编 辑 器 中 打 开 文 件 。 当 同 时 对 几 个 文 件 进 行 操 作 时 , 使用 MRU 列 表 是 很 方 便 的 。 然 而 , 你 会 发 现 , 即 使 对 于 一 个 很 小 的 软 件 项 目 , 也需 同 时 对 四 个 以 上 的 文 件 进 行 操 作 。 这 时 , M R U 列 表 就 显 得 不 够 用 了 。 幸 运 的是 ,Visual C++ 允 许 扩 展 MRU 列 表 ,以 使 它 可 容 纳 更 多 的 文 件 名 。单 击 Tool s( 工具 ) 菜 单 下 的 Option s( 选 项 ) 命 令 , 然 后 按 左 、 右 箭 头 键 选 择 Workspac e( 工 作空 间 ) 项 。 在 标 有 Recent File List Contains( 最 新 文 件 列 表 包 含 ) 的 文 本 框 中 输入 新 值 即 可 ( 如 下 图 所 示 )。
Workspace 选 项 还 提 供 了 另 一 种 影 响 M R U 列 表 外 观 的 选 项 。 如 果 希 望 M R U 列表 直 接 出 现 在 Fil e( 文 件 ) 菜 单 中 , 而 不 是 隐 藏 在 下 一 级 命 令 里 , 只 需 取 消 Show Recently Used Items On Submenus( 在 子 菜 单 上 显 示 最 近 使 用 的 项 ) 选 项 即 可 。不 过 , 由 于 文 件 名 的 增 加 , File ( 文 件 ) 菜 单 会 显 得 很 拥 挤
Open ( 打 开 ) 对 话 框
如 果 所 需 的 文 件 不 在 M R U 列 表 中 , 那 么 , 必 须 使 用 Open ( 打 开 ) 命 令 , 再 在Open ( 打 开 ) 对 话 框 确 定 文 件 。 这 个 对 话 框 中 的 默 认 路 径 是 当 前 软 件 所 在 的 文件 夹 , 因 此 不 必 花 很 大 力 气 来 寻 找 文 件 。
在 选 择 要 打 开 的 文 件 时 , 按 下 Ctrl 键 再 单 击 文 件 名 , 就 可 以 同 时 打 开 一 组 文 件 , 每 单 击 一 次 就 多 打 开 一 个 文 件 。 如 果 想 取 消 某 个 已 打 开 的 文 件 , 只 需 再 次 按 下Ctrl, 同 时 单 击 该 文 件 名 即 可 。 选 定 文 件 后 , 单 击 Open ( 打 开 ), 就 可 将 所 有 选中 的 文 件 分 别 打 开 成 不 同 的 文 档 。 如 果 想 打 开 的 文 件 在 其 目 录 下 是 连 续 排 列 的 , 那 么 , 有 一 种 更 快 的 方 法 来 选 中 它 们 。 可 先 单 击 选 中 第 一 个 文 件 , 再 按 住 Shift 单 击 最 后 一 个 文 件 , 这 样 , 在 这 两 个 文 件 间 的 所 有 文 件 都 被 选 中 了 。 如 果 想 不 要其 中 某 个 文 件 , 只 需 按 住 Ctrl 的 同 时 单 击 该 文 件 即 可 。
注 意 : 在 Open ( 打 开 ) 对 话 框 中 列 出 的 文 件 并 不 是 该 文 件 夹 下 的 所 有 文 件 , 这是 由 于 Files Of Type( 文 件 类 型 ) 组 合 框 中 有 过 滤 设 置 。“ 过 滤 ” 是 指 只 选 择 一组 相 关 的 文 件 。 例 如 , 系 统 默 认 的 C++ Files 过 滤 器 将 使 Open( 打 开 ) 对 话 框 中只 包 含 以 C 、 CPP 、 C X X 、 TL I、 H 、 TLH 、 INL 和 RC 为 扩 展 名 的 文 件 。 如 要 列出 其 他 类 型 的 文 件 ,如 以 HPP 或 TXT 为 扩 展 名 的 文 件 ,则 须 在 Files Of Typ e( 文件 类 型 ) 框 中 选 择 相 应 的 过 滤 器 。
在 Ope n( 打 开 ) 对 话 框 中 有 一 个 Open As Read-Onl y( 作 为 只 读 文 件 打 开 ) 选 项 。
这 是 一 个 很 重 要 的 选 项 , 一 旦 它 被 选 中 , 将 不 能 对 打 开 的 文 件 作 任 何 改 变 , 而 只能 对 其 浏 览 、 打 印 , 或 将 其 复 制 到 剪 贴 板 上 。 通 常 , 只 需 使 用 File( 文 件 ) 菜 单下 的 Save as ( 另 存 为 ) 命 令 , 将 此 只 读 文 档 以 一 个 新 名 称 保 存 , 就 可 以 解 除 只读 限 制 。 注 意 , 此 时 原 文 件 只 读 属 性 并 未 改 变 , 只 是 新 文 件 中 没 有 只 读 限 制 。Visual C++ 6.0 还 提 供 了 一 种 设 置 , 使 得 即 使 对 于 上 面 这 种 无 害 的 操 作 , 系 统 也不 允 许 进 行 。 Tools ( 工 具 ) 菜 单 下 Options( 选 项 ) 对 话 框 中 Compatibility ( 兼容 性 ) 选 项 卡 下 , 有 一 个 Protect Read-Only Files From Editing ( 阻 止 编 辑 只 读 文件 ) 选 项 , 当 它 被 选 中 后 , 只 读 文 件 将 不 能 以 新 名 称 另 存 。
查 看 文 档
尽 管 文 本 编 辑 器 尽 可 能 有 效 地 使 用 屏 幕 空 间 , 但 当 有 好 几 个 窗 口 同 时 显 示 时 ,空间 常 常 显 得 很 紧 张 。为 了 使 可 用 空 间 尽 可 能 大 , 选 择 Vie w( 查 看 ) 菜 单 下 的 Full Screen ( 全 屏 ) 命 令 ( 如 图 3-3 ), 或 者 按 Ctrl+V , 就 可 使 标 题 栏 、 菜 单 、 工 具栏 都 消 失 , 以 便 最 大 限 度 地 腾 出 空 间 。 如 果 要 返 回 正 常 显 示 , 只 需 按 Esc , 或 单击 浮 动 的 Full Screen ( 全 屏 ) 工 具 栏 即 可 。 在 满 屏 状 态 下 , 由 于 菜 单 栏 消 失 , 不能 再 用 鼠 标 来 单 击 下 拉 菜 单 。 如 果 要 使 用 下 拉 菜 单 , 可 先 按 A lt, 再 按 所 需 菜 单的 首 字 母 即 可 。 例 如 , 先 按 A lt, 再 按 F , 就 可 激 活 File ( 文 件 ) 菜 单 , 再 按 左 、右 箭 头 键 , 可 激 活 相 邻 的 菜 单 ( 在 这 里 , 按 A lt 起 激 活 菜 单 栏 的 作 用 , 因 此 两 个键 不 必 同 时 按 下 )。
如 果 Full Scree n( 全 屏 )工 具 栏 令 你 感 到 眼 花 缭 乱 ,单 击 此 工 具 栏 上 的 关 闭 按 钮 , 就 可 移 走 它 。 不 过 这 样 的 话 , 将 只 能 通 过 按 Esc 键 来 返 回 正 常 显 示 。 如 要 恢 复 该工 具 栏 , 按 A lt+T 显示 Tools ( 工 具 ) 菜 单 , 再 单 击 Custmize ( 自 定 义 ) 命 令 , 在 Custmize ( 自 定 义 ) 对 话 框 内 的 Toolbar( 工 具 栏 ) 选 项 卡 下 选 中 工 具 栏 列 表中 的 Full Screen ( 全 屏 )。 以 同 样 的 方 法 , 也 可 以 在 满 屏 状 态 下 显 示 其 他 工 具 栏或 菜 单 栏 。
W indow ( 窗 口 ) 菜 单 提 供 了 一 个 文 档 列 表 , 其 中 包 含 所 有 的 Visual C++ 编 辑 器打 开 的 文 件 。例如,图 3-3 中 的 文 档 表 就 包 含 了 一 个 文 本 文 件 Test.CPP 和 一 个 图表 编 辑 器 下 的 图 片 文 件 Dimo.bm p。 可 以 通 过 拉 下 W indow ( 窗 口 ) 菜 单 , 再 单击 想 处 理 的 文 档 名 ,来 实 现 各 个 文 档 间 的 切 换 。如 果 想 同 时 将 所 有 的 文 档 都 显 示在 屏 幕 上 ,可 选 择 Cascad e( 层 叠 )、Tile Horizontall y( 水 平 平 铺 )或 Tile Vertically
( 垂 直 平 铺 ) 命 令 ( 如 图 3-3 )。
图 3-3 View ( 查 看 ) 和 Window (窗口) 菜单
文 本 编 辑 器 的 文 档 窗 口 允 许 多 窗 格 显 示 ,可 以 将 同 一 文 档 的 一 个 、 两 个 或 四 个 不同 部 分 同 时 显 示 在 窗 口 上 。 图 3-4 就 是 同 一 文 档 的 四 窗 格 显 示 的 例 子 。
图 3-4 典 型 的 文 档 窗 口 分 为 四 个 窗 格
由 于 Visual C++ 使用 MFC 的 CSplitterWnd 类 创 建 每 一 个 文 本 窗 口 , 所 以 , 当 创建 或 打 开 一 个 文 档 时 , 多 窗 格 功 能 自 动 生 效 。 窗 格 分 隔 条 最 初 显 示 为 两 个 按 钮 , 一 个 位 于 垂 直 滚 动 条 的 顶 端 ,另 一 个 位 于 水 平 滚 动 条 的 最 左 端 。要 想 设 定 某 个 窗格 分 隔 条 的 位 置 ,只 需 拖 动 该 窗 格 分 隔 条 到 所 需 位 置 再 释 放 即 可 。 也 可 以 通 过 选择 Window ( 窗 口 ) 菜 单 下 的 Split( 分 隔 ) 命 令 , 来 一 次 设 定 两 个 窗 格 分 隔 条 的位 置 。 Split( 分 隔 ) 命 令 设 定 了 两 个 窗 格 分 隔 条 所 决 定 的 分 割 线 在 编 辑 窗 口 中 交
点 的 位 置 , 移 动 鼠 标 , 将 此 交 点 移 到 所 需 位 置 上 , 再 单 击 , 即 可 将 两 个 窗 格 分 隔条 同 时 设 定 。
由 于 各 窗 格 没 有 自 己 的 滚 动 条 ,因 此 ,最 有 效 的 方 法 是 将 显 示 窗 口 划 分 为 一 上 一下 两 个 窗 格 。 要 想 做 此 划 分 , 只 需 要 将 垂 直 分 隔 条( 即 位 于 水 平 滚 动 条 上 的 分 隔条 ) 移 到 最 左 端 或 最 右 端 , 直 到 其 消 失 为 止 。 通 过 单 击 窗 格 或 按 F6 , 可 从 一 个窗 格 切 换 到 另 一 窗 格 。
上 面 的 两 窗 格 显 示 对 于 上 下 划 分 的 文 档 非 常 方 便 , 但 由 于 各 窗 格 不 能 独 立 滚 动 , 因 此 对 于 左 右 划 分 的 文 档 就 不 大 有 效 了 。 幸 运 的 是 , W indow ( 窗 口 ) 菜 单 提 供了 另 一 个 命 令 , 它 可 以 垂 直 视 图 的 方 式 显 示 将 一 个 文 档 分 成 两 个 或 多 个 窗 格 。在文 本 编 辑 器 只 打 开 一 个 文 档 的 情 况 下 , 单 击 New Window ( 新 窗 口 ) 命 令 , 就 会打 开 另 一 个 包 含 同 一 文 档 的 显 示 窗 口 。这 并 不 是 重 新 打 开 文 件 , 而 不 过 是 在 编 辑器 的 工 作 空 间 中 提 供 了 原 文 档 的 第 二 个 视 图 。这 两 个 视 图 各 有 其 滚 动 条 及 闪 烁 光标 , 所 以 可 以 同 时 浏 览 文 档 的 不 同 部 分 。 此 时 , 再 单 击 Window ( 窗 口 ) 菜 单 下的 Tile Vertically( 垂 直 平 铺 ) 命 令 , 就 可 使 两 个 浏 览 器 实 现 左 右 显 示 。 通 过 单 击某 个 窗 口 , 或 按 F6 键 , 可 实 现 视 图 之 间 的 切 换 。
也 可 以 通 过 New Window ( 新 窗 口 ) 命 令 再 增 加 视 图 。 不 过 , 尽 管 各 视 图 之 间相 互 独 立 , 但 它 们 都 只 能 显 示 同 一 文 档 的 内 容 , 因 此 , 在 一 个 视 图 中 对 文 档 做 的任 何 修 改 , 都 会 立 即 显 示 在 其 他 视 图 中 。
保 存 文 档
当 开 始 在 一 个 文 档 窗 口 中 输 入 文 本 时 ,一个“ * ” 符 号 会 显 示 在 标 题 栏 和 W indow
( 窗 口 ) 菜 单 下 已 打 开 文 档 表 中 的 文 档 名 后 。 这 表 明 此 时 该 文 档 已 被 改 变 , 它 和原 文 件 已 不 相 同 。与 文 字 处 理 器 不 同 的 是 ,Visual C++ 文 本 编 辑 器 不 能 自 动 存 盘 , 因 此 , 在 输 入 源 代 码 时 , 一 定 要 养 成 定 时 存 盘 的 习 惯 。 存 盘 可 用 以 下 方 法 :
- 单 击 标 准 工 具 栏 上 的 Save 按 钮 。
-
按 Ctrl+S 。
-
选 择 File ( 文 件 ) 菜 单 下 的 Save ( 保 存 ) 命 令 。
保 存 文 件 时 , 文 件 名 后 的 “ * ” 符 号 将 消 失 。 当 再 次 改 变 文 本 时 , 它 又 将 出 现 。当 “ * ” 符 号 存 在 时 , 编 辑 器 会 提 示 先 存 盘 。
定 时 存 盘 主 要 是 针 对 长 时 间 编 辑 一 个 文 档 的 场 合 。 在 这 种 情 况 下 , 在 处 理 文 档时 , 偶 尔 问 一 下 自 己 ,“ 如 果 突 然 停 电 , 我 会 不 会 因 没 存 盘 而 很 后 悔 ? ”。如果答案 是 肯 定 的 , 就 请 按 Ctrl+S。 如 果 只 是 对 源 文 件 作 一 些 小 改 动 , 再 重 新 编 译 它 , 那 么 存 盘 就 不 那 么 重 要 了 , 因 为 在 重 新 编 译 之 前 , 系 统 会 自 动 保 存 文 档 。
第 一 次 保 存 一 个 未 命 名 的 文 档 时 , 会 出 现 Save as ( 另 存 为 ) 对 话 框 , 在 这 个 对话 框 里 , 你 可 给 出 文 件 名 及 其 扩 展 名 。 请 将 扩 展 名 定 为 CPP 或 C , 因 为 文 本 编辑 器 只 能 通 过 扩 展 名 判 断 文 件 内 容 , 再 依 内 容 将 其 按 C++ 或 C 程 序 编 译 。 如 果不 给 出 扩 展 名 , Visual C++ 将 自 动 设 一 个 与 在 New ( 新 建 ) 对 话 框 ( 图 3-1 ) 中选 择 的 文 件 类 型 相 近 的 扩 展 名 。 例 如 , 如 果 从 此 对 话 框 中 选 择 C++ Source File
( C++ 源 文 件 ), 则 新 文 件 名 的 扩 展 名 将 为 CPP 。
许 多 程 序 员 常 将 C++ 头 文 件 的 后 缀 名 置 为 HPP , 在 使 用 Visual C++ 时 ,这 会 带 来一 点 小 麻 烦 。 当 选 择 Open ( 打 开 ) 命 令 时 , 对 话 框 中 通 常 只 显 示 以 C 、 CPP 、C X X 、TL I、H 、TLH 、INL 、RC 等 为 扩 展 名 的 文 件 。要 想 打 开 一 个 扩 展 名 为 HPP 的 文 件 , 必 须 将 对 话 框 下 部 的 文 件 类 型 改 为 C++ Include File( C++ 包 括 文 件 ) 或A ll Files( 所 有 文 件 )。 除 此 之 外 , 使 用 HPP 作 为 头 文 件 的 扩 展 名 再 不 会 有 别 的麻 烦 。实 际 上 ,对 于 头 文 件 可 以 使 用 任 何 扩 展 名 ,因 为 在 创 建 项 目 时 ,Visual C++ 只 根 据“ #include” 语 句 来 搜 索 源 文 件 。 无 论 扩 展 名 是 什 么 , 只 要 被 #include 语 句
包 含 , 它 就 会 自 动 加 入 到 项 目 中 , 并 显 示 在 Workspace ( 工 作 空 间 ) 窗 口 中 的
FileView ( 文 件 视 图 ) 选 项 卡 下 的 头 文 件 表 中 。
当 保 存 一 个 新 文 档 , 并 给 定 其 文 件 名 时 , 这 个 文 件 名 就 代 替 系 统 默 认 的 文 件 名 , 并 显 示 在 标 题 栏 和 W indow ( 窗 口 ) 菜 单 下 。 从 此 , 当 再 保 存 此 文 件 时 , 系 统 将自 动 覆 盖 前 一 个 版 本 , 并 不 再 显 示 Save as ( 另 存 为 ) 对 话 框 。 而 且 , 系 统 也 不会 以 任 何 形 式 保 存 前 一 个 版 本 。 因 此 , 一 旦 保 存 了 一 个 文 档 , 则 它 从 前 的 版 本 将不 复 存 在 。 如 果 源 文 件 需 要 多 个 版 本 , 则 必 须 通 过 File( 文 件 ) 菜 单 下 的 Save as
( 另 存 为 ) 命 令 来 给 不 同 版 本 赋 予 不 同 名 称 。
打 印 文 档
要 打 印 一 个 正 在 编 辑 的 文 档 ,只需单击 Fil e( 文 件 )菜单下的 Prin t( 打 印 ) 命 令 , 或 按 Ctrl+P , 来 打 开 Prin t( 打 印 ) 对 话 框 。 如 果 只 想 打 印 该 文 档 中 的 一 部 分 , 先选 择 要 打 印 的 部 分 , 再 启 用 Prin t( 打 印 ) 对 话 框 中 的 Selectio n( 选 择 ) 单 选 按 钮
( 如 图 3-5 )。
图 3-5 Prin t( 打 印 ) 对 话 框
Selectio n( 选 择 ) 单 选 按 钮 设 定 系 统 只 打 印 用 户 选 中 的 部 分 。 如 要 取 消 它 ,只 需 单击 图 中 的 All( 所 有 ) 单 选 按 钮 即 可 。
上 图 所 示 的 对 话 框 也 给 出 了 W indows 将 使 用 的 打 印 机 。 如 要 选 择 其 他 打 印 机 , 单 击 Printer( 打 印 机 ) 下 拉 框 , 并 从 其 列 表 中 选 择 打 印 机 类 型 。 再 单 击 O K ( 确定 ) 就 可 开 始 打 印 。 使 用 后 台 打 印 时 , 系 统 会 立 即 返 回 文 本 编 辑 器 , 使 你 可 以 继续 工 作 。 尽 管 控 制 打 印 过 程 时 需 要 浏 览 Print 文 件 夹 , 但 还 是 可 以 迅 速 打 印 数 个
文 档 。单 击 任 务 栏 中 的 Sta r(t 启 动 )按 钮 ,再 选 择 Settin g( 设 置 ),然 后 单 击 Printers
( 打 印 机 ), 选 定 打 印 机 后 再 单 击 File ( 文 件 ) 菜 单 下 的 Open ( 打 开 ) 命 令 , 就可 看 到 当 前 正 在 打 印 的 文 件 列 表 。
当 使 用 后 台 打 印 时 , 取 消 某 个 打 印 任 务 会 稍 微 麻 烦 一 些 。 一 旦 后 台 打 印 开 始 进行 , Cance l( 取 消 ) 按 钮 将 从 屏 幕 上 消 失 , 因 此 , 只 能 通 过 Printer 文 件 夹 来 取 消打 印 任 务 。 另 外 , 如 果 后 台 打 印 不 能 用 , 那 么 , 文 本 编 辑 器 只 能 等 待 打 印 完 成 后才 能 被 用 户 使 用 。
Visual C++ 文 本 编 辑 器 为 其 打 印 的 文 本 提 供 了 有 限 格 式 , 可 以 设 置 页 边 距 , 并 指定 每 页 的 页 眉 和 页 脚 。 从 File( 文 件 ) 菜 单 下 选 择 Page Setu p( 页 面 设 置 ) 命 令 , 在 Page Setup( 页 面 设 置 ) 对 话 框 下 将 所 要 的 页 眉 和 页 脚 文 本 分 别 输 入 到 对 应 的文 本 框 中 。 可 使 用 表 3-1 中 的 代 码 在 页 眉 和 页 脚 文 本 中 加 入 某 些 实 时 信 息 。
表 3-1 在 页 眉 |
和 页 脚 中 添 加 信 息 的 打 印 代 码 |
|
---|---|---|
代 码 |
意 义 |
|
& F |
文 件 名 称 |
|
& P &T |
当 前 页 数 系 统 时 间 |
|
& D &L |
系 统 日 期 页 眉 和 页 脚 与 文 本 左 边 缘 对 齐 |
|
& C |
页 眉 和 页 脚 与 文 本 中 心 对 齐 |
|
& R |
页 眉 和 页 脚 与 文 本 右 边 缘 对 齐 |
这 些 代 码 并 不 需 要 去 记 , 只 需 单 击 Page Setup( 页 面 设 置 ) 对 话 框 中 文 本 框 旁 边的 箭 头 , 即 可 显 示 格 式 选 项 列 表 。 单 击 其 中 某 选 项 , 就 可 将 它 插 入 到 页 眉 或 页 脚中 。 打 印 代 码 就 在 此 列 表 的 最 上 端 或 最 下 端 。
可 将 打 印 代 码 与 正 常 文 本 以 任 意 方 式 组 合 。例 如 ,一 个 指 明 文 件 名 称 和 打 印 日 期的 页 眉 可 做 如 下 安 排 :
&RFile: &F; Date: &Dpage & p
这 里 ,& R 代 码 使 得 页 眉 与 右 边 缘 对 齐 ,这 和 字 处 理 器 中 的 右 对 齐 是 一 样 的 。 & P 代 码 打 印 页 数 , 从 “ 1 ” 开 始 。 这 里 的 页 数 与 打 印 作 业 相 关 , 而 不 是 与 原 文 档 相关 。 也 就 是 说 , 如 果 选 择 文 档 的 中 间 部 分 打 印 , & p 代 码 仍 将 被 打 印 的 第 一 页 的页 数 定 为 “ 1 ”。 Visual C++ 中 没 有 代 码 可 显 示 总 页 数 , 也 就 是 说 , 不 可 能 以 类 似于“ Page 1 of 20 ” 的 形 式 来 显 示 页 数 。 另 外 , 由 于 页 眉 和 页 脚 中 的 打 印 代 码 在 整个 打 印 过 程 中 都 起 作 用 , 因 此 , 不 存 在 那 种 可 交 替 使 用 左 对 齐 与 右 对 齐 , 以 便 设定 奇 数 页 为 “ &R " , 而 偶 数 页 为 “ &L" 的 选 项 。
页 眉 和 页 脚 中 每 行 不 能 超 过 40 个 字 符 。 每 个 打 印 代 码 算 两 个 字 符 。 Tab 键 不 允许 使 用 。
浏 览 文 档
当 然 , 通 过 按 上 下 左 、 右 箭 头 键 或 拉 动 滚 动 条 , 可 以 浏 览 文 档 。 可 是 , 在 下 面 将可 以 看 到 , 通 过 一 些 其 他 办 法 可 更 方 便 、 更 有 效 地 浏 览 文 档 。 在 此 之 前 , 先 让 我们 统 一 一 些 术 语 。 在 DOS 模 式 文 本 编 辑 器 中 很 熟 悉 的 光 标 , 在 Windows 中 有 不
同 的 名 称 。Windows 把 闪 烁 光 标 称 为 提 示 符 ,因 为 它 的 功 能 与 用 来 表 示 可 输 入 新文 本 的 ^ 符 号 相 似 。 光 标 一 词 在 W indows 中 仍 被 保 留 , 它 被 用 来 指 代 表 示 鼠 标位 置 的 箭 头 ( 或 其 他 标 志 )。 Visual C++ 的 在 线 帮 助 称 插 入 符 为 “ 插 入 点 ”, 作 为一 个 W indows 程 序 员 , 应 该 知 道 光 标 与 提 示 符 之 间 的 区 别 。 这 样 , 当 进 入 API 函 数 ( 例 如 ShowCaret 和 SetCaretPos ) 时 , 就 不 会 感 到 迷 惑 了 。
在 文 本 编 辑 器 中 移 动 提 示 符 的 快 捷 键 , 对 于 任 何 一 个 使 用 过 W indows 字 处 理 器的 用 户 来 说 , 都 是 很 熟 悉 的 。 表 3-2 列 出 了 主 要 的 提 示 符 移 动 快 捷 键 。
表 3-2 文 本 编 辑 器 插 入 符 移 动 键
敲 键 插 入 符 移 动
左 箭 头 , 右 箭 头 向 前 或 向 后 移 动 一 个 字 符 。 如 果 提 示 符 在 最 左
端 , 则 左 移 将 移 到 前 一 行 的 末 尾 ; 如 果 提 示 符 在右 端 , 则 右 移 将 移 到 下 一 行 的 开 头
上 箭 头 , 下 箭 头 向 上 或 向 下 一 行 。 如 果 目 标 行 比 当 前 行 短 , 则 移
动 后 提 示 符 的 位 置 取 决 于 提 示 符 现 在 的 具 体 位 置
Ctrl+ 左 箭 头 , Ctrl+
右 箭 头
向 前 或 向 后 移 动 一 个 单 词 。 Visual C++ 编 辑 器 将很 多 标 点 符 号 按 独 立 单 词 对 待 。 例 如 , 必 须 按 7 次 Ctrl+ 右 箭 头 , 才 能 移 过 “ CAN'T/WON'T ”
Hom e, End 移 到 一 行 的 开 头 或 末 尾
Ctrl+Home ,
Ctrl+End
移 到 文 档 的 开 头 或 末 尾
续 表
Page U p ,Page Down 按 照 窗 口 中 显 示 的 行 数 来 上 下 滚 动 文 档 。 这 里 ,
编 辑 器 将 重 叠 滚 动 一 行 , 也 就 是 说 , 当 按 下PageDown 键 时 , 当 前 屏 幕 最 底 部 的 一 行 将 变 成下 一 屏 的 最 顶 行 。 这 个 滚 动 间 距 是 不 能 改 变 的
在 空 白 区 内 移 动
当 把 插 入 符 移 到 一 行 的 末 尾 时 , 文 本 编 辑 器 下 面 再 怎 样 动 作 没 有 一 个 统 一 的 规则 。 有 些 编 辑 器 将 不 进 行 任 何 操 作 。 另 有 一 些 编 辑 器 将 文 本 看 作 连 续 的 流 , 当 在行 尾 按 右 箭 头 键 时 , 插 入 符 会 移 到 下 一 行 的 开 头 。 如 果 长 时 间 右 箭 头 键 不 放 , 甚至 可 将 插 入 符 一 直 移 到 文 档 末 尾 。还 有 一 些 编 辑 器 允 许 插 入 符 继 续 向 右 进 入 空 白区 。 这 种 方 式 的 好 处 是 , 它 使 屏 幕 就 像 一 页 纸 , 你 可 以 任 意 移 动 插 入 符 , 并 可 在任 何 地 方 输 入 。 但 同 时 它 也 有 一 些 缺 点 。
想 一 想 , 当 插 入 符 位 于 下 例 中 第 一 行 的 末 尾 时 , 想 将 它 移 到 下 一 行 , 会 出 现 什 么情 况 :
b = SendMessgae( hwnd , MY_MESSAGE , wParam , 1Param); b *=2;
如 果 没 有 空 白 区 , 按 右 箭 头 键 就 可 很 快 移 到 第 二 行 开 头 , 按 向 下 箭 头 键 , 可 移 到第 二 行 的 结 尾 。 而 对 于 有 空 白 区 的 编 辑 器 , 则 需 要 按 两 次 键 。 必 须 先 按 向 下 箭 头键 , 再 按 End 或 Home 键 。 然 而 , 在 另 一 方 面 , 有 空 白 区 的 编 辑 器 又 可 以 很 方 便地 给 第 二 行 加 一 个 注 释 。 只 需 把 插 入 符 向 下 移 动 到 空 白 区 即 可 :
b =SendMessage (hwnd, MY_MESSAGE, WParam, 1Param); b*=2; // Double it
顺 便 说 一 下 , Visual C++ 之 外 的 编 辑 器 大 都 将 文 档 看 作 文 本 流 。 这 样 , 在 文 档 中
就 不 能 留 有 间 隙 。 在 原 文 档 与 在 空 白 区 加 入 的 文 档 之 间 的 间 隙 中 , Visual C++ 编辑 器 用 尽 可 能 多 的 TAB 键 和 空 格 键 填 充 。
上 面 两 种 体 系 都 有 其 麻 烦 之 处 。 为 了 使 操 作 方 便 , Visual C++ 文 本 编 辑 器 将 选 择权 交 给 了 你 , 可 按 以 下 步 骤 将 空 白 区 设 置 改 为 自 己 所 喜 好 的 类 型 :
-
选 Tools( 工 具 ) 菜 单 下 Options( 选 项 ) 命 令 。
-
单 击 Compatibility ( 兼 容 性 ) 选 项 卡 。
-
设 置 或 清 除 Enable Virtual Space ( 启 用 空 白 区 ) 文 本 框 中
的 值 。
括 号 匹 配
Visual C++ 文 本 编 辑 器 可 识 别 包 围 C/C++ 源 代 码 块 的 括 号 对 ,这 样 ,只 按 一 次 键 , 就 可 将 插 入 符 由 一 个 括 号 处 移 到 与 此 括 号 相 对 应 的 括 号 处 。编 辑 器 可 区 别 三 种 不同 类 型 的 括 号 : 小 括 号 ( ), 大 括 号 {} , 方 括 号 []。
括 号 通 常 成 对 使 用 , 用 于 源 代 码 块 的 两 端 。 每 一 对 括 号 建 立 一 个 层 次 , 并 可 能 包含 若 干 个 次 级 层 。 下 例 就 是 一 个 用 大 括 号 来 分 层 次 的 典 型 例 子 :
if (msg=WM_USER)
{ //Begin level A
for(i=0;i<5;i++)
{ //Begin level B
.
.
.
} //End level B
} //End level A
当 光 标 在 任 何 一 个 括 号 旁 边 时 , 按 Ctrl+ ]可 将 插 入 符 移 到 与 之 对 应 的 另 一 个 括 号处 。 按 Shift+Ctrl+ ]可 选 定 两 括 号 间 所 有 文 本 。
C 和 C++ 中 的 小 括 号 用 来 含 纳 不 同 的 代 码 元 素 。然 而 , 被 小 括 号 定 义 的 层 次 不 依赖 于 语 句 类 型 , 而 依 赖 于 这 些 层 次 在 文 档 中 的 角 色 。 下 面 这 个 例 子 就 举 出 了 A 、B 、 C 三 个 层 次 的 例 子 :
这 里 , 最 里 面 的 两 对 括 号 层 次 相 同 , 都 是 C 层 , 并 且 都 包 含 在 A 层 与 B 层 内 。当 插 入 符 位 于 第 一 个 括 号 旁 时 , 由 于 它 代 表 A 层 的 开 始 , 因 此 , 按 Ctrl+ ], 可 将插 入 符 移 到 代 表 A 层 结 尾 的 最 后 一 个 括 号 处 。
编 辑 器 通 过 使 用 一 个 小 程 序 计 算 源 代 码 中 括 号 的 个 数 ,从 而 确 定 每 个 括 号 属 于 那一 层 。 任 何 一 个 完 整 层 次 中 左 右 括 号 个 数 必 须 相 等 , 否 则 就 说 明 有 错 误 。 在 把 插入 符 从 第 一 个 括 号 处 移 到 A 层 末 尾 的 过 程 中 , 编 辑 器 向 前 搜 索 匹 配 括 号 , 并 启动 记 数 器 。 每 发 现 一 个 左 括 号 计 数 器 加 一 , 每 发 现 一 个 右 括 号 计 数 器 减 一 , 直 到
编 辑 器 发 现 层 尾 的 括 号 时 计 数 器 又 变 为 0 ,于 是 ,编 辑 器 移 动 插 入 符 到 此 括 号 处 。
编 辑 器 也 把 #if , #ifdef, #else , #elif 和 #endif 这 些 条 件 编 辑 指 令 按 括 号 对 待 , 不过 , 相 应 的 操 作 键 是 不 同 的 。 当 插 入 符 位 于 某 个 条 件 指 令 旁 边 时 , 按 Ctrl+J 可 将它 移 到 下 一 个 指 令 旁 。 如 果 同 时 按 下 Shift 键 , 则 会 在 移 动 的 同 时 选 中 这 一 区 间的 文 本 。
书 签
文 本 编 辑 器 的 书 签 可 以 记 忆 一 个 位 置 , 这 样 , 无 论 在 文 档 的 任 何 位 置 , 都 可 以 迅速 返 回 书 签 所 在 位 置 。 如 果 以 前 是 利 用 Go To 命 令 来 跳 到 想 浏 览 的 位 置 , 那 么 , 现 在 一 定 会 发 现 书 签 的 好 处 。 Go To 命 令 是 以 行 数 为 目 标 的 , 若 在 文 档 的 某 些 地方 增 加 或 删 减 了 若 干 行 , 则 其 后 的 每 一 行 都 将 向 后 或 向 前 偏 离 其 原 始 位 置 。 因此 , 当 有 行 加 入 或 删 除 时 , GoTo 命 令 不 能 准 确 到 达 想 去 的 位 置 。 而 书 签 就 方 便多 了 ,你 不 必 去 记 行 数 ,书 签 会 自 动 保 留 在 所 在 行 ,并 随 文 档 的 增 减 而 改 变 位 置 。Visual C++ 文 本 编 辑 器 提 供 了 两 种 类 型 的 书 签 : 有 名 书 签 和 无 名 书 签 。
有 名 书 签
- 个 命 名 的 书 签 将 会 长 久 留 在 文 档 中 ,直 到 删 掉 它 为 止
。 它 在 文 本 中 标 志 了 一 个精 确 的 位 置 。 实 际 上 , 当 一 个 有 书 签 的 文 档 没 有 打 开 时 , 也 可 以 从 另 一 个 已 打 开的 文 档 中 直 接 跳 到 该 文 档 中 。 这 里 , 编 辑 器 自 动 打 开 该 文 档 , 并 将 插 入 符 置 于 书
签 所 在 的 位 置 。
要 创 建 一 个 有 名 书 签 , 先 将 插 入 符 置 于 所 想 标 志 的 位 置 , 再 单 击 Edi t( 编 辑 ) 菜单 下 的 Bookmarks ( 书 签 ) 命 令 , 此 时 就 会 看 到 Bookmark ( 书 签 ) 对 话 框 。 输入 给 此 书 签 所 起 的 名 字 ,再 单 击 Ad d( 添 加 )按 钮 ,就 可 将 此 书 签 加 入 到 列 表 中 。当 关 闭 对 话 框 后 , 此 新 书 签 就 开 始 起 作 用 了 。 有 两 种 方 式 可 返 回 书 签 处 : 直 接 方式 和 间 接 方 式 。 如 果 文 档 中 的 书 签 不 很 多 时 , 用 间 接 方 式 是 最 方 便 的 。 只 需 按F2 就 可 跳 到 下 一 个 书 签 处 , 按 Shift+F2 可 跳 到 前 一 个 书 签 处 。 单 击 Edit( 编 辑 ) 工
具 栏 中 的 Next Bookmark ( 下 一 个 书 签 ) 按 钮 , 也 会 得 到 同 样 的 结 果 , 如 下 图 所示 :
通 过 直 接 方 式 移 动 插 入 符 到 书 签 处 , 需 要 再 次 访 问 Boodmark ( 书 签 ) 对 话 框 。双 击 书 签 名 , 或 选 择 目 标 书 签 , 再 单 击 GoT o( 转 到 ) 按 钮 即 可 。也可以通过 Edit
( 编 辑 ) 菜 单 下 的 GoTo ( 转 到 ) 命 令 来 跳 到 某 个 有 名 书 签 处 。
具 体 来 说 , 有 名 书 签 是 一 个 32 位 量 , 用 以 记 录 文 本 中 一 个 特 定 位 置 。 当 在 书 签前 的 文 本 中 添 加 或 删 除 一 个 字 节 时 , 这 个 量 会 相 应 增 加 或 减 小 。 这 样 , 书 签 就 会继 续 指 向 其 目 标 , 文 本 怎 样 变 更 都 不 会 影 响 它 。 与 字 处 理 器 不 同 的 是 , 关 闭 文 档后 , Visual C++ 编 辑 器 不 将 有 名 书 签 保 留 在 文 档 中 , 因 为 额 外 字 符 会 使 编 辑 器 产生 混 乱 。
无 名 书 签
通 常 , 上 面 使 用 书 签 的 方 式 似 乎 有 些 大 材 小 用 。 当 想 定 义 这 样 一 个 书 签 时 , 它 标
志 源 代 码 的 一 处 地 方 , 在 编 辑 文 档 的 其 他 部 分 时 , 只 想 返 回 这 个 地 方 一 两 次 , 然后 它 就 没 用 了 , 在 这 种 情 况 下 , 有 名 书 签 就 不 是 很 方 便 了 。 此 时 , 为 方 便 起 见 , 可 使 用 一 个 无 名 书 签 。无 名 书 签 是 暂 时 的 ,当 取 消 它 或 关 闭 文 档 后 ,它 就 消 失 了 。而 且 , 无 名 书 签 只 标 志 一 行 , 而 不 是 一 个 精 确 位 置 。 当 插 入 符 跳 到 一 个 无 名 书 签处 时 , 插 入 符 自 动 置 于 该 行 开 头 。 如 果 删 除 被 标 志 的 行 , 则 书 签 也 将 被 删 除 。
无 名 书 签 的 好 处 是 , 它 易 于 设 置 , 删 除 更 简 便 。 要 使 用 一 个 无 名 书 签 , 只 需 将 插入 符 置 于 该 行 , 按 Ctrl+F2 , 或 单 击 标 有 旗 帜 的 按 钮 ( 如 图 示 ) 即 可 。
如 果 页 边 选 择( 本 章 后 面 部 分 将 会 描 述 ) 被 激 活 , 那 么 , 一 个 小 盒 子 图 标 就 会 显示 在 被 标 志 行 左 边 的 页 边 处 。 否 则 , 编 辑 器 将 以 不 同 颜 色 来 显 示 整 个 被 标 志 行 。
可 通 过 单 击 工 具 栏 按 钮 , 或 按 F2/Shift+F2 , 来 移 动 插 入 符 到 无 名 书 签 处 。每 按 一
次 , 插 入 符 将 向 前 或 向 后 移 到 下 一 个 书 签 处 , 无 论 该 书 签 是 有 名 书 签 , 还 是 无 名书 签 。
有 以 下 几 种 方 法 可 删 除 无 名 书 签 :
-
将 插 入 符 移 到 此 行 , 再 按 Ctrl+F2 即 可 删 除 此 书 签 。
-
按 Shift+Ctrl+F2 。 这 将 删 除 所 有 无 名 书 签 。
-
不 去 理 它 。 当 文 档 关 闭 后 , 无 名 书 签 将 自 动 消 失 。
文 本 搜 索
Visual C++ 编 辑 器 提 供 了 三 种 文 本 搜 索 类 型 。 可 以 :
-
在 已 打 开 的 文 档 中 搜 索 文 本 。
-
在 已 打 开 的 文 档 中 替 换 文 本 。
-
在 磁 盘 文 件 中 搜 索 文 本 。
前 两 种 类 型 在 文 本 编 辑 器 中 是 很 普 通 的 ,而 在 磁 盘 文 件 中 搜 索 文 本 ,则 是 一 个 不常 见 但 却 极 有 用 的 类 型 , 它 可 显 示 出 包 含 一 个 特 定 词 或 短 语 的 所 有 文 件 。以 下 我
们 将 详 细 说 明 这 三 个 类 型 。
在 打 开 的 文 档 中 搜 索 文 本
像 大 多 数 文 本 编 辑 器 一 样 , Visual C++ 编 辑 器 能 够 扫 描 文 档 , 并 找 出 给 定 单 词 或短 语 ( 我 们 称 之 为 目 标 字 符 串 ) 的 位 置 。 有 两 种 方 法 可 设 定 目 标 字 符 串 的 内 容 。最 方 便 的 方 法 是 使 用 标 准 工 具 栏 中 的 下 拉 框 , 如 下 图 示 :
在 下 拉 框 中 输 入 字 符 串 , 或 者 单 击 框 旁 的 箭 头 按 钮 , 再 从 列 表 中 选 择 以 前 输 入 的字 符 串 。 按 Enter 键 开 始 搜 索 。 当 编 辑 器 找 到 该 字 符 串 后 , 它 将 其 高 亮 显 示 , 并将 插 入 符 置 于 此 高 亮 字 符 串 的 首 字 符 旁 。 只 要 组 合 框 允 许 , 按 Enter 键 就 可 继 续按 下 一 个 已 给 出 的 目 标 字 符 串 搜 索 。 按 Esc 键 , 或 单 击 文 档 窗 口 的 任 何 部 分 , 就可 返 回 编 辑 模 式 。再 按 F3 或 Shift+F3 ,就 可 继 续 向 后 或 向 前 继 续 搜 索 。Visual C++ 提 供 了 这 些 命 令 的 工 具 按 钮 ,不 过 需 要 你 自 己 将 它 们 加 到 工 具 栏 中 。本 章 后 面 的“ 为 命 令 创 建 工 具 栏 按 钮 ” 一 节 将 说 明 怎 样 添 加 工 具 按 钮 。下 面 是 它 们 被 加 到 工具 栏 中 后 的 样 子 :
第 二 种 设 定 目 标 字 符 串 的 方 法 需 要 Fin d( 查 找 ) 对 话 框 。 虽 然 这 种 方 法 不 如 第 一种 直 接 , 但 它 提 供 了 更 多 的 选 择 。 例 如 , 如 果 想 搜 索 的 字 符 串 碰 巧 在 屏 幕 中 , 可以 直 接 借 用 它 , 而 不 必 再 输 入 它 。 如 果 目 标 字 符 串 只 是 一 个 单 词 , 只 需 通 过 单 击这 个 单 词 或 将 插 入 符 置 于 这 个 单 词 上 ;否 则 , 可 通 过 拖 动 鼠 标 光 标 来 选 中 所 需 文本 。 接 下 来 , 通 过 按 Ctrl+F , 或 选 择 Edit ( 编 辑 ) 菜 单 下 的 Find ( 查 找 ) 命 令 , 来 打 开 Fin d( 查 找 ) 对 话 框 。 当 对 话 框 显 示 出 来 的 时 候 , 所 选 中 的 文 本 已 经 在 对话 框 中 了 。
可 通 过 设 定 是 否 区 别 大 小 写 , 或 是 否 整 词 匹 配 , 来 使 搜 索 更 为 精 确 。 单 击 M atch Cas e( 区 别 大 小 写 )复 选 框 ,将 设 定 一 个 区 别 大 小 写 的 搜 索 。在 这 个 搜 索 过 程 中 , 编 辑 器 只 找 出 与 目 标 串 完 全 相 同 的 字 符 串 。 例 如 , 对 于 目 标 串 “ abc ”, 区 分 大 小写 的 搜 索 只 找 出“ abc ”, 而 不 区 分 大 小 写 的 搜 索 则 会 找 出“ abc ”、“ ABC ”、“ Abc ”
等 等 。 单 击 Match Whole Word Only ( 整 词 匹 配 ) 复 选 框 , 可 忽 略 包 含 于 另 一 单词 之 中 的 目 标 串 。 例 如 , 对 于 目 标 串“ any ”, 在 整 词 匹 配 搜 索 中 , 编 辑 器 只 找 出以 完 整 单 词 形 式 出 现 的 “ any ”, 而 忽 略 掉 类 似“ company ”、“ many ”、“ anywhere ” 之 类 的 单 词 。
在 Fin d( 查 找 ) 对 话 框 中 , 单 击 Mark Al l( 标 记 所 有 的 ) 按 钮 , 就 可 在 每 一 个 搜索 到 的 目 标 处 设 置 一 个 无 名 书 签 。 当 继 续 使 用 Find 命 令 搜 索 其 他 目 标 时 , 这 种设 置 能 够 回 到 前 面 的 目 标 处 。
Visual C++ 编 辑 器 中 一 个 有 用 的 变 化 是 ,有 一 个 叫 Incremental Searc h( 增 量 搜 索 ) 的 命 令 ,它 使 得 搜 索 工 作 在 输 入 目 标 串 的 同 时 就 开 始 进 行 。在 一 个 打 开 的 文 档 中按 Ctrl+ I, 则 “ Incremental Search :” 就 会 立 即 出 现 在 屏 幕 左 下 角 的 状 态 栏 中 。 在输 入 目 标 串 的 同 时 , 编 辑 器 就 开 始 搜 索 , 通 常 不 等 输 完 , 搜 索 就 已 完 成 。 当 编 辑器 找 到 正 在 寻 找 的 字 符 串 时 , 按 Enter 键 , 或 一 个 方 向 键 就 可 回 到 编 辑 模 式 。 如要 再 次 搜 索 同 样 的 目 标 串 , 按 F3 或 单 击 适 当 的 工 具 按 钮 即 可 。 按 Shift+Ctrl+I 键 可 改 变 搜 索 方 向 , 以 使 编 辑 器 从 插 入 符 所 在 位 置 向 前 搜 索 。
在 已 打 开 的 文 档 中 替 换 文 本
如 果 想 替 换 文 档 中 的 某 些 字 符 串 , 可 选 择 Edi t( 编 辑 ) 命 令 下 的 Replac e( 替 换 ) 命 令 。 这 个 命 令 将 给 出 一 个 类 似 于 Fin d( 查 找 ) 对 话 框 的 对 话 框 , 只 不 过 这 个 对话 框 有 两 个 文 本 框 , 需 要 两 个 字 符 串 。 第 一 个 文 本 框 中 放 置 普 通 的 目 标 字 符 串 。
第 二 个 文 本 框 中 则 要 放 置 要 用 来 替 换 的 新 字 符 串 。如 果 将 第 二 个 文 本 框 置 空 ,则编 辑 器 将 把 找 到 的 所 有 目 标 串 删 除 。 为 了 有 选 择 地 搜 索 或 替 换 , 当 编 辑 器 找 到 目标 串 时 ,单 击 Replac e( 替 换 )按 钮 ,系 统 将 自 动 跳 到 下 一 个 目 标 串 处 。单 击 Find
Nex t( 查 找 下 一 个 )按 钮 ,系 统 将 跳 过 这 个 字 符 串 ,而 不 改 变 它 。单 击 Replace All
( 全 部 替 换 ) 按 钮 , 将 会 一 次 性 完 成 所 有 替 换 。 可 以 只 向 前 , 或 只 向 后 搜 索 或 替换 , 但 不 能 在 多 个 文 件 中 搜 索 或 替 换 。
如 果 在 激 活 Replac e( 替 换 )对 话 框 之 前 ,已 选 中 了 超 过 一 行 的 文 本 ,则 Selection
( 选 择 )单 选 钮 将 自 动 打 开 ,这 表 明 编 辑 器 将 把 搜 索 或 替 换 操 作 限 制 在 所 选 章 节之 中 。 单 击 Whole File ( 整 个 文 件 ) 单 选 钮 , 将 取 消 这 一 设 置 。 虽 然 可 通 过 在 按下 Alt 键 的 同 时 向 右 下 方 拖 动 鼠 标 光 标 来 选 中 一 列 字 符 串 , 但 通 常 情 况 下 , 不 能进 行 列 的 替 换 。 如 果 选 中 一 列 字 符 串 , Selection( 选 择 ) 单 选 钮 将 不 会 打 开 。 不过 , 有 一 个 宏 操 作 可 克 服 这 一 困 难 , 在 第 13 章 中 举 出 了 一 个 可 对 列 进 行 搜 索 或替 换 的 宏 操 作 的 例 子 。
在 磁 盘 文 件 中 搜 索 文 本
UNIX 系 统 的 用 户 都 知 道 这 一 功 能 。 给 出 一 个 目 标 字 符 串 , Visual C++ 文 本 编 辑器 能 找 出 某 个 文 件 夹 下 所 有 包 含 目 标 串 的 文 件 , 包 括 位 于 子 文 件 夹 内 的 文 件 。单
击 Edit( 编 辑 ) 菜 单 下 的 Find In Files ( 在 文 件 中 查 找 ) 命 令 , 可 打 开 如 图 3-6 所 示 的 对 话 框 。 这 个 对 话 框 需 要 指 定 目 标 串 、 文 件 类 型 以 及 搜 索 过 程 所 在 的 文 件夹 。
图 3-6 Find In Files 对 话 框 , 用 于 搜 索 磁 盘 文 件
通 常 ,默 认 文 件 夹 是 当 前 软 件 所 在 的 文 件 夹 ;如 果 想 搜 索 其 他 文 件 夹 ,在 In Folder
( 文 件 夹 中 ) 框 中 , 输 入 其 路 径 , 或 单 击 框 旁 的 有 三 个 点 的 按 钮 , 来 寻 找 所 需 文件 夹 。 Look In Subfolders ( 在 子 文 件 夹 中 查 找 ) 复 选 框 决 定 编 辑 器 是 否 在 子 文 件夹 中 进 行 搜 索 。 通 常 其 默 认 值 为 打 开 。 单 击 Advanced ( 高 级 ) 按 钮 , 可 设 定 除子 文 件 夹 之 外 的 其 他 文 件 夹 , 搜 索 也 将 在 这 些 文 件 夹 中 进 行 。
在 第 1 章 中 我 们 已 看 到 , Find In File s( 在 文 件 中 查 找 ) 命 令 通 常 将 其 找 到 的 文 件
在 Outpu t( 输 出 ) 窗 口 中 的 Find In Files 1 选 项 卡 下 列 出 ( 参 看 图 1-7 )。 如 要 将其 在 Find In Files 2 选 项 卡 下 列 出 , 只 需 激 活 Output To Pane 2 ( 输 出 到 窗 格 2 ) 复 选 框 , 如 图 3-6 所 示 。 这 个 选 项 可 同 时 显 示 两 个 独 立 的 文 件 列 表 , 这 样 , 当 前搜 索 的 结 果 不 会 覆 盖 前 一 次 搜 索 的 结 果 。
如 果 已 经 设 置 好 各 项 , 单 击 Fin d(查找)按钮。当 Visual C++ 找 到 一 个 包 含 所 给出 的 目 标 串 的 文 件 时 , 它 把 其 文 件 名 和 路 径 列 在 Outpu t( 输 出 ) 窗 口 中 , 同 时 还列 出 此 文 件 中 第 一 个 目 标 串 所 在 行 , 这 便 可 以 看 到 目 标 串 在 文 件 中 是 怎 么 用 的 。双 击 某 个 文 件 , 可 在 文 本 编 辑 器 中 打 开 它 。
在 进 行 文 件 搜 索 之 前 , Visual C++ 首 先 保 存 任 何 在 文 本 编 辑 器 中 打 开 而 未 保 存 的文 档 , 这 将 确 保 所 搜 索 的 文 件 都 是 最 新 版 本 的 。 可 通 过 调 整 Option s( 选 项 ) 对话 框 中 Edito r( 编 辑 器 ) 选 项 卡 下 的 两 个 标 有 “ Save Before Running Tools( 在 运行 工 具 之 前 保 存 )”和“ Prompt Before Saving File s( 在 保 存 文 件 之 前 提 示 )”的复 选 框 来 改 变 这 一 属 性 。关 闭“ Save Before Running Tools ”复 选 框 ,将 使 Visual C++ 在 搜 索 前 不 保 存 文 档 , 这 样 就 使 搜 索 在 上 次 保 存 的 文 档 中 进 行 。如 果 希 望 在 激 活Find In File s( 在 文 件 中 查 找 ) 命 令 之 前 , 由 自 己 决 定 是 否 保 存 文 档 , 则 关 闭 这 两个 选 项 。 这 将 使 编 辑 器 在 保 存 每 个 文 档 前 先 征 求 你 的 意 见 。
常 规 表 达 式 搜 索
迄 今 为 止 , 我 们 见 到 的 搜 索 对 话 框 中 , 都 包 含 一 个 标 有 Regular Expressio n( 常 规
表 达 式 ) 的 复 选 框 。 常 规 表 达 式 是 指 有 一 个 或 多 个 特 殊 字 符 组 成 , 用 以 表 示 一 系列 文 本 的 字 符 或 字 符 串 。 在 Open ( 打 开 ) 和 Save as( 另 存 为 ) 对 话 框 中 , 我 们已 有 过 类 似 的 使 用 , 例 如 ,“ *.CPP ” 表 示 以 CPP 为 扩 展 名 的 任 何 文 件 。 这 里 的星 号 就 是 一 个 常 规 表 达 式 , 它 代 表 可 组 成 有 效 文 件 的 任 何 文 本 。
搜 索 中 的 目 标 字 符 串 中 所 用 的 常 规 表 达 式 则 更 为 复 杂 ,这 样 可 以 更 为 精 确 地 控 制目 标 字 符 串 。 表 3-3 列 出 了 系 统 默 认 的 常 规 表 达 式 。 注 意 , 只 有 当 搜 索 对 话 框 中的 Regular Expressio n( 常 规 表 达 式 ) 复 选 框 打 开 时 , 编 辑 器 才 把 这 些 字 符 按 常 规表 达 式 处 理 , 否 则 , 将 把 它 们 当 作 一 般 字 符 处 理 。
表 |
3-3 |
常 规 表 达 式 字 符 |
||
---|---|---|---|---|
符 号 |
含 义 |
示 例 |
||
。 |
任 何 单 个 字 符 |
" ..do " 可 以 同 |
redo 和 |
undo 匹 |
配 , 但 不 能 同 outdo 匹 配
[] 任 意 字 符 或 括 号 内 的 字 符 " sl[aou]g " 可 以 同 slag ,slog 和
slug 匹 配
[^] 插 入 符 后 所 示 范 围 之 外 的 任 何字符
"sl[^r-z]g"包 含 slag , slog ,但不 含 slug
- 没 有 或 有 更 多 的 前 一 个 字 符 "re*d" 包 含 rd , red , reed
+ 一 个 或 多 个 前 一 个 字 符 "re+d" 包 含 red , reed ,但 不 含
rd
^ 一 行 的 开 头 "^word" 只 包 含 位 于 行 首 的
word
续 表
$ |
一 行 的 结 尾 |
"word$" 只 包 含 位 于 行 尾 的 |
---|---|---|
word |
||
\ |
下 一 个 字 符 不 是 常 规 表 达 式 |
"word\$" 只 与 word$ 匹 配 ,而 不把 $ 看 作 常 规 表 达 式 |
不 必 去 记 这 张 表 。 在 所 有 的 Fin d( 查 找 ) 对 话 框 中 , 都 通 过 组 合 框 旁 的 一 个 小 按钮 来 给 出 表 3-3 的 当 前 版 本 。 单 击 此 按 钮 , 打 开 常 规 表 达 式 菜 单 , 然 后 就 可 以 选择 所 需 的 常 规 表 达 式 了 。
用 加 号 可 设 计 一 个 字 符 串 。 例 如 , 考 虑 常 规 表 达 式 [a-zA-Z ], 它 代 表 任 何 一 个 字母 。 如 果 再 增 加 一 个 加 号 , 意 义 就 完 全 变 了 。 加 号 的 意 义 是“ 一 个 或 多 个 这 些 字符 ”。因此,编辑器将 [a-zA-Z]+ 看 作 为 任 意 字 符 串 , 也 就 是 任 意 一 个 单 词 。 同 样 , 常 规 表 达 式 [0-9] 代 表 一 个 数 字 , 而 [0-9]+ 则 代 表 任 意 一 个 正 数 , 无 论 其 大 小 。
常 规 表 达 式 搜 索 通 常 是 区 别 大 小 写 的 。 即 使 关 闭 Fin d( 查 找 ) 对 话 框 中 的 M atch Case 复 选 框 , 对 常 规 表 达 式 [0-9a-f]+ 的 搜 索 也 只 能 找 到 类 似 于 0x37ac 的 字 符 串 , 而 不 能 找 到 0x7A4B 。 为 了 找 到 后 者 , 必 须 将 大 写 字 母 包 含 在 常 规 表 达 式 中 , 例如 :[0-9a-fA-F]+ 。
编 程 辅 助 工 具
在 Winsows 和 MFC 下 编 程 , 即 使 是 最 有 经 验 的 程 序 员 , 也 不 得 不 经 常 翻 阅 大 量的 参 考 资 料 , 或 浏 览 在 线 资 料 。 我 们 还 不 得 不 花 大 量 时 间 , 去 记 住 一 些 编 程 所 必须 的 信 息 , 例 如 参 数 表 、 函 数 或 变 量 的 拼 写 等 。 现 在 , Visual C++ 文 本 编 辑 器 的一 些 特 性 将 使 程 序 员 省 去 了 这 些 麻 烦 。本 章 将 介 绍 这 其 中 最 有 用 的 一 个 工 具 :一种 称 作 Statement Completion ( 语 句 补 全 ) 的 输 入 辅 助 工 具 。
Statement Completio n( 语 句 补 全 ) 是 三 个 编 程 工 具 的 总 称 , 它 们 是 : 成 员 表( List M embers ), 参 数 信 息( Parameter Info ), 输 入 信 息( Type Info )。 这 三 个 工 具 就 如同 是 手 边 随 时 可 用 的 W in32 和 MFC 的 参 考 资 料 。
成 员 表
为 了 提 高 代 码 输 入 速 度 , 并 最 大 限 度 的 减 少 输 入 错 误 , Visual C++ 编 辑 器 的 成 员表 可 任 随 时 调 用 。 通 过 一 个 弹 出 式 窗 口 , 成 员 表 给 出 了 一 个 巨 大 的 列 表 , 其 中 包括 MFC 类 成 员 、 C 运 行 函 数 、 显 示 常 量 、 结 构 名 称 、 W in32 API 函 数 、 当 前 程序 的 类 成 员 。 可 在 这 个 列 表 找 出 要 输 入 的 单 词 , 从 而 完 成 输 入 。 当 输 入 域 运 算 符
( ::)、 成 员 运 算 符 ( .)、 指 针 运 算 符 ( -> ) 时 , 成 员 表 会 自 动 弹 出 到 屏 幕 上 。 此时 , 当 继 续 输 入 一 个 成 员 名 时 , 这 个 弹 出 式 窗 口 的 选 择 条 会 自 动 移 到 与 输 入 最 匹配 的 成 员 名 上 。 图 3-7 说 明 了 在 函 数 CDC::SetMapMode 下 , 成 员 表 是 如 何 在 完
成 输 入 之 前 找 到 匹 配 名 的 。
图 3-7 在 文 本 编 辑 器 中 显 示 的 List Member (成员表)
当 输 入 一 个 无 字 符 码 ( 如 空 格 或 semicolon ) 时 , 系 统 就 将 高 亮 显 示 的 成 员 名 插入 到 文 档 中 。 这 个 过 程 听 起 来 挺 复 杂 , 但 实 际 过 程 要 简 单 得 多 , 因 为 源 代 码 中 每一 个 成 员 名 后 都 几 乎 总 是 跟 着 一 个 标 志 :函 数 名 后 跟 一 个 左 括 号 , 变 量 名 后 跟 一
个 等 号 或 分 号 。 例 如 , 在 图 3-7 右 图 中 , 输 入 一 个 左 括 号 会 产 生 如 下 结 果 :
//Set coordinate system pDC->SetMapMode(
这 里 , 成 员 表 消 失 , 高 亮 显 示 的 SetMapMode 被 插 入 到 插 入 符 所 在 处 , 并 在 其 后
加 一 小 括 号 , 从 而 为 继 续 输 入 参 数 做 好 准 备 。 在 下 一 节 我 们 会 看 到 , Statement Completion( 语 句 补 全 ) 并 没 有 到 此 为 止 , 而 是 又 激 活 了 Parameter Info( 参 数 信息 ) 工 具 来 帮 你 继 续 完 成 参 数 输 入 。 当 成 员 表 消 失 后 , 这 个 逻 辑 工 具 就 自 动 取 代了 它 的 位 置 。
按 Tab 键 或 Ctrl+Enter 键 , 可 在 不 增 添 字 符 的 情 况 下 完 成 单 词 输 入 , 并 使 成 员 表消失。按 Ctrl+Alt+T 键 , 可 在 任 何 时 刻 激 活 成 员 表 窗 口 。 编 辑 器 总 是 以 插 入 符 左侧 的 文 本 为 线 索 来 定 位 选 择 条 。 例 如 , 在 键 入 cv 后 激 活 成 员 表 , 此 时 将 显 示 成员 表 窗 口 , 并 将 选 择 条 定 位 在 CView 处 :
这 里 输 入 的 字 符 cv 与 高 亮 显 示 的 名 称 CView 大 小 写 不 同 。 不 过 , 成 员 表 在 定 位工 具 栏 时 忽 略 大 小 写 , 因 此 , 可 以 全 部 用 小 写 输 入 , 只 是 最 后 需 要 按 Tab 或 回 车
来 确 认 一 下 。 这 个 特 点 有 助 于 输 入 一 些 难 以 记 忆 的 组 合 函 数 , 如
UnmapViewOfFile 和 UnMapAndLoad 等 。
尽 管 通 过 按 组 合 快 捷 键 很 容 易 显 示 成 员 表 窗 口 , 但 如 果 乐 意 , 还 可 以 通 过 Edit
( 编 辑 ) 菜 单 , 或 在 文 档 窗 口 内 双 击 右 箭 头 键 , 激 活 上 下 文 菜 单 来 打 开 成 员 表 。成 员 表 窗 口 中 只 包 括 那 些 在 当 前 类 或 对 象 下 有 效 的 符 号 名 。例如,当输入一个从CDialog 继 承 来 的 目 标 时 ,成 员 表 中 将 包 括 PrevDlgCtrl 函 数 ,因 为 这 个 函 数 属 于这 个 类 。 而 当 输 入 一 个 从 CString 继 承 来 的 类 时 , 这 个 函 数 将 不 存 在 于 列 表 中 。
在 Edit ( 编 辑 ) 菜 单 下 还 有 一 个 叫 Complete Word ( 补 全 词 ) 的 命 令 , 它 看 似Statement Completio n( 语 句 补 全 ) 的 另 一 个 工 具 , 其 实 不 过 是 成 员 表 的 一 种 简 短方 式 。 如 果 不 想 通 过 按 Ctrl+Alt+T 来 激 活 List Members( 成 员 表 ) 命 令 , 可 通 过按 Ctrl+Space 来 激 活 Complete Word 命 令 。 通 常 情 况 下 , 这 两 种 方 法 会 有 同 样 的结 果 , 都 显 示 成 员 表 窗 口 , 并 将 选 择 条 置 于 与 正 输 入 的 文 本 最 匹 配 的 成 员 名 上 。不 过 ,当 与 所 输 入 的 文 本 最 匹 配 的 成 员 名 只 有 一 个 时 , 仍 显 示 成 员 表 就 显 得 多 余了 。 在 这 种 情 况 下 , 按 Ctrl+Space 将 不 显 示 成 员 表 , 而 直 接 完 成 操 作 。 例 如 , 在输 入 CreateMul 后 按 Ctrl+Spacebar, 就 可 一 步 完 成 输 入 , 因 为 它 可 以 明 确 判 定 想输 入 的 是 CreateMultiProfileTransform , 而 不 是 CreateMutex 或 其 他 。
参 数 信 息
参 数 信 息 包 含 函 数 的 各 个 参 数 ,当 在 函 数 后 输 入 第 一 个 括 号 时 , 参 数 信 息 将 以 一
个 工 具 栏 式 窗 口 的 形 式 弹 到 屏 幕 上 。 这 种 工 具 栏 式 窗 口 像 一 个 屏 幕 提 示 , 显 示 出函 数 原 型 , 并 要 求 输 入 参 数 。 如 下 例 :
输 入 参 数 时 ,函 数 原 型 一 直 显 示 在 屏 幕 上 ,当 输 入 最 后 的 右 括 号 时 ,此 窗 口 消 失 。如 果 这 个 函 数 是 过 载 的 , 可 接 受 多 组 参 数 , 则 参 数 信 息 窗 口 将 显 示 一 个 函 数 原型 , 并 在 窗 口 左 端 给 出 数 字 , 来 说 明 此 函 数 有 多 少 过 载 的 版 本 。 按 Ctrl+PgU p, 或 单 击 参 数 信 息 窗 口 , 可 在 一 个 函 数 原 型 循 环 到 下 一 个 。 如 下 例 :
有 一 个 命 令 可 使 得 当 把 插 入 符 放 在 函 数 名 上 时 ,参 数 信 息 窗 口 会 自 动 显 示 在 屏 幕上 。 可 通 过 Edit( 编 辑 ) 菜 单 或 按 Ctrl+Shift+Spacebar 来 选 择 这 个 命 令 。 也 可 在文 本 中 用 右 击 一 个 函 数 名 , 来 打 开 上 下 文 菜 单 , 再 从 中 选 择 该 命 令 。 和 其 他 的Visual C++ 命 令 一 样 , 也 可 以 设 置 一 个 快 捷 键 来 激 活 参 数 信 息 工 具 。 本 章 后 面 的“ 未 结 合 命 令 ” 一 节 解 释 这 点 。
输 入 信 息
输 入 信 息 和 参 数 信 息 类 似 , 也 以 工 具 提 示 窗 口 出 现 , 它 包 含 有 关 函 数 和 变 量 的 信息 。 当 系 统 认 出 鼠 标 光 标 处 的 符 号 时 , 输 入 信 息 窗 口 将 自 动 显 示 出 来 , 当 把 光 标移 开 时 , 该 窗 口 将 自 动 消 失 。可 通 过 Edi t( 编 辑 ) 菜 单 、 上 下 文 菜 单 或 按 Ctrl+T , 来 调 用 输 入 信 息 功 能 。如 果 想 了 解 刚 输 入 的 , 或 刚 从 成 员 表 中 粘 贴 过 来 的 代 码 信息 , 那 么 , 最 后 一 种 方 法 是 很 方 便 的 。 当 插 入 符 位 于 一 个 函 数 名 上 时 , 输 入 信 息窗 口 和 参 数 信 息 窗 口 所 提 供 的 信 息 是 一 样 的 , 都 列 出 函 数 的 原 型 。 当 调 用 一 个 定义 的 类 型 时 , 窗 口 中 显 示 创 建 别 名 时 的 typedef 语 句 :
当 需 要 显 示 某 个 变 量 的 信 息 时 , 输 入 信 息 就 显 得 很 有 用 。 它 给 出 了 变 量 的 说 明 , 使 得 不 再 需 要 查 询 源 代 码 或 类 的 头 文 件 来 确 定 该 变 量 类 型 。 例 如 , 如 果 变 量indicators 的 类 型 不 清 楚 , 使 用 输 入 信 息 窗 口 , 就 会 立 即 看 到 它 是 一 个 整 数 数 组变 量 , 如 下 图 :
输 入 信 息 窗 口 以 及 其 他 类 似 的 弹 出 式 窗 口 也 许 会 使 你 感 到 眼 花 缭 乱 。 如 果 这 样 , 单 击 Tools( 工 具 ) 菜 单 下 的 Options( 选 项 ) 命 令 , 再 清 除 对 话 框 中 Editor( 编辑 器 ) 选 项 卡 下 的 相 应 复 选 框 即 可 ( 参 看 图 3-11 )。 通 过 相 应 的 快 捷 键 或 菜 单 命令 , 可 再 次 激 活 这 些 工 具 。
Advanced ( 高 级 ) 命 令
Edit( 编 辑 ) 菜 单 底 部 附 近 的 Advanced( 高 级 ) 命 令 提 供 了 一 个 选 项 集 合 , 它 们在 进 行 文 本 文 档 工 作 时 会 非 常 有 用 。 让 光 标 在 Advanced ( 高 级 ) 命 令 上 停 留 一会 儿 ,会 显 示 如 下 所 示 的 子 菜 单 。
正 如 你 所 看 到 的 那 样 , 菜 单 提 供 了 对 前 述 Incremental Searc h( 增 量 搜 索 ) 命 令 的访 问 , 尽 管 按 Ctrl+I 是 访 问 该 命 令 的 更 为 方 便 的 办 法 。 Format Selectio n( 格 式 选择 ) 命 令 通 过 插 入 制 表 符 , 来 设 置 花 括 号 内 的 C/C++ 代 码 的 缩 进 。 这 个 命 令 把 下面 的 代 码 :
if(msg=WM_USER)
{
for(i=0;i<5;i++)
{
//Additional code
}
}
变 成 :
if(msg= WM_USER)
{
for(i=0;i<5;i++)
{
//Additional code
}
}
Format Selectio n( 选 择 ) 命 令 通 过 扫 描 为 花 括 号 选 择 的 文 本 来 决 定 嵌 套 层 次 。 第一 层 的 文 本 行 缩 进 一 个 制 表 符 , 第 二 层 的 文 本 行 缩 进 两 个 制 表 符 , 依 此 类 推 。
Tabify Selection ( 制 表 符 选 择 ) 命 令 把 选 中 的 一 系 列 空 格 转 换 成 等 量 的 制 表 符 。Untabify Selection ( 取 消 制 表 符 选 择 ) 则 把 这 个 操 作 反 过 来 。 通 过 打 开 View Whitespace( 查 看 工 作 空 间 ) 双 态 开 关 , 可 清 楚 地 看 到 两 个 命 令 的 效 果 , 这 时 文档 中 的 空 格 和 制 表 符 都 变 成 可 见 的 。 当 该 开 关 打 开 时 , 文 本 中 的 空 格 字 符 显 示 为小 圆 点 (.) , 而 制 表 符 显 示 为 书 名 号 (>> )。
子 菜 单 中 剩 下 的 两 个 命 令 的 作 用 就 像 它 们 的 名 字 所 表 示 的 那 样 。 M ake Selection Uppercase( 使 选 择 内 容 成 为 大 写 ) 命 令 使 选 中 的 所 有 字 母 都 变 成 大 写 , 而 Make Selection Lowercase ( 使 选 择 内 容 成 为 小 写 ) 命 令 则 恰 恰 相 反 。 选 择 中 的 非 字 母字 符 , 如 数 字 和 标 点 符 号 , 则 不 受 这 两 个 命 令 的 影 响 。
未 结 合 命 令
每 个 Visual C++ 命 令 都 有 一 个 描 述 性 的 内 部 名 称 。 例 如 , 刚 刚 说 过 的 Incremental Searc h( 增 量 搜 索 )和 Tabif y( 转 换 制 表 符 )命 令 的 内 部 名 称 为 SearchIncremental 、SelectionTabify 和 SelectionUntabify 。在 线 帮 助 提 到 了 许 多 你 在 菜 单 中 找 不 到 的 其他 命 令 ,例 如 名 为 GoT o( 转 到 )NextErrorTag ,LineTranspose 和 LineDeleteTo Start 的 命 令 。 有 两 个 原 因 来 解 释 为 什 么 帮 助 系 统 宁 愿 用 内 部 名 称 , 而 不 用 组 合 键 , 如
F4 或 Shift+Alt+T 来 标 识 命 令 。 首 先 , 你 可 以 把 命 令 的 组 合 键 改 成 你 喜 欢 的 任 意键 。 其 次 , 许 多 命 令 还 没 有 指 派 快 捷 键 。 这 样 的 命 令 称 为 “ 未 结 合 的 ”。 要 使 用一 个 未 结 合 命 令 , 你 必 须 首 先 给 它 指 定 一 个 组 合 键 。
在 Developer Studio 环 境 下 , 隐 藏 着 一 大 套 命 令 , 除 那 些 出 现 在 菜 单 和 工 具 栏 按钮 上 的 命 令 之 外 ,还 有 更 多 的 命 令 可 以 使 用 。在 Hel p( 帮 助 )菜 单 中 单 击 Keyboard M ap ( 敲 键 映 射 ) 来 查 看 命 令 列 表 , 如 图 3-8 所 示 。
图 3-8 从 Help 菜单中选择 Keyboard Map ,以显示 Visual C++ 的命令列表
在 Help Keyboard( 帮 助 键 盘 ) 窗 口 中 出 现 的 默 认 列 表 称 为“ 结 合 命 令 ”, 这 意 味着 , 这 些 命 令 已 经 指 派 了 组 合 键 。 要 查 看 只 属 于 文 本 编 辑 器 的 结 合 命 令 和 未 结 合命 令 列 表 , 在 下 拉 列 表 框 中 选 择 Edit( 编 辑 ), 并 在 第 二 栏 的 上 边 单 击 Command
( 命 令 ) 按 钮 , 来 按 命 令 的 字 母 顺 序 排 列 列 表 。 当 你 滚 动 列 表 时 , 你 会 在 Keys
( 键 ) 栏 中 看 到 最 常 用 的 命 令 已 经 约 定 了 组 合 键 , 但 许 多 命 令 还 没 有 。 未 结 合 命令 的 设 置 使 许 多 特 征 变 得 可 用 , 否 则 它 们 就 不 能 通 过 菜 单 、 工 具 栏 或 键 盘 来 访问 。
如 何 访 问 命 令 完 全 取 决 于 你 的 喜 好 。 Visual C++ 允 许 你 向 菜 单 或 工 具 栏 中 添 加 任
何 结 合 的 和 未 结 合 命 令 , 这 将 在 第 13 章 中 详 细 讨 论 。 但 因 为 拥 挤 的 菜 单 和 工 具栏 反 而 容 易 误 事 ,最 好 通 过 给 未 结 合 命 令 定 义 一 个 组 合 键 来 调 用 它 。唯 一 的 缺 点是 你 必 须 记 住 访 问 命 令 的 快 捷 键 。
没 有 人 会 打 算 一 次 就 启 用 所 有 的 未 结 合 命 令 。选 择 那 些 你 认 为 最 有 用 的 命 令 ,给它 们 指 派 最 符 合 你 的 风 格 和 最 容 易 记 忆 的 组 合 键 。举 个 例 子 ,让 我 们 给 文 本 编 辑器 添 加 两 个 非 常 有 用 的 命 令 : WordUpperCase 和 WordLowerCase , 它 们 改 变 当 前文 本 中 插 入 符 之 下 的 单 词 的 大 小 写 。 默 认 情 况 下 , WordUpperCase 和WordLowerCase 没 有 被 指 派 组 合 键 , 也 没 有 工 具 栏 按 钮 或 菜 单 选 项 来 访 问 它 们 。除 非 你 给 它 们 指 定 组 合 键 , 没 有 别 的 办 法 来 使 用 这 两 个 命 令 。
下 面 是 调 用 命 令 的 方 式 : 从 Tools ( 工 具 ) 菜 单 中 选 择 Customize ( 自 定 义 ), 来打 开 Customiz e( 自 定 义 )对 话 框 ,然 后 单 击 Keyboar d( 键 盘 )选 项 卡 。从 Category
( 分 类 ) 下 拉 列 表 中 选 择 Edit( 编 辑 ), 并 确 保 Tex t( 文 本 ) 出 现 在 Editor 框 中 。这 些 设 置 表 示 我 们 正 为 一 个 只 用 于 文 本 编 辑 器 的 命 令 定 义 一 个 组 合 键 。 在Commands 列 表 框 中 出 现 的 命 令 是 按 字 母 顺 序 排 列 的 。 向 下 滚 动 列 表 到 底 部 , 找到 WordUpperCase 条 目 ,然 后 单 击 它 来 选 中 它 。对 话 框 的 左 下 角 会 出 现 命 令 的 简短 说 明 , 但 Current Keys ( 当 前 键 ) 列 表 框 中 是 一 片 空 白 , 这 表 示 目 前 没 有 给WordUpperCase 定 义 快 捷 键 。 要 定 义 一 个 快 捷 键 , 单 击 Press New Shortcut Key
( 按 新 的 快 捷 键 ) 文 本 框 , 并 按 下 你 想 用 来 访 问 该 命 令 的 组 合 键 。 如 果 你 按 下Ctrl+U , 对 话 框 提 示 你 该 组 合 键 目 前 已 指 定 给 SelectionLowercase 命 令 。 这 并 不意 味 着 你 不 能 把 Ctrl+U 指 定 给 WordUpperCase ; 它 只 是 提 示 你 , 如 果 你 这 样 做
的 话 ,按 Ctrl+U 将 不 再 调 用 SelectionLowercase 命 令 ,它 会 变 成 一 个 未 结 合 命 令 。因 为 Ctrl+U 已 经 使 用 了 , A lt+U 对 WordUpperCase 来 说 是 一 个 更 好 的 选 择 。 当你 按 下 A lt+U 时 , 对 话 框 告 诉 你 这 个 快 捷 键 目 前 没 有 定 义 给 别 的 命 令 ( 见 图 3- 9 )。 单 击 Assign ( 指 定 ) 按 钮 后 , 快 捷 键 就 可 以 使 用 了 。
图 3-9 对文本编辑器命令指定一个键组合
同 样 给 WordLowerCase 命 令 定 义 快 捷 键 A lt+L 。 当 你 在 Press New Shortcut Key 文 本 框 中 按 下 A lt+L 时 , 系 统 会 提 示 你 这 个 组 合 键 被 用 来 访 问 菜 单 。提 示 消 息 提到 Layou t( 布 局 ) 菜 单 , 它 只 在 对 话 框 编 辑 器 调 用 时 才 能 使 用 。 因 为 Layou t( 布局 ) 菜 单 对 文 本 编 辑 器 没 有 影 响 , 选 择 A lt+L 不 会 导 致 快 捷 键 冲 突 。 当 文 本 编 辑器 调 用 时 , A lt+L 调用 WordLowerCase 命 令 ; 当 对 话 框 编 辑 器 调 用 时 , A lt+L 像以 前 一 样 拉 下 Layou t( 布 局 ) 菜 单 。
要 使 用 新 的 WordUpperCase 和 WordLowerCase 命 令 , 打 开 一 个 文 本 文 档 , 并 随便 在 一 个 单 词 上 放 一 个 插 入 符 。按 下 A lt+U 或 Alt+L 调 用 命 令 来 改 变 从 插 入 符 到单 词 末 尾 的 所 有 字 母 的 大 小 写 。 同 样 地 , 新 的 命 令 会 覆 盖 SelectionUppercase 和SelectionLowercase 命 令 , 因 为 它 们 作 用 在 任 何 选 中 的 文 本 块 上 , 而 不 是 在 单 一的 单 词 上 。 现 在 Selection ( 选 择 ) 命 令 是 多 余 的 了 , 没 有 关 系 。 新 的 Alt+U 和A lt+L 快 捷 键 比 起 等 同 的 Shift+Ctrl+U(SelectionUppercase) 和Ctrl+U(SelectionLowercase) 组 合 键 来 更 容 易 使 用 和 记 忆 。 然 而 这 种 覆 盖 只 适 用 于选 中 的 文 本 ,因 为 当 没 有 选 择 文 本 时 SelectionUppercase 和 SelectionLowercase 会影 响 插 入 符 附 近 的 字 符 。
为 命 令 创 建 工 具 栏 按 钮
如 果 你 喜 欢 使 用 工 具 栏 , 并 发 现 自 己 经 常 使 用 诸 如 WordUpperCase 和
WordLowerCase 之 类 没 有 预 定 义 工 具 栏 按 钮 的 命 令 ,你 可 能 想 为 这 些 命 令 创 建 新
的 按 钮 。 你 可 以 把 按 钮 放 在 任 何 已 有 的 工 具 栏 上 , 或 者 创 建 一 个 新 的 工 具 栏 。 下面 演 示 如 何 为 新 的 WordUpperCase 和 WordLowerCase 命 令 创 建 工 具 栏 按 钮 。 在Customize ( 自 定 义 ) 对 话 框 的 Commands 选 项 卡 中 , 从 Category ( 分 类 ) 框 中选 择 A ll Command s( 所 有 命 令 ),来 显 示 按 字 母 顺 序 排 列 的 Visual C++ 命 令 列 表 。滚 动 列 表 , 来 找 到 WordUpperCase , 然 后 从 列 表 中 拖 动 该 条 目 , 把 它 放 在 环 境 的一 个 工 具 栏 , 如 Edit 工 具 栏 上 。 如 果 你 更 愿 意 创 建 一 个 新 的 工 具 栏 , 只 要 把WordUpperCase 条 目 拖 出 对 话 框 , 并 放 在 屏 幕 上 没 有 被 工 具 栏 覆 盖 的 地 方 , 就 可以 了 。 Visual C++ 自 动 创 建 一 个 新 的 工 具 栏 来 放 置 按 钮 。 从 列 表 中 把WordLowerCase 命 令 拖 到 同 一 个 工 具 栏 中 。
图 3-10 Visual C++ 提 供 新 工 具 栏 按 钮 的 图 标 选 择
因 为 WordUpperCase 和 WordLowerCase 命 令 没 有 预 定 义 的 图 标 , Button
Appearance ( 按 钮 外 观 ) 对 话 框 打 开 ( 图 3-10 ), 在 该 对 话 框 中 , 你 可 以 为 每 个新 的 按 钮 选 择 一 个 图 标 。 在 可 用 的 图 标 中 , 没 有 一 个 能 反 映 WordUpperCase 和WordLowerCase 的 不 寻 常 的 功 能 , 但 你 可 以 把 图 像 和 文 字 组 合 起 来 ,以 使 按 钮 的功 能 变 得 明 确 。 在 Button Appearanc e( 按 钮 外 观 ) 对 话 框 中 选 择 一 个 图 标 , 单 击Image And Tex t( 图 像 和 文 本 ) 单 选 钮 , 然 后 , 在 对 话 框 底 部 的 文 本 框 中 键 入 按钮 文 本 。 下 面 是 带 有 WordUpperCase 和 WordLowerCase 命 令 的 按 钮 的 新 工 具 栏的 样 子 :
未 结 合 命 令 不 只 是 用 于 文 本 编 辑 器 。下 一 章 描 述 如 何 用 同 样 的 方 法 来 通 过 快 捷 键或 工 具 栏 按 钮 来 执 行 图 形 编 辑 器 中 非 常 有 用 的 命 令 。 第 13 章 中 详 细 地 讨 论 了 在Visual C++ 环 境 中 创 建 工 具 栏 的 主 题 , 解 释 了 如 何 重 命 名 或 删 除 工 具 栏 , 如 何 从一 个 工 具 栏 中 向 另 一 个 工 具 栏 中 复 制 按 钮 , 以 及 如 何 定 制 按 钮 图 标 。
宏 的 基 础
你 可 以 把 一 个 结 合 命 令 当 作 一 个 预 定 义 的 宏 , 即 指 派 给 一 个 组 合 键 的 用 法 说 明 。环 境 也 允 许 你 创 建 用 于 文 本 编 辑 器 的 宏 , 你 可 以 通 过 记 录 按 键 和 鼠 标 单 击 活 动 , 来 把 它 们 组 合 成 普 通 的 Visual C++ 命 令 中 的 一 个 可 重 复 使 用 的 命 令 。你 可 以 像 执行 其 他 命 令 一 样 通 过 快 捷 键 、 菜 单 命 令 和 工 具 栏 按 钮 来 执 行 一 个 宏 。 实 际 上 , 宏同 普 通 的 结 合 命 令 几 乎 没 有 区 别 , 这 使 它 们 成 为 扩 展 环 境 功 能 的 一 个 高 级 方 法 。这 一 部 分 只 介 绍 一 下 宏 的 主 题 。 因 为 宏 用 在 整 个 Developer Studio 环 境 中 , 而 不只 是 用 于 文 本 编 辑 器 , 我 们 在 第 13 章 再 作 更 详 细 的 讨 论 。 现 在 , 我 们 可 以 简 单地 通 过 打 开 命 令 录 制 器 来 为 文 本 编 辑 器 创 建 一 个 宏 。
下 面 演 示 如 何 创 建 一 个 建 立 在 前 面 说 过 的 Untabify Selectio n( 解 除 制 表 符 转 换 选择 ) 命 令 上 的 宏 。 该 宏 把 命 令 的 功 能 扩 展 到 整 个 文 档 , 而 不 仅 仅 是 选 中 的 文 本 。首 先 关 闭 文 本 编 辑 器 中 所 有 的 文 档 , 来 防 止 改 变 已 有 的 文 本 , 然 后 通 过 按 下Ctrl+Shift+R ,或从 Tools( 工 具 ) 菜 单 中 选 择 Record Quick Macro( 快 速 录 制 宏 ) 命 令 , 来 开 始 录 制 新 宏 。 这 会 打 开 Recor d( 录 制 ) 工 具 栏 , 并 把 鼠 标 变 成 一 个 盒式 磁 带 形 的 图 像 , 这 表 示 Visual C++ 正 在 录 制 每 一 个 按 键 和 鼠 标 单 击 动 作 。 该 宏包 括 下 面 四 个 步 骤 :
-
在 Edit ( 编 辑 ) 菜 单 中 单 击 Select All ( 全 选 ) 命 令 来
选 中 整 个 文 档 。
-
从 Edit( 编 辑 ) 菜 单 中 选 择 Advanced , 并 在 子 菜 单 中 单
击 Untabify
Selection 命 令 。
-
按 下 Ctrl+Home 来 在 文 档 开 头 返 回 一 个 插 入 符 。
-
在 Recor d( 录 制 ) 工 具 栏 上 单 击 Stop Recordin g( 停 止 录
制 ) 按 钮 来 结束 录 制 过 程 。
现 在 , 我 们 有 了 一 个 新 的 宏 。 Visual C++ 以 G lobalTemporary.dsm ( 该 扩 展 名 代 表Developer Studio 宏 )。 的 文 件 名 把 宏 存 储 在 Common\MsDev98\Macros 的 文 件 夹下 。 该 文 件 包 含 一 个 简 单 的 Visual Basic 子 程 序 , 其 中 的 语 句 调 用 了 我 们 刚 才 录制 的 三 个 命 令 :
Sub GlobalTemporary
ActiveDocument.Selection.SelectAll ActiveDocument.Selection.Untabify ActiveDocument.Selection.StartOfDocument
End Sub
附 录 C 更 详 细 地 说 明 了 宏 的 源 文 件 语 言 : Visual Basic Scripting Edition 。 要 检 验这 个 宏 , 打 开 一 个 典 型 的 文 档 , 并 在 Advanced ( 高 级 ) 子 菜 单 中 打 开 View Whitespace ( 查 看 空 白 空 间 ) 命 令 , 来 使 你 能 够 看 到 宏 的 效 果 。 现 在 通 过 按 下Ctrl+Shift+P 或 在 Tools ( 工 具 ) 菜 单 中 单 击 Play Quick Macro ( 快 速 播 放 宏 ) 命令 来 运 行 宏 。 效 果 同 重 新 键 入 录 制 的 动 作 一 样 。
G lobalTemporary 宏 是 独 特 的 ,因 为 它 没 有 出 现 在 图 3-8 所 示 的 Visual C++ 命 令 列表 中 。 它 被 保 留 为 通 过 Record Quick Macro 命 令 创 建 的 “ 快 速 ” 宏 。 通 过 同 样 的命 令 来 录 制 另 一 个 宏 , 就 会 覆 盖 前 一 个 宏 , 因 此 , 一 次 只 有 一 个 快 捷 宏 存 在 。
定 制 编 辑 器
Visual C++ 文 本 编 辑 器 可 以 改 变 自 己 的 许 多 特 征 , 以 更 好 地 适 应 你 的 工 作 风 格 。我 们 已 经 讨 论 过 Tools( 工 具 ) 菜 单 中 的 Customiz e( 自 定 义 ) 命 令 , 它 让 你 定 制工 具 栏 , 并 给 命 令 约 定 快 捷 键 。 要 改 变 编 辑 器 界 面 的 其 他 特 征 , 从 Tools( 工 具 ) 菜 单 中 选 择 Options( 选 项 ) 命 令 。
Options( 选 项 ) 命 令 显 示 图 3-11 所 示 的 对 话 框 , 它 允 许 你 指 定 文 本 编 辑 器 的 下列 特 征 :
-
外 观 、 文 档 保 存 和 Statement Completion ( 语 句 补 全 ) 选 项
-
制 表 符 和 缩 进
-
模 拟
-
字 体
图 3-11 Options 对 话 框 的 Editor 选 项 卡
在 对 话 框 的 Edit 选 项 卡 中 , 根 据 你 的 爱 好 来 选 择 编 辑 器 如 何 及 何 时 需 要 保 存 文档 ( 下 面 将 详 细 说 明 Automatic Reload Of Externally Modified Files ( 外 部 修 改 的文 件 自 动 重 新 加 载 )复 选 项 。你 也 可 以 指 定 编 辑 器 在 编 译 之 前 是 否 自 动 保 存 已 改变 的 文 件 , 以 及 在 保 存 文 档 之 前 是 否 提 示 你 。
值 得 一 提 的 是 同 一 页 中 的 Selection M argi n( 选 择 边 界 ) 复 选 项 。选 择 边 界 是 文 档窗 口 左 边 的 大 约 半 英 寸 宽 的 一 列 阴 影 区 。通 过 单 击 该 边 界 ,你 就 可 以 选 中 附 近 的一 整 行 。 该 空 格 也 可 以 保 留 书 签 的 图 标 , 以 及 后 面 我 们 将 在 第 11 章 中 提 到 的 调试 断 点 。 如 果 你 宁 愿 恢 复 这 些 空 白 来 显 示 文 档 , 清 除 掉 此 复 选 项 , 来 禁 用 选 择 空格 。
Visual C++ 文 本 编 辑 器 可 以 在 一 定 程 度 上 模 拟 BRIEF 或 Epsilon 程 序 员 的 编 辑器 。 如 果 你 习 惯 于 这 些 产 品 , 可 以 打 开 相 应 的 模 拟 选 项 。 单 击 Compatibility ( 兼容 性 ) 选 项 卡 , 然 后 从 列 表 中 选 择 编 辑 器 中 的 一 个 , 或 通 过 打 开 单 个 的 复 选 项 来设 置 想 要 的 选 项 。
Forma t( 格 式 ) 选 项 卡 允 许 你 给 编 辑 器 窗 口 指 定 字 体 类 型 和 颜 色 。 从 Category 列表 中 单 击 Source Window s( 源 窗 口 ), 来 查 看 当 前 的 字 体 。 默 认 情 况 下 , 字 体 为10 号 Courie r,但 你 可 以 把 它 改 成 任 何 你 所 想 要 的 类 型 和 大 小 。Color 区 允 许 你 为编 辑 器 中 不 同 的 标 记 和 文 本 ( 如 源 文 件 注 释 和 H T M L 标 记 ) 调 整 背 景 和 前 景 颜色 。 要 改 变 颜 色 , 从 列 表 中 选 择 一 个 条 目 , 然 后 从 组 合 框 中 选 择 想 要 的 颜 色 。
在 Developer Studio 之 外 编 辑 文 本
文 本 编 辑 器 同 用 户 喜 欢 的 字 处 理 程 序 共 享 了 许 多 特 征 。 Visual C++ 给 你 提 供 了 一个 非 常 强 大 的 程 序 编 辑 器 , 但 是 , 如 果 你 现 在 喜 欢 使 用 另 一 个 编 辑 器 , 也 可 以 。使 用 一 个 你 非 常 熟 悉 的 产 品 效 率 可 能 会 更 高 一 些 。并 且 , 如 果 你 从 来 没 有 使 用 过Developer Studio 环 境 , 除 了 使 用 别 的 编 辑 器 外 , 你 没 有 别 的 选 择 了 。 Visual C++ 编 辑 器 是 Developer Studio 整 体 的 一 部 分 , 而 不 是 一 个 独 立 的 程 序 。 你 只 能 从Developer Studio 中 访 问 该 编 辑 器 。
Visual C++ 文 本 编 辑 器 的 一 个 很 大 的 优 点 是 , 展 示 了 一 个 集 成 的 开 发 环 境 的 整 体应 是 什 么 样 子 。 当 编 译 器 在 源 代 码 中 发 现 错 误 时 ,它 自 动 把 编 辑 器 的 光 标 设 置 在第 一 个 出 错 的 语 句 上 , 准 备 让 你 改 正 错 误 。 双 击 列 表 中 的 下 一 个 错 误 , 光 标 就 会移 动 到 源 文 件 中 的 正 确 位 置 上 。 编 辑 完 后 , 只 需 单 击 Build ( 建 立 ) 工 具 栏 上 的Compile ( 编 译 ) 按 钮 , 就 可 以 把 修 订 过 的 文 本 重 新 提 交 给 编 译 器 。 Visual C++ 自 动 把 新 的 源 文 件 保 存 到 磁 盘 上 。在 环 境 之 外 的 编 辑 器 中 工 作 , 就 需 要 更 多 的 努力 。你 必 须 切 换 到 编 辑 器 ,把 光 标 移 到 编 译 出 错 的 语 句 行 ,改 正 之 后 ,保 存 文 件 , 然 后 再 切 换 回 Visual C++ 来 重 新 编 译 。
如 果 你 决 定 用 另 一 个 文 本 编 辑 器 来 编 写 和 维 护 源 代 码 ,你 应 该 对 Visual C++ 环 境作 两 个 小 小 的 改 动 。 首 先 , 如 果 你 打 算 长 期 使 用 另 外 的 一 个 编 辑 器 , 你 可 能 会 发现 从 Tool s( 工 具 )菜 单 中 通 过 编 辑 器 的 专 用 命 令 来 运 行 它 更 为 方 便 。通 过 在 Tools
( 工 具 ) 菜 单 中 放 置 一 个 新 的 命 令 , 你 可 以 在 环 境 内 部 启 动 编 辑 器 。 如 果 你 的 编
辑 器 从 命 令 行 接 受 文 件 名 , 可 以 配 置 该 命 令 , 以 使 编 辑 器 在 启 动 时 自 动 加 载 源 文件 。 添 加 一 个 新 的 Tools ( 工 具 ) 命 令 , 来 启 动 一 个 文 本 编 辑 器 ( 或 任 何 其 他 外部 程 序 ), 这 将 在 第 13 章 中 详 细 讨 论 。
应 该 做 的 第 二 个 改 变 是 对 默 认 设 置 的 细 小 改 动 。在 另 一 个 编 辑 器 中 打 开 一 个 文 件时 , 通 常 在 Visual C++ 中 会 打 开 同 一 个 文 件 。 这 发 生 在 编 译 和 调 试 代 码 的 过 程中 , 因 为 调 试 器 要 加 载 源 文 件 。 当 你 在 编 辑 器 中 改 变 , 并 保 存 文 件 后 , 切 换 回Visual C++ 来 重 新 编 译 时 , 环 境 可 以 识 别 到 打 开 的 文 件 副 本 不 再 是 当 前 的 内 容了 。 默 认 情 况 下 , 系 统 会 显 示 图 3-12 所 示 的 消 息 框 , 它 提 示 你 从 磁 盘 上 重 新 加载 新 的 文 件 。 你 的 回 答 通 常 会 是 Yes , 或 者 至 少 你 不 会 很 在 意 。 为 了 防 止 每 次 你切 换 回 Visual C++ 时 出 现 这 个 消 息 ,在 Tool s( 工 具 )菜 单 中 单 击 Option s( 选 项 )。选 中 图 3-11 所 示 的 Automatic Reload Of Externally Modified Files 复 选 项 , 来 让 编辑 器 自 动 加 载 改 变 了 的 文 件 , 而 不 再 提 示 你 。
图 3-12 在 外 部 编 辑 器 已 经 改 变 了 一 个 文 件 时 , 解 析 文 档 版 本
当 你 使 用 另 外 的 编 辑 器 时 , 你 就 已 经 与 Visual C++ 签 订 了 这 样 的 协 议 : 你 不 会 在两 个 编 辑 器 中 同 时 改 变 文 档 。然 而 ,环 境 可 以 处 理 对 文 档 的 同 时 改 变 。Visual C++ 承 认 外 部 改 动 , 因 为 当 环 境 重 新 获 得 输 入 焦 点 时 ,它 检 查 所 有 在 文 本 编 辑 器 中 打开 的 文 件 的 日 期 和 时 间 标 志 。出 于 安 全 的 目 的 ,环 境 重 新 加 载 拥 有 更 新 标 志 的 文件 , 但 Automatic Reload Of Externally Modified Files 设 置 仅 适 用 于 那 些 编 辑 器 自己 的 文 档 副 本 没 有 改 变 的 情 况 下 。如 果 编 辑 器 中 的 文 档 已 经 被 改 变 ,即 使 是 一 个字 符 ,不 论 Automatic Reload Of Externally Modified Files 复 选 项 如 何 设 置 ,Visual C++ 都 显 示 图 3-12 所 示 的 消 息 。 这 使 你 可 以 控 制 文 档 的 哪 个 版 本 是 正 确 的 。
第 4 章 资 源
-
般 地 , 当 我 们 说 起 一 个 程 序 的 数 据 时 , 我 们 指 的 是 那
些 用 X 或 pString 命 名 的源 代 码 里 的 变 量 。 一 个 典 型 的 W indows 应 用 程 序 也 有 另 一 类 叫 做 资 源 的 数 据 , 它 包 括 文 本 和 图 形 ,这 些 决 定 程 序 用 户 界 面 的 外 观 和 感 觉 。一 个 程 序 的 资 源 定 义界 面 元 素 如 下 :
-
菜 单
-
加 速 键
-
位 图 、 光 标 和 图 标
-
对 话 框 和 控 件
-
字 符 串
-
工 具 栏
-
当 W indows 调 用 一 个 程 序 时 , 它 从 程 序 的 可 执 行 文 件 里 读 取 程 序 代 码 和 初 始 化
数 据 的 数 值 , 并 把 它 们 拷 贝 到 分 配 的 内 存 里 。 有 些 情 况 下 , 资 源 数 据 保 留 在 程 序硬 盘 上 的 可 执 行 文 件 里 。 资 源 在 运 行 时 读 取 , 而 不 是 在 装 载 时 读 取 , 实 际 上 , 它是 程 序 创 建 窗 口 、显 示 对 话 框 或 装 载 位 图 时 ,从 EXE 文 件 或 DLL 文 件 里 读 取 的 。Visual C++ 提 供 一 些 资 源 编 辑 器 , 通 过 它 , 你 可 以 创 建 或 编 辑 一 个 项 目 的 资 源 数据 。 出 于 某 些 考 虑 , 本 章 是 前 面 几 章 的 延 续 , 它 描 述 怎 样 通 过 Visual C++ 的 文 字编 辑 器 创 建 和 编 辑 文 档 。 虽 然 这 里“ 文 档 ” 这 个 词 的 定 义 已 经 扩 展 , 它 包 括 的 内容 不 仅 仅 有 包 括 纯 文 本 , 还 有 其 他 格 式 , 这 些 格 式 的 编 辑 原 理 是 相 同 的 。
有 关 资 源 和 资 源 编 辑 器 的 主 题 范 围 广 泛 ,它 占 了 本 章 和 下 一 章 的 内 容 。本 章 覆 盖了 用 户 在 应 用 里 首 先 会 遇 到 的 界 面 元 素 , 这 种 资 源 数 据 包 括 菜 单 、 工 具 栏 、 加 速键 、 图 标 和 鼠 标 光 标 。 有 关 对 话 框 和 控 件 的 主 题 放 在 第 5 章 里 。
系 统 资 源
为 了 以 后 清 楚 所 讲 的 内 容 , 我 也 应 该 谈 谈 系 统 资 源 , 它 是 Windows 提 供 给 应 用程 序 的 公 共 资 源 数 据 集 。 系 统 资 源 实 际 上 是 借 给 应 用 程 序 的 , 要 知 道 , 在 应 用 程序 释 放 一 个 句 柄 时 , 它 以 显 式 的 方 式 归 还 给 系 统 , 在 应 用 程 序 终 止 时 , 它 以 隐 式的 方 式 归 还 给 系 统 。 某 些 系 统 资 源 , 例 如 鼠 标 光 标 , 是 自 动 提 供 的 , 这 样 , 就 不需 每 个 应 用 程 序 创 建 自 己 的 资 源 了 。虽 然 一 个 应 用 程 序 可 以 显 示 它 自 己 独 特 的 光标 ( 正 如 我 们 在 本 章 后 面 将 看 到 的 ), 但 是 , 使 用 箭 头 、 沙 漏 和 其 他 系 统 提 供 的位 图 更 容 易 些 。 在 对 程 序 员 提 供 方 便 的 同 时 , 它 也 可 以 保 证 用 户 在 程 序 之 间 切 换
时 , 不 会 对 各 种 光 标 感 到 不 知 所 措 。
其 他 的 系 统 资 源 , 例 如 设 备 上 下 文 和 系 统 插 入 符 , 不 能 够 被 一 个 应 用 程 序 复 制 , 也 不 能 够 被 真 正 类 比 为 本 章 中 所 描 述 的 程 序 资 源 。虽 然 在 一 个 程 序 的 外 观 上 ,内存 没 有 起 到 什 么 作 用 , 但 是 , 它 也 是 一 种 被 经 常 谈 及 的 系 统 资 源 , 因 为 它 作 为 堆分 配 给 程 序 , 这 是 程 序 所 要 求 的 。 控 件 是 另 一 种 当 我 们 谈 及 资 源 时 容 易 混 淆 的 潜在 的 资 源 。 在 一 个 程 序 的 资 源 数 据 里 , 程 序 声 明 的 仅 仅 是 它 想 使 用 的 控 件 类 型 , 例 如 窗 口 的 坐 标 , 或 者 可 能 是 初 始 化 状 态 。 控 件 的 显 示 和 操 作 是 由 系 统 传 递 的 。如 果 系 统 资 源 和 程 序 资 源 的 界 限 有 时 看 起 来 不 明 了 ,那 么 不 要 着 急 。当 你 在 本 章中 学 习 更 多 的 资 源 时 , 两 者 之 间 的 差 别 将 变 得 非 常 明 显 。
RC 资 源 脚 本 文 件
- 个 项 目 在 源 文 件 里 定 义 它 的 资 源 , 资 源 文 件 以 RC 为 扩
展 名 , 并 且 一 般 和 项 目具 有 相 同 的 名 字 。 RC 文 件 只 包 含 文 本 , 它 更 像 是 一 个 程 序 资 源 文 件 , 所 以 , 你可 以 用 一 个 文 本 编 辑 器 查 看 它 。在 文 件 里 , 你 将 发 现 一 些 定 义 字 符 串 和 菜 单 内 容的 表 格 ,但 是 ,没 有 包 含 位 图 和 图 标 的 图 形 数 据 。图 形 资 源 保 存 在 单 独 的 文 件 里 , 它 的 名 字 和 在 磁 盘 中 的 位 置 保 存 在 RC 文 件 里 。 RC 这 个 扩 展 名 指 示 出 这 个 文 件为 资 源 编 译 器 提 供 像 源 代 码 那 样 的 服 务 , 资 源 编 译 器 是 Visual C++ 的 一 个 独 立部 分 , 它 把 程 序 的 文 本 和 图 形 资 源 编 译 成 目 标 文 件 形 式 , 这 样 , 链 接 器 可 以 把 它联 编 到 EXE 文 件 里 。 一 个 项 目 的 RC 文 件 经 常 叫 做 资 源 脚 本 或 资 源 定 义 文 件 。
资 源 脚 本 文 件 是 可 选 择 的 。 不 与 用 户 交 互 的 窗 口 应 用 程 序 不 需 要 资 源 ,对 一 个 程序 来 说 , 更 可 能 在 运 行 时 随 时 创 建 所 有 的 资 源 。 但 是 , 正 如 你 将 在 本 章 中 看 到 的那 样 ,资 源 脚 本 利 于 开 发 者 进 行 开 发 ,因 为 资 源 脚 本 从 源 代 码 中 分 离 出 用 户 界 面元 素 。 通 过 使 用 Visual C++ 资 源 编 辑 器 , 开 发 者 可 以 设 计 一 个 界 面 , 看 到 它 是 什么 样 子 ,并 且 可 以 通 过 少 许 鼠 标 单 击 来 改 变 它 。并 且 ,由 于 程 序 要 面 向 国 际 市 场 , 所 以 资 源 脚 本 是 必 须 的 , 因 为 它 们 允 许 转 换 者 修 改 用 户 界 面 ,而 不 用 接 触 程 序 源代 码 。
- 个 Visual C++ 项 目 只 认 可 一 个 主 要 的 RC 文 件 。 如 果 你 想
使 用 Project( 项 目 ) 菜 单 里 的 Add To Project( 添 加 到 项 目 ) 命 令 添 加 一 个 额 外 的 RC 文 件 , 集 成 环境 会 警 告 你 , 当 编 译 这 个 项 目 时 , 这 个 文 件 将 不 会 被 编 译 , 如 下 所 示 .
然 而 , 一 个 项 目 可 以 有 任 何 数 目 的 资 源 脚 本 文 件 , 但 是 , 所 有 的 二 级 文 件 只 能 通过 #include 语 句 添 加 到 RC 文 件 里 。 例 如 , AppWizar d( 应 用 程 序 向 导 ) 自 动 创 建第 二 个 资 源 文 件 , 这 个 文 件 以 项 目 文 件 名 作 为 名 字 , 以 RC2 作 为 扩 展 名 , 它 提供 了 一 个 存 放 你 以 前 开 发 和 测 试 的 任 何 资 源 的 好 地 方 , 你 不 需 进 一 步 的 修 改 。为了 看 看 RC2 文 件 怎 样 包 含 在 AppWizard ( 应 用 程 序 向 导 ) 创 建 的 项 目 里 , 打 开项 目 , 并 从 View ( 查 看 ) 菜 单 里 选 择 Resource Include s( 资 源 包 括 ) 项 , 然 后 在Compile-Time Directives ( 编 译 时 伪 指 令 ) 控 件 里 向 下 滚 动 , 到 下 面 这 一 行 ( 在这 里 project 是 项 目 名 ):
#include “ res\project.rc2 ” //non- M icrosoft Visual C++ resource
包 含 在 补 充 文 件 里 的 所 有 资 源 均 将 编 译 , 并 链 接 到 项 目 的 可 执 行 文 件 里 。 但 是 ,
当 你 使 用 一 个 Visual C++ 资 源 编 辑 器 对 主 RC 文 件 操 作 时 , 将 不 能 访 问 它 。 这 就是 为 什 么 只 有 完 成 的 和 测 试 过 的 资 源 才 应 该 包 含 在 RC2 中 的 原 因 。 资 源 编 译 器读 取 所 有 的 脚 本 文 件 , 并 产 生 一 个 以 RES 做 后 缀 的 编 译 过 的 二 进 制 文 件 , 它 类似 于 C/C++ 编 译 器 产 生 的 OBJ 文 件 .
在 第 1 章 中 描 述 的 作 为 环 境 的 Workspace ( 工 作 空 间 ) 窗 口 , 列 出 了 在 主 RC 文件 里 定 义 的 项 目 资 源 。 当 项 目 打 开 时 , 单 击 ResourceView ( 资 源 查 看 ) 选 项 卡 , 并 通 过 单 击 靠 近 文 件 夹 图 标 的 加 号 展 开 列 表 。为 了 在 适 当 的 编 辑 器 里 打 开 一 个 资源 ( 我 们 将 立 刻 做 这 件 事 情 ), 双 击 列 表 里 的 资 源 。 图 4-1 显 示 了 ResourceView
( 资 源 查 看 ) 窗 格 中 的 资 源 , 这 是 名 为 Demo 的 AppWizard ( 应 用 程 序 向 导 ) 项目 中 的 。
通 过 AppWizard ( 应 用 程 序 向 导 ) 创 建 的 默 认 RC 文 件 是 广 泛 的 , 包 括 冗 长 的 字符 串 表 、菜 单 脚 本 和 与 交 叉 开 发 平 台 有 关 的 代 码 。如 果 你 接 受 创 建 新 的 应 用 程 序时 AppWizard ( 应 用 程 序 程 序 向 导 ) 产 生 的 所 有 默 认 资 源 , 那 么 , 最 终 将 得 到 一个 将 近 400 行 的 RC 文 件 。 你 可 以 尝 试 在 一 个 文 本 编 辑 器 里 修 改 RC 文 件 , 删 除通 过 AppWizard( 应 用 程 序 程 序 向 导 ) 产 生 的 多 余 的 代 码 行 , 减 少 文 件 尺 寸 到 易于 管 理 的 大 小 。 但 是 , 这 样 做 意 味 着 , 以 后 当 你 使 用 一 个 Visual C++ 的 资 源 编 辑器 修 改 一 种 资 源 时 , 就 会 有 麻 烦 。 虽 然 你 可 以 得 到 一 个 有 效 的 RC 文 件 , 但 是 , 不 幸 的 是 , Visual C++ 不 再 认 为 它 是 AppWizard ( 应 用 程 序 程 序 向 导 ) 产 生 的 。你 仍 然 可 以 通 过 一 个 编 辑 器 修 改 资 源 , 但 是 , 当 你 保 存 修 改 后 的 文 件 时 , Visual C++ 用 一 个 新 的 RC 文 件 重 写 你 的 最 低 限 要 求 的 RC 文 件 , 它 包 含 许 多 你 在 前 面
已 经 删 除 的 由 AppWizard( 应 用 程 序 程 序 向 导 ) 生 成 的 多 余 代 码 。 唯 一 可 供 选 择的 是 用 一 个 不 同 的 文 件 名 保 存 修 改 后 的 文 件 , 然 后 , 使 用 文 本 编 辑 器 从 新 文 件 里拷 贝 你 想 要 的 行 ,并 粘 贴 到 最 初 的 资 源 脚 本 。我 推 荐 你 学 习 使 用 由 AppWizar d( 应用 程 序 程 序 向 导 ) 产 生 的 巨 大 的 RC 文 件 , 除 了 一 些 小 的 变 化 外 , 只 通 过 资 源 编辑 器 来 修 改 资 源 。
图 4-1 Workspace 窗 口 的 ResourceView 窗 格
Resource.h 头 文 件
项 目 里 的 每 一 个 资 源 或 者 通 过 常 量 标 识 符 , 或 者 至 少 通 过 一 个 字 符 串 名 , 来 加 以区 别 。 例 如 , 在 图 4-1 中 , 假 想 的 Demo 程 序 的 资 源 都 用 恒 定 的 值 标 识 : IDR_MAINFRAME 是 菜 单 和 工 具 栏 , IDR_DEMOTYPE 是 程 序 的 一 个 图 标 , IDD_ABOUTBOX 是 Abou t( 关 于 ) 对 话 框 。 用 于 标 识 一 个 项 目 的 资 源 常 量 一 般是 在 以 Resource.h 命 名 的 文 件 里 。 AppWizard ( 应 用 程 序 程 序 向 导 ) 自 动 创 建Resource.h 作 为 项 目 的 一 部 分 , 对 资 源 标 识 符 指 定 标 准 MFC 的 资 源 前 缀 。 表 格4-1 列 出 一 些 MFC 使 用 的 标 识 前 缀 。
表 |
4-1 |
标 准 |
MFC 标 识 符 前 缀 |
|
---|---|---|---|---|
前 缀 |
资 源 类 型 |
|||
IDR_ |
主 菜 单 、工 具 栏 、加 速 键 表 和 应 用 程 序 图标 |
|||
IDD_ |
对 话 框 |
续 表
IDC_ 控 件 和 光 标
IDS_ 字 符 串
IDP_ 为 消 息 框 提 示 字 符 串
ID_ 菜 单 命 令
常 量 标 识 符 可 以 由 字 母 ( 大 写 或 小 写 )、 数 字 和 下 划 线 组 成 , 但 是 不 能 以 一 个 数字 开 头 。
C 程 序 把 标 识 符 成 员 认 为 是 明 显 的 常 量 或“ 定 义 ”,但是 , Visual C++ 有 时 将 它 们作 为 符 号 。 从 技 术 上 来 说 , 符 号 是 在 源 代 码 里 标 明 内 存 地 址 的 名 字 , 例 如 一 个 变量 或 一 个 函 数 名 字 。 我 们 将 在 第 11 章 里 看 到 , 编 译 器 怎 样 生 成 一 个 程 序 里 的 符号 列 表 , 通 过 阅 读 它 , 调 试 器 可 以 知 道 程 序 里 的 变 量 和 函 数 名 。 不 要 混 淆 资 源 符号 和 源 代 码 里 的 符 号 。 毫 无 疑 问 , Visual C++ 的 设 计 者 选 择 单 词 符 号 , 他 们 认 为资 源 脚 本 也 是 一 种 源 代 码 和 资 源 标 识 符 , 类 似 于 程 序 源 代 码 里 的 变 量 名 字 。
你 可 以 改 变 列 在 Workspace ( 工 作 空 间 ) 窗 口 里 ResourceView ( 资 源 查 看 ) 窗 格里 的 一 个 资 源 标 识 符 的 名 字 ,或 以 数 字 表 示 的 值 。首 先 通 过 展 开 适 当 的 文 件 夹 图标 , 找 到 标 识 符 名 字 , 如 图 4-1 所 示 。 然 后 , 单 击 列 表 里 的 标 识 符 选 择 它 , 并 单
击 View ( 查 看 ) 菜 单 里 的 Properties( 属 性 )。 你 也 可 以 右 击 一 个 标 识 符 , 并 从弹 出 的 上 下 文 菜 单 里 选 择 Properties 。 在 任 何 一 种 方 法 里 , 都 要 通 过 在 ID 控 件 里重 新 输 入 标 识 符 名 字 来 改 变 它 。同 时 ,你 可 以 像 下 面 这 样 给 名 字 添 加 一 个 以 数 字表 示 的 整 型 值 , 来 给 它 赋 值 :
IDD_ABOUTBOX_NEW = 3001
按 下 Enter 键 时 , 一 个 星 号 出 现 在 ResourceView ( 资 源 查 看 ) 窗 格 顶 部 的 项 目 行附 近 ,它 表 明 你 已 经 改 变 了 它 ,但 是 还 没 有 保 存 。从 Fil e( 文 件 )菜 单 里 选 择 Save
( 保 存 ) 命 令 , 使 Visual C++ 重 写 Resource.h 文 件 , 用 新 的 标 识 符 代 替 #define
语 句 里 旧 的 标 识 符 。
从 理 论 上 来 说 , 你 可 以 给 一 个 资 源 标 识 符 赋 以 从 1 到 6553 5( 0xFFFF ) 中 的 任 何一 个 值 。 然 而 , Windows 为 系 统 菜 单 项 保 留 了 0xF000 及 它 上 面 的 值 , MFC 为 内部 使 用 保 留 了 从 0xE000 到 0xEFFF 之 间 的 值 , 所 以 , 你 应 该 使 自 己 的 标 识 符 值保 持 在 1 到 57343 之 间 ( 0xDFFF )。 标 识 符 的 值 被 限 制 在 W O R D 大 小 , 而 不 是DWORD 大 小 ,这 是 因 为 W M _ C O M M A N D 消 息 在 wParam 消 息 参 数 的 低 字 节 里传 递 标 识 符 的 值 。
你 也 可 以 在 Resource Symbols( 资 源 符 号 ) 浏 览 器 里 改 变 、 添 加 或 删 除 标 识 符 符号 , 如 图 4-2 所 示 , 这 些 标 识 符 是 由 AppWizard ( 应 用 程 序 程 序 向 导 ) 或 其 他 一种 Visual C++ 资 源 编 辑 器 创 建 的 RC 文 件 提 供 的 。要 打 开 视 图 ,单 击 Vie w( 查 看 ) 菜 单 里 的 Resource Symbols( 资 源 符 号 )。 视 图 将 显 示 所 有 在 Resource.h 中 定 义 的
标 识 符 , 要 给 标 识 符 重 命 名 或 改 变 其 值 , 从 列 表 里 选 择 它 并 单 击 Change( 更 改 ) 按 钮 。 New ( 新 建 ) 按 钮 让 你 在 Resource.h 里 添 加 新 的 标 识 符 , 并 给 它 们 赋 值 。在 你 关 闭 Resource Symbols( 资 源 符 号 ) 对 话 框 之 后 , 右 击 ResourceView ( 资 源 查看 ) 窗 格 里 的 项 目 行 , 并 选 择 Save ( 保 存 ) 命 令 , 把 新 的 值 写 到 Resource.h 文件 里 。
图 4-2 Resource Symbols 浏 览 器 , 它 通 过 View 菜单上的 Resource Symbols 命令调用
符 号 浏 览 器 是 为 最 佳 利 用 由 AppWizard ( 应 用 程 序 程 序 向 导 ) 或 其 他 一 种 Visual C++ 资 源 编 辑 器 创 建 的 RC 文 件 而 设 计 的 。 你 可 以 查 看 所 有 在 项 目 RC 文 件 里 引用 的 标 识 符 的 定 义 ,但是,浏览器只可以修改在 Resource.h 头 文 件 里 定 义 的 标 识符 。 它 把 定 义 在 其 他 包 含 文 件 里 的 标 识 符 当 作 只 读 的 , 并 不 提 供 修 改 它 们 名 字 和值 的 方 法 。 要 看 这 些 标 识 符 , 单 击 浏 览 器 对 话 框 里 的 Show Read-Only Symbols
( 显 示 只 读 符 号 ) 检 查 框 。 例 如 , AppWizard ( 应 用 程 序 程 序 向 导 ) 添 加 到 RC
文 件 里 的 这 一 行 , 我 们 将 在 本 章 后 面 再 次 见 到 它 :
#include "afxres.h"
当 你 选 择 了 Show Read-Only Symbols 复 选 框 ,浏 览 器 将 包 含 在 Afxres.h 文 件 里 的所 有 符 号 的 列 表 。你 可 以 区 别 出 在 列 表 里 的 只 读 符 号 , 因 为 可 修 改 的 符 号 以 黑 体字 显 示 。
在 In Use ( 正 在 使 用 ) 列 里 , 一 个 复 选 标 记 表 明 , 在 RC 文 件 里 , 一 个 符 号 标 识一 种 资 源 。 在 你 开 发 一 个 程 序 时 , 偶 尔 可 能 要 改 变 标 识 符 的 名 字 , 没 有 关 系 , 但是 Visual C++ 不 删 除 旧 的 名 字 , 而 为 新 的 标 识 符 在 Resource.h 中 添 加 一 个 定 义 。一 些 标 识 符 最 终 会 成 为 孤 标 识 符 ( orphan s), 它 在 Resource.h 文 件 里 定 义 , 但 是在 RC 文 件 里 任 何 地 方 都 没 有 使 用 。在 In Use 列 中 , 我 们 可 以 很 容 易 确 定 孤 标 识符 。 要 删 除 一 个 标 识 符 , 就 是 从 Resource.h 文 件 中 删 除 它 的 #define 语 句 , 那 么从 列 表 里 选 择 它 , 并 单 击 Delete 按 钮 。 删 除 将 在 你 下 一 次 单 击 Save( 保 存 ) 命令 时 生 效 。 记 住 , 虽 然 浏 览 器 告 诉 你 , 只 有 复 选 的 符 号 才 会 出 现 在 RC 文 件 里 ,
但 是 , 这 并 不 意 味 着 这 个 符 号 不 在 源 代 码 或 其 他 资 源 文 件 的 其 他 地 方 使 用 。
AppWizard 资 源 的 例 子
在 深 入 说 明 之 前 , 让 我 们 看 看 一 部 分 AppWizard( 应 用 程 序 程 序 向 导 ) 为 假 想 的Demo 程 序 生 成 的 资 源 脚 本 文 件 。 我 们 已 经 见 到 , AppWizard ( 应 用 程 序 程 序 向导 ) 自 动 的 为 About ( 关 于 ) 对 话 框 创 建 一 个 资 源 脚 本 , 还 有 一 个 MFC 图 标 。在 生 成 的 Demo.rc 文 件 里 , 对 话 框 脚 本 看 起 来 像 下 面 这 样 :
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 217, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Demo" FONT 8, "MS Sans Serif" BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,10,22,20,20 LTEXT "Demo Version 1.0",IDC_STATIC,45,10,115,8
LTEXT "Copyright 1998 ", IDC_STATIC,40,25,119,8 DEFPUSHBUTTON "OK",IDOK,178,7,32,14,WS_GROUP
END
上 述 命 令 定 义 了 下 面 所 示 的 对 话 框 , 它 是 通 过 选 择 Demo 程 序 的 Hel p( 帮 助 )菜单 里 的 About 来 调 用 的 :
虽 然 一 行 也 没 写 , 但 是 , 效 果 还 不 错 。 然 而 , AppWizard ( 应 用 程 序 程 序 向 导 ) 并 不 是 适 合 于 任 何 场 合 。 要 看 一 下 不 使 用 AppWizar d( 应 用 程 序 程 序 向 导 ) 将 会是 什 么 样 , 本 章 的 其 余 部 分 开 发 了 一 个 不 使 用 AppWizar d( 应 用 程 序 程 序 向 导 ), 而 是 从 头 开 始 的 资 源 程 序 , 并 讨 论 这 个 方 法 的 利 弊 。
例 程 DiskPie1 简 介
这 里 , 我 们 将 开 始 用 连 续 的 几 节 逐 步 开 发 一 个 叫 做 D iskPie1 的 例 程 。 每 一 节 集中 一 种 资 源 类 型 , 我 们 将 从 菜 单 和 加 速 键 开 始 , 接 着 是 状 态 栏 、 位 图 和 工 具 栏 。每 一 节 都 以 总 体 讨 论 一 种 资 源 类 型 开 始 , 以 将 这 种 资 源 加 入 D iskPie1 结 束 , 并
示 范 怎 样 用 适 当 的 Visual C++ 编 辑 器 创 建 或 修 改 一 种 资 源 。 当 我 们 结 束 的 时 候 , D iskPie1 将 成 为 一 个 有 用 的 工 具 ,它 快 速 查 看 当 前 内 存 使 用 情 况 和 可 用 的 磁 盘 空间 。
为 了 更 好 地 开 发 实 践 , 我 们 将 在 写 任 何 代 码 之 前 , 首 先 对 程 序 进 行 说 明 。 这 个 说明 将 使 你 了 解 我 们 将 加 入 到 程 序 中 的 资 源 ,并 使 我 们 可 以 很 容 易 地 看 到 它 们 怎 样一 起 工 作 , 形 成 一 个 和 谐 的 界 面 。 下 面 是 D iskPie1 的 主 要 说 明 :
- 描 述 : DiskPie1 是 一 个 用 MFC 写 的 实 用 程 序 , 它 显 示
两 份 饼 图 。 通 过对 菜 单 或 工 具 栏 的 选 择 , 这 个 图 显 示 指 定 的 磁 盘 驱 动 器 上 的 存 储 空 间分 配 。 饼 图 的 一 部 分 描 述 已 经 分 配 的 空 间 , 而 其 余 部 分 显 示 未 分 配 的
空 间 。 有 标 签 将 两 者 明 显 区 分 开 。
- 主 窗 口 : 程 序 有 四 个 菜 单 , 叫 做 File , Chart, View
和 Help 。 File ( 文件 ) 菜 单 只 包 含 一 个 Exit 命 令 , Help ( 帮 助 ) 菜 单 有 一 个 显 示 程 序 信息 的 About 命 令 。 View ( 查 看 ) 菜 单 允 许 用 户 显 示 或 隐 藏 工 具 栏 和 状
态 栏 。 Chart 菜 单 开 始 时 只 包 含 一 个 命 令 , 叫 做 M emory , 它 显 示 内 存使 用 状 况 。 在 运 行 的 时 候 , DiskPie1 搜 索 与 系 统 相 连 的 磁 盘 驱 动 器 , 包 括 R A M 磁 盘 和 远 程 网 络 驱 动 器 , 并 把 它 们 添 加 到 Chart 菜 单 里 。此程 序 忽 略 软 盘 驱 动 器 、 CD 驱 动 器 及 其 他 可 卸 式 驱 动 器 。
- 工 具 栏 和 加 速 键 : 可 停 靠 的 工 具 栏 和 键 盘 命 令 补
充 了 程 序 的 菜 单 , 允许 用 户 通 过 单 击 按 钮 或 通 过 按 表 示 从 C 到 Z 的 特 定 驱 动 器 的 键 , 来 显
示 表 示 使 用 状 况 的 饼 图 。
-
状 态 栏 : 标 识 当 前 选 择 的 菜 单 或 工 具 栏 。
-
上 下 文 菜 单 : DiskPie1 不 提 供 上 下 文 菜 单 。
D iskPie1 可 以 很 容 易 地 通 过 AppWizard 生 成 骨 架 代 码 , 但 是 , 我 不 选 择 这 样 做 , 有 两 个 原 因 。 首 先 , D iskPie1 并 不 是 那 种 文 档 / 视 图 形 式 的 应 用 程 序 程 序 , 而AppWizard 创 建 文 件 时 , 注 重 的 是 这 种 形 式 , 并 且 , 删 除 AppWizard 生 成 的 多 余资 源 描 述 可 能 是 冗 长 乏 味 的 过 程 。 第 二 , 我 们 已 经 谈 到 过 AppWizard 。现在,应当 看 看 在 Visual C++ 里 从 底 层 创 建 一 个 项 目 会 怎 样 。 下 面 的 几 节 并 没 有 忽 略AppWizard , 不 管 怎 样 , 在 默 认 的 情 况 下 , 它 们 都 描 述 AppWizard , 这 样 , 你 能够 看 到 , 通 过 使 用 AppWizard 创 建 D iskPie1 这 样 的 小 项 目 将 得 到 或 失 去 什 么 。
讨 论 假 设 D iskPie1 以 一 个 没 有 资 源 文 件 的 空 项 目 开 始 。 如 果 你 喜 欢 在 这 里 略 述的 步 骤 从 头 开 始 创 建 这 个 项 目 ,那么从 Fil e( 文 件 ) 菜 单 选 择 Ne w( 新 建 ) 命 令 , 然 后 单 击 Project( 项 目 ) 选 项 卡 , 选 择 W in32 Application 图 标 。 输 入 项 目 名 字 , 然 后 单 击 OK ( 确 定 ) 按 钮 。 Win32 Application Wizard 只 显 示 一 个 单 独 的 步 骤 , 提 供 在 三 种 不 同 的 准 备 状 态 下 , 以 设 置 一 个 新 的 项 目 , 单 击 Finis h( 完 成 ) 按 钮 , 接 受 为 空 项 目 选 择 的 默 认 设 置 。
如 果 你 已 经 运 行 Setup 程 序 , 从 所 附 CD 中 将 DiskPie1 拷 贝 到 你 的 硬 盘 , 那 么 你可 能 更 喜 欢 打 开 项 目 , 不 用 自 己 创 建 资 源 , 而 继 续 进 行 讨 论 。 要 打 开 已 经 完 成 的项 目 , 从 File( 文 件 ) 菜 单 选 择 Open Workspace( 打 开 工 作 空 间 ) 命 令 , 并 在 硬盘 驱 动 器 上 浏 览 D iskPie1 项 目 所 在 的 文 件 夹 。 双 击 D iskPie1.dsw 打 开 项 目 。
打 开 已 有 的 项 目
新 项 目 就 像 新 文 件 一 样 , 开 始 要 使 用 New 命 令 , 并 在 一 个 Visual C++ 向 导 的 帮助 下 ( 如 AppWizard 或 W in32 Application ), 设 置 新 的 项 目 。 一 旦 向 导 完 成 了 它的 工 作 , 此 项 目 就 不 再 使 用 New 命 令 了 。 要 打 开 一 个 已 有 的 项 目 , 例 如 从 配 套光 盘 中 安 装 的 任 何 一 个 项 目 , 需 从 File 菜 单 中 选 择 Open Workspace 命 令 , 并 浏览 到 项 目 的 文 件 夹 。对 于 最 近 使 用 过 的 项 目 , 相 同 菜 单 上 的 Recent Workspace 命令 提 供 了 更 好 的 方 便 性 。
如 果 你 愿 意 , Visual C++ 环 境 可 以 在 启 动 时 自 动 打 开 最 近 的 项 目 。 对 于 你 已 经 花费 了 许 多 时 间 的 冗 长 的 项 目 , 这 个 特 征 非 常 方 便 。 单 击 Tools ( 工 具 ) 菜 单 上 的Option s( 选 项 ),并 滚 动 到 右 边 ,找 到 Workspace 选 项 卡 ,然 后 ,激 活 标 为 Reload Last Workspace At Startup ( 在 启 动 时 重 新 加 载 上 次 的 工 作 空 间 ) 复 选 框 。
配 置 DiskPie1 项 目
W in32 Application 向 导 只 生 成 几 个 文 件 , 它 们 用 于 建 立 项 目 的 主 干 内 容 。 此 向 导也 假 设 项 目 不 使 用 M F , 对 D iskPie1 来 说 , 这 是 不 正 确 的 假 设 。 在 选 择 W in32 Application 创 建 像 DiskPie1 一 样 的 MFC 程 序 之 后 , 你 必 须 配 置 这 个 项 目 , 来 识别 MFC 库 文 件 。 正 如 在 第 2 章 里 描 述 的 那 样 , 这 是 通 过 在 Project Settings 对 话框 General 选 项 卡 的 一 个 开 关 来 实 现 的 。 通 过 从 Projec t( 项 目 ) 菜 单 选 择 Setting 打 开 对 话 框 , 从 对 话 框 的 左 上 角 的 组 合 框 里 选 择 All Configuration s( 所 有 配 置 ),
并 为 项 目 选 择 静 态 或 动 态 链 接 库 。 图 4-3 显 示 后 一 种 选 择 。
图 4-3 在 Project Settings 对 话 框 中 选 择 到 MFC 的动态链接
一 旦 打 开 了 初 具 雏 形 的 DiskPie1 项 目 , 并 正 确 进 行 配 置 , 我 们 便 可 以 开 始 为 它
创 建 资 源 , 并 添 加 DiskPie1.rc 和 Resource.h 文 件 了 。 对 于 D iskPie1 这 样 一 个 小程 序 , 它 使 用 了 很 多 资 源 , 所 以 , 大 部 分 工 作 是 创 建 资 源 数 据 。 在 完 成 资 源 的 创建 之 后 , 我 们 将 为 程 序 写 出 实 际 的 代 码 。
菜 单 和 加 速 键
图 4-4 显 示 了 AppWizard 创 建 的 默 认 菜 单 系 统 。 你 可 以 看 到 , 图 中 的 菜 单 和
AppWizard 放 在 RC 文 件 中 的 菜 单 脚 本 是 对 应 的 : IDR_MAINFRAME MENU PRELOAD DISCARDABLE BEGIN
POPUP "&File" BEGIN
MENUITEM "&New\tCtrl+N", ID_FILE_NEW
MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
MENUITEM "Save &As...", ID_FILE_SAVE_AS MENUITEM SEPARATOR
MENUITEM "&Prin t… \tCtrl+P", ID_FILE_PRINT
MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW
MENUITEM "P&rint Setup … ", ID_FILE_PRINT_SETUP MENUITEM SEPARATOR
MENUITEM "Recent File",
ID_FILE_MRU_FILE1,GRAYED MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO MENUITEM SEPARATOR
MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
END
POPUP "&View" BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Help" BEGIN
MENUITEM "&About Demo...", ID_APP_ABOUT
END
END
图 4-4 由 AppWizard 生 成 的 菜 单 系 统
脚 本 的 第 一 行 给 菜 单 栏 一 个 IDR_MAINFRAME 标 识 号 ,它 在 AppWizard 添 加 到项 目 的 Resource.h 文 件 里 定 义 。像 文 件 里 的 所 有 标 识 符 一 样 ,IDR_MAINFRAME 只 是 AppWizard 的 默 认 名 字 。 你 可 以 为 资 源 指 定 你 想 要 的 任 何 名 字 或 值 。
PRELOAD 和 DISCARDABLE 伪 指 令 在 Win32 应 用 程 序 程 序 脚 本 中 并 不 是 必 须的 。 只 对 16 位 程 序 有 意 义 的 PRELOAD 告 诉 W indow s, 当 它 开 始 加 载 程 序 时 , 将 菜 单 资 源 数 据 拷 贝 到 内 存 , 而 不 是 以 后 当 程 序 创 建 主 窗 口 时 , 再 打 开 程 序 的EXE 文 件 , 并 读 取 菜 单 数 据 。 不 需 要 DISCARDABLE 伪 指 令 , 是 因 为 在 W in32 里 , 所 有 的 资 源 都 是 可 丢 弃 的 。 这 意 味 着 , 操 作 系 统 可 以 自 由 地 从 物 理 内 存 中 删除 程 序 的 资 源 数 据 , 以 使 其 他 程 序 能 够 得 到 这 些 内 存 。 当 程 序 再 次 获 得 焦 点 , 并需 要 那 些 删 除 的 资 源 时 , 系 统 从 程 序 的 EXE 文 件 中 重 新 读 取 数 据 。 这 可 能 是 因
为 资 源 是 静 态 只 读 数 据 , 在 内 存 里 的 副 本 和 磁 盘 上 的 一 样 。 相 反 , 从 内 存 中 移 去动 态 数 据 由 虚 拟 内 存 管 理 器 完 成 , 但 是 , 虚 拟 内 存 管 理 器 必 须 首 先 在 内 存 被 用 于其 他 目 的 之 前 , 将 数 据 保 存 到 系 统 交 换 文 件 。
资 源 脚 本 文 件 的 缩 进 排 列 显 示 了 BEGIN 和 END 语 句 之 间 的 资 源 的 级 别 。第 一 级定 义 了 完 整 的 菜 单 资 源 , 包 括 菜 单 栏 , 它 被 叫 做 顶 级 菜 单 。 BEGIN-END 对 的 第二 级 指 明 每 一 个 下 拉 菜 单 的 内 容 。 每 一 个 POPUP 语 句 跟 在 一 个 显 示 在 菜 单 栏 上的 菜 单 标 题 之 后 , 随 后 的 MENUITEM 语 句 指 明 列 在 菜 单 上 的 命 令 。 菜 单 上 的 一行 叫 做 命 令 或 菜 单 项 。
- 些 菜 单 命 令 包 含 键 盘 组 合 键 , 例 如 Ctrl+N 相 当 于 New (
新 建 ) 命 令 , Ctrl+O 相 当 于 Open ( 打 开 ) 命 令 。 如 你 所 知 , 这 些 组 合 键 提 供 像 快 捷 键 那 样 的 服 务 , 它 让 用 户 选 择 命 令 , 而 不 用 通 过 菜 单 系 统 。 例 如 , Ctrl+O 立 即 显 示 Ope n( 打 开 ) 对 话 框 , 与 从 File ( 文 件 ) 菜 单 里 选 择 Open ( 打 开 ) 命 令 的 效 果 一 样 。 加 速 键的 麻 烦 是 用 户 必 须 记 住 它 们 , 它 们 出 现 在 菜 单 中 , 是 为 了 提 醒 用 户 , 还 有 一 种 更容 易 的 方 法 来 选 择 命 令 。 加 速 键 要 求 在 RC 文 件 中 附 加 的 表 格 , 我 们 将 立 即 看 到这 些 。
加 速 组 合 键 之 前 的 \t 是 一 个 制 表 符 , 它 整 齐 地 在 菜 单 上 排 列 加 速 键 。 你 也 可 以 使用 \a 代 替 \t, 在 菜 单 上 右 对 齐 排 列 文 本 , 以 具 有 一 致 性 。 如 果 你 使 用 \a 来 排 列 菜单 上 的 任 何 加 速 组 合 键 , 那 么 , 你 应 该 在 其 他 行 上 不 使 用 \t。 如 果 不 这 样 做 , 将使 Windows 混 乱 , 导 致 菜 单 文 本 排 列 凌 乱 。\a 字 符 比 \t 对 菜 单 的 控 制 更 好 些 。 如
果 菜 单 上 的 文 本 看 起 来 太 拥 挤 , 那 么 在 \a 字 符 前 输 入 几 个 空 格 , 可 以 加 宽 菜 单 , 并 使 加 速 键 和 命 令 之 间 的 间 隔 更 远 。 在 每 一 个 菜 单 命 令 里 的 字 符 & 把 它 后 面 的 字符 作 为 菜 单 的 助 记 符 。 如 图 4-4 所 示 , 在 菜 单 里 , 一 个 助 记 符 以 下 划 线 显 示 , 以便 用 户 识 别 它 。对 于 一 个 菜 单 或 菜 单 栏 来 说 ,助 记 符 应 该 是 唯 一 的 ,例 如 ,Format 菜 单 应 该 有 一 个 不 是 “ F ” 的 其 他 助 记 符 , 以 便 避 免 同 File ( 文 件 ) 菜 单 冲 突 。但 是 , 使 用 唯 一 的 助 记 符 只 是 一 个 建 议 , 而 不 是 一 条 规 则 , 如 果 一 个 菜 单 栏 或 下拉 菜 单 在 两 个 或 更 多 的 地 方 包 含 相 同 的 助 记 符 , 那 么 , 当 用 户 按 下 助 记 符 时 , W indows 将 依 次 加 亮 每 一 个 命 令 , 并 且 只 激 活 你 按 下 Enter 键 时 选 择 的 命 令 。 下一 节 描 述 的 菜 单 编 辑 器 可 以 通 过 在 弹 出 的 上 下 文 菜 单 上 的 命 令 ,来 检 查 重 复 的 助记 符 。 在 编 辑 器 工 作 区 域 的 任 何 地 方 右 击 , 将 打 开 这 个 菜 单 :
助 记 符 和 加 速 键 并 不 是 相 同 的 东 西 。 加 速 键 不 需 要 通 过 菜 单 系 统 , 就 可 以 激 活 一个 命 令 , 然 而 , 下 划 线 助 记 符 只 有 当 菜 单 可 见 时 才 是 可 用 的 。
每 一 个 菜 单 命 令 都 有 一 个 以 ID _ 作 为 前 缀 , 紧 接 着 是 描 述 命 令 的 名 字 组 成 的 辅 助
标 识 符 。 包 括 ID_ 前 缀 的 标 识 符 是 完 全 由 用 户 决 定 , 前 面 的 菜 单 脚 本 只 是AppWizard 提 出 的 ( 然 而 , 正 如 我 们 将 看 到 的 , 使 用 MFC 已 经 定 义 的 特 定 符 号名 是 有 好 处 的 )。 只 有 通 过 菜 单 标 识 符 , 程 序 才 能 引 用 菜 单 事 件 。 当 用 户 单 击 一个 菜 单 命 令 , 或 按 下 一 个 加 速 键 时 , W indows 用在 wParam 低 字 节 里 的 命 令 标 识符 给 主 窗 口 发 出 W M _ C O M M A N D 消 息 。 如 果 这 个 命 令 是 用 户 按 下 加 速 键 响 应的 , 那 么 wParam 的 高 字 节 是 TRU E , 如 果 是 通 过 菜 单 选 择 响 应 的 , 那 么 wParam 的 高 字 节 是 FALSE 。
按 传 统 , C 程 序 通 过 一 系 列 switch-case 语 句 , 来 检 查 W M _ C O M M A N D 消 息 的
wParam 参 数 以 传 递 菜 单 命 令 :
switch (msg)
{
case W M _ C O M M A N D :
switch (LOWORD (wParam))
{
case ID_FILE_NEW OnFileNew ();
break;
case ID_FILE_OPEN: OnFileOpen ();
break;
.
.
.
}
}
MFC 程 序 通 过 一 个 消 息 映 射 来 完 成 相 同 的 事 情 :
BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd) ON_COMMAND(ID_FILE_NEW, OnFileNew) ON_COMMAND(ID_FILE_OPEN,OnFileOpen)
.
.
.
END_MESSAGE_MAP ()
为 DiskPie1 创 建 菜 单
正 如 我 们 将 为 DiskPie1 所 做 的 那 样 , 当 我 们 从 头 开 始 创 建 菜 单 资 源 时 , 我 们 从Insert 菜 单 选 择 Resource , 以 显 示 资 源 类 型 列 表 , 如 下 所 示 。 然 后 , 双 击 列 表 里的 Menu 条 目 打 开 菜 单 编 辑 器 。
项 目 必 须 是 打 开 的 , 你 可 能 不 得 不 隐 藏 Workspace 或 Outpu t( 输 出 ) 窗 口 , 以 便不 覆 盖 编 辑 器 的 工 作 区 域 。 当 你 设 计 并 保 存 菜 单 时 , Visual C++ 把 菜 单 脚 本 写 到
项 目 的 RC 文 件 里 , 并 把 标 识 符 #define 语 句 写 到 Resource.h 文 件 里 。其 后 , 当 你打 开 菜 单 资 源 时 , 环 境 自 动 打 开 菜 单 编 辑 器 。 为 了 显 示 Projec t( 项 目 ) 菜 单 标 识符 的 列 表 ,双 击 ResourceVie w( 资 源 查 看 )窗 格 里 的 Menu 条 目( 如 图 4-1 所 示 )。通 过 双 击 列 表 里 的 资 源 标 识 符 或 右 击 标 识 符 , 并 从 上 下 文 菜 单 里 选 择 Open 打 开菜 单 编 辑 器 。
图 4-5 使用 Visual C++ 菜 单 编 辑 器 创 建 DiskPie1 的菜单
图 4-5 显 示 了 当 我 们 向 DiskPie1 项 目 进 一 步 添 加 菜 单 时 菜 单 编 辑 器 的 外 观 。顶 级菜 单( 也 就 是 菜 单 栏 ) 包 含 一 个 点 线 矩 形 , 叫 做 新 项 框 , 它 指 出 菜 单 标 题 文 本 插入 点 。 当 你 在 菜 单 栏 上 输 入 一 个 条 目 , 并 按 下 Enter 键 , 一 个 带 有 自 己 的 新 项 框的 下 拉 菜 单 出 现 了 。 模 糊 的 边 界 表 明 新 项 框 是 激 活 的 , 而 不 管 它 是 菜 单 栏 上 , 还是 在 下 拉 菜 单 里 。 如 果 你 想 在 没 有 击 活 的 新 项 框 里 输 入 一 项 , 那 么 , 首 先 单 击 新项 框 来 选 择 它 。 任 何 输 入 到 新 项 框 的 东 西 将 同 时 输 入 到 图 4-6 所 示 的 M enu Item Properties( 菜 单 项 属 性 ) 对 话 框 的 Caption 控 件 里 。 要 返 回 并 修 改 一 个 标 题 或 菜
单 项 , 或 者 选 择 这 个 项 目 , 并 输 入 新 的 文 本 , 或 者 双 击 这 个 项 目 打 开 M enu Item Properties ( 菜 单 项 属 性 ) 对 话 框 。 当 你 正 在 菜 单 项 之 间 跳 转 时 , 对 话 框 会 消 失 , 有 时 ,这 是 很 不 方 便 的 。在 这 种 情 况 下 ,单 击 对 话 框 左 上 角 带 金 属 头 的 钢 针 按 钮 , 可 强 制 对 话 框 保 持 可 见 。
D iskPie1 的 File ( 文 件 ) 菜 单 只 有 一 个 命 令 , 叫 做 Exit。 要 创 建 这 个 菜 单 , 首 先在 菜 单 栏 的 新 项 框 里 输 入 &File ,按下 Enter 键 , 然 后 输 入 E&xit 作 为 菜 单 项 的 文本 。如 果 此 时 按 下 Enter 键 ,菜 单 编 辑 器 自 动 给 这 个 命 令 一 个 叫 做 ID_FILE_EXIT 的 标 识 符 , 它 是 菜 单 标 题 和 菜 单 项 文 本 的 混 和 物 。 它 也 为 ID_FILE_EXIT 添 加#define 语 句 到 Resource.h 文 件 中 。
让 我 们 停 一 会 儿 ,想 一 下 为 什 么 这 可 能 会 导 致 以 后 的 问 题 。当 你 保 存 这 个 新 的 菜单 资 源 时 , Visual C++ 看 到 这 个 项 目 没 有 RC 文 件 , 它 自 动 为 你 创 建 一 个 。 它 也添 加 这 些 行 到 RC 文 件 :
#include “ afxres.h ” #include “ resource.h ”
MFC 提 供 了 Afxres.h 头 文 件 , 使 你 不 必 为 每 一 个 项 目 定 义 相 同 的 公 共 标 识 符 ,
它 们 显 示 在 典 型 的 W indows 程 序 里 。 理 论 上 , 大 多 数 W indows 程 序 都 有 一 个File , Edit , View 和 Help ( 帮 助 ) 菜 单 , Afxres.h 定 义 了 一 些 常 用 的 标 识 符 , 例如 , ID_FILE_OPEN , ID_EDIT_COPY 和 ID_APP_ABOUT 等 。 它 为 你 定 义 自 己
的 资 源 标 识 符 保 留 了 Resource.h 。 偶 然 情 况 下 , Afxres.h 没 有 为 ID_FILE_EXIT 定 义 , 但 是 , 如 果 它 定 义 了 会 怎 样 呢 ? 在 那 种 情 况 下 , 当 编 译 RC 文 件 时 , 你 将碰 到 一 个 错 误 , 因 为 ID_FILE_EXIT 将 定 义 两 次 , 一 次 是 在 Afxres.h 里 , 一 次 是在 Resource.h 里 。
AppWizard 生 成 的 资 源 脚 本 并 不 存 在 这 个 潜 在 的 命 名 冲 突 问 题 。 AppWizard 生 成的 所 有 的 菜 单 项 都 在 Afxres.h 里 定 义 , 所 以 , AppWizard 并 不 为 它 们 添 加 定 义 到Resource.h 里 。 对 于 D iskPie1 这 样 的 非 AppWizard 项 目 , 当 使 用 资 源 编 辑 器 时 , 你 有 三 种 选 择 来 防 止 定 义 重 复 :
-
在 文 本 编 辑 器 里 打 开 RC 文 件 , 并 为 Afxres.h 移 去 #define
语 句 。
-
不 接 受 资 源 编 辑 器 可 能 在 A fxres.h 文 件 里 的 默 认 标 识
符 , 用 你 自 己 定义 的 资 源 标 识 符 。
-
编 辑 Resource.h 文 件 , 并 删 除 任 何 已 经 在 A fxres.h 里 定 义
的 标 识 符 。第 一 种 操 作 的 问 题 是 , 它 迫 使 你 也 从 文 件 里 移 去 了 所 有 其 他 Visual C++ 要 求 在
Afxres.h 里 定 义 的 跟 踪 信 息 。 第 二 种 解 决 方 案 更 可 靠 。 当 命 名 资 源 标 识 符 时 , 由于 ID M _ 在 Afxres.h 中 从 没 有 作 为 一 种 标 识 符 前 缀 使 用 , MFC Technical Note 20 推 荐 你 添 加 IDM _ 到 菜 单 标 识 符 上 。 在 M enu Item Propertie s( 菜 单 项 属 性 ) 对 话框 里 指 定 标 识 符 名 字 , 同 时 像 下 面 那 样 随 意 为 标 识 符 设 一 个 值 :
IDM_FILE_EXIT=1001
当 然 , 你 要 确 定 每 一 个 菜 单 标 识 符 有 一 个 唯 一 的 值 。
采 用 上 面 列 表 选 项 中 的 第 三 种 方 案 更 好 些 , 尽 管 这 种 方 法 有 些 粗 野 。 考 虑 一 下 , 如 果 你 在 程 序 里 使 用 像 IDM_FILE_EXIT 这 样 的 名 字 来 标 识 Exit 命 令 ,将 会 发 生什 么 。 对 于 像 DiskPie1 这 样 的 MFC 应 用 程 序 , 你 必 须 接 着 为 带 有 标 识 符 的W M _ C O M M A N D 消 息 提 供 一 个 处 理 函 数 ,同 时 也 添 加 一 个 指 向 处 理 函 数 的 消 息映 射 。 结 果 可 能 看 起 来 像 下 面 这 样 :
ON_COMMAND (IDM_FILE_EXIT,OnFileExit) // In the message map
.
.
.
void CMainFrame::OnFileExit() //Handler for IDM_FILE_EXIT
{
SendMessage( W M _CLOSE, 0, 0);
}
Afxres.h 包 含 几 个 特 定 的 标 识 符 名 字 ,MFC 为 它 提 供 自 己 的 处 理 函 数 ,这 样 做 可免 除 应 用 程 序 的 麻 烦 。 这 些 特 定 标 识 符 中 的 一 个 是 ID_APP_EXIT , 它 通 过 一 个关 闭 应 用 程 序 的 MFC 函 数 来 自 动 调 用 。 通 过 指 定 ID_APP_EXIT 的 值 给 Exit 菜单 命 令 ,D iskPie1 不 需 要 提 供 它 自 己 的 代 码 来 处 理 Exit 菜 单 选 项 。出 于 类 似 的 原因 , D iskPie1 的 View ( 查 看 ) 菜 单 上 的 两 个 菜 单 项 的 值 被 指 定 为ID_VIEW_TOOLBAR 和 ID_VIEW_STATUS_BA R。MFC 认 可 这 些 特 定 值 ,并 调用 它 自 己 的 处 理 函 数 来 显 示 或 隐 藏 工 具 栏 和 状 态 栏 。D iskPie1 在 它 自 己 的 菜 单 脚本 里 为 Toolbar 和 Status Bar 命 令 简 单 地 使 用 这 些 标 识 符 ,而 MFC 框 架 则 处 理 其他 每 一 件 事 情 。
给 命 令 特 定 的 标 识 符 ( 如 ID_APP_EXIT 或 ID_VIEW_TOOLBAR ) 的 缺 点 是 菜单 编 辑 器 在 Resource.h 里 为 这 些 名 字 书 写 定 义 ,这 样 就 重 复 了 在 Afxres.h 里 的 定义 。我 们 不 得 不 在 创 建 资 源 之 后 使 用 文 本 编 辑 器 , 来 删 除 在 Resource.h 里 的 无 用定 义 。
D iskPie1 菜 单 项 标 识 符 的 名 字 是 通 过 把 它 们 输 入 到 Menu Item Propertie s( 菜 单 项属 性 ) 对 话 框 里 来 指 定 的 。 下 面 是 结 果 概 况 :
菜 单 标 题 |
项 目 标 题 |
标 识 符 |
---|---|---|
&File |
E&xit |
ID_APP_EXIT |
&Chart |
&Memory\tCtrl+M |
IDM_MEMORY |
&View |
&Toolbar |
ID_VIEW_TOOLBAR |
&View |
&Status bar |
ID_VIEW_STATUS_BAR |
&Help |
&About DiskPie1 … |
ID_APP_ABOUT |
在 图 4-6 所 示 的 M enu Item Propertie s( 菜 单 项 属 性 ) 对 话 框 中 , 可 以 优 化 菜 单 的外 观 。 例 如 , 如 果 程 序 刚 开 始 时 一 个 菜 单 命 令 是 非 激 活 的 , 那 么 , 这 个 菜 单 的 文本 应 该 变 灰 ,来 提 示 用 户 这 个 命 令 当 前 是 不 可 用 的 。通 过 单 击 对 话 框 里 的 Grayed
( 变 灰 ) 复 选 框 , 可 以 为 一 个 菜 单 项 指 定 变 灰 文 本 。 要 在 菜 单 命 令 旁 放 置 复 选 标记 , 单 击 Checked ( 复 选 的 )。 在 资 源 脚 本 里 设 定 变 灰 文 本 或 复 选 标 记 , 对 于D iskPie1 这 样 的 MFC 程 序 是 不 需 要 的 , 因 为 框 架 会 自 动 更 正 菜 单 。
图 4-6 菜单资源的 Menu Item Properties 对 话 框
如 果 你 想 用 菜 单 命 令 打 开 一 个 折 叠 的 弹 出 菜 单 , 单 击 在 M enu Item Propertie s( 菜单 项 属 性 ) 对 话 框 里 的 Pop-u p( 弹 出 ) 复 选 框 。 显 示 在 菜 单 项 旁 边 的 箭 头 符 号 告诉 用 户 ,这 个 命 令 显 示 一 个 嵌 套 的 弹 出 菜 单 。 编 辑 器 为 这 个 弹 出 菜 单 显 示 另 一 个新 项 框 , 你 在 里 面 输 入 命 令 , 就 像 在 其 他 任 何 菜 单 里 一 样( 在 环 境 的 Fil e( 文 件 ) 菜 单 上 的 Recent File 命 令 给 出 一 个 折 叠 弹 出 菜 单 的 例 子 )。
对 于 像 D iskPie1 这 样 有 状 态 栏 的 程 序 , 当 用 户 加 亮 菜 单 上 的 命 令 时 , 对 话 框 里的 Prompt ( 提 示 ) 文 本 框 提 供 了 一 个 方 便 的 地 方 , 来 输 入 显 示 在 状 态 栏 里 的 描
述 。我 们 将 在 以 后 的 一 节 里 ,使用 Visual C++ 字 符 串 编 辑 器 添 加 D iskPie1 的 菜 单描 述 。 当 你 看 到 重 复 的 描 述 时 , 你 将 会 同 意 , 使 用 字 符 串 编 辑 器 是 最 好 的 选 择 。
D iskPie1 的 菜 单 是 标 准 的 。 唯 一 有 趣 的 添 加 项 是 Chart 菜 单 底 部 的 分 隔 条 。 在 一个 菜 单 最 后 放 置 一 个 分 隔 条 , 乍 看 起 来 是 很 古 怪 的 。 但 是 , DiskPie1 在 执 行 时 向Chart 菜 单 添 加 更 多 的 命 令 : 顶 部 的 M emory 命 令 和 底 部 的 D isk 命令,像 Disk C 和 Disk D 。 要 在 菜 单 上 创 建 一 个 分 隔 条 , 需 单 击 图 4-6 里 的 Separator ( 分 隔 条 ) 复 选 框 。
如 果 你 想 插 入 一 个 新 的 菜 单 或 菜 单 命 令 ,将 新 项 框 拖 到 想 要 的 地 方 。当 你 拖 拉 这个 方 框 时 , 一 个 水 平 或 垂 直 插 入 线 显 示 在 光 标 附 近 。 放 开 鼠 标 按 钮 来 放 下 新 项框 , 然 后 一 般 是 输 入 新 菜 单 的 标 题 。 你 也 可 以 拖 动 独 立 的 菜 单 项 或 菜 单 栏 目 , 来改 变 它 显 示 的 顺 序 。例如,要改变 Chart 和 Vie w( 查 看 )菜单的顺序,拖动 View
( 查 看 )菜 单 到 左 边 ,直 到 你 看 到 一 个 显 示 在 File 和 View 之 间 的 垂 直 插 入 线 .释放 鼠 标 , 就 完 成 了 操 作 。
如 前 所 述 创 建 一 个 新 菜 单 资 源 时 , 菜 单 编 辑 器 想 给 这 个 新 资 源 起 一 个 像IDR_MENU1 这 样 的 名 字 。 资 源 的 符 号 名 字 显 示 在 RC 文 件 里 菜 单 脚 本 的 第 一行 :
IDR_MENU1 MENU PRELOAD DISCARDABLE
菜 单 应 当 有 一 个 像 IDR_MENU1 这 样 的 名 字 , 但 是 ,对 DiskPie1 这 样 的 MFC 程
序 来 说 , 它 不 是 很 好 的 选 择 。 作 为 一 个 单 文 档 界 面 程 序 (SDI) , D iskPie1 可 以 为它 的 资 源 注 册 模 板 ,使 用 到 CSingleDocTemplate 构 造 器 的 单 独 调 用 ,提 供 具 有 相同 标 识 符 值 的 所 有 资 源 。 标 识 符 的 值 是 什 么 , 甚 至 给 资 源 不 同 的 标 识 符 名 字 , 这些 并 不 重 要 , 只 要 菜 单 、 工 具 栏 、 加 速 键 表 和 状 态 栏 资 源 是 通 过 同 一 不 变 的 数 值描 述 的 就 行 。 如 果 你 的 程 序 不 调 用 CSingleDocTemplate 或 同 M D I 等 效 的CMultiDocTemplate , 那 么 , 你 不 需 要 担 心 像 菜 单 和 加 速 键 那 样 用 同 样 的 符 号 值来 标 识 资 源 。
在 默 认 状 态 下 , 资 源 编 辑 器 给 所 有 的 主 窗 口 资 源 标 识 符 提 供 不 同 的 名 字 和 值 ,所以 , Resource.h 文 件 可 能 最 终 是 这 样 :
#define IDR_MENU1 革 者 101
#define IDR_ACCELERATOR1 102
#define IDR_ICON1 103
#define IDR_TOOLBAR1 104
如 果 创 建 资 源 时 , 你 接 受 默 认 的 名 字 , 那 么 必 须 接 着 编 辑 Resource.h 文 件 , 在 使用 CSingleDocTemplate 前 给 标 识 符 一 个 通 用 值 。对 于 DiskPie1 , 我 们 将 不 接 受 默认 的 名 字 , 而 改 为 给 菜 单 和 其 他 资 源 指 定 相 同 的 普 通 符 号 标 识 符 , 就 是 被AppWizard 使 用 的 IDR_MAINFRAM E 。这 将 保 证 CSingleDoTemplate 总 是 得 到 一
个 对 所 有 的 资 源 来 说 公 共 单 一 的 值 。 要 改 变 菜 单 的 标 识 符 ,双 击 菜 单 栏 的 任 何 地方 , 但 必 须 是 在 一 个 菜 单 名 字 上 , 来 打 开 Menu Properties 对 话 框 , 输 入IDR_MAINFRAM E, 并 按 下 Enter 键 。
这 时 , 项 目 的 RC 文 件 还 没 有 存 在 。 要 保 存 项 目 的 第 一 个 资 源 , 单 击 Fil e( 文 件 ) 菜 单 上 的 Save 或 Save A s ,并 给 文 件 起 一 个 同 项 目 相 同 的 名 字 ,在 此 是 D iskPie1 。Visual C++ 就 创 建 D iskPie1.rc 文 件 , 将 菜 单 资 源 脚 本 写 到 它 里 面 , 并 创 建Resource.h 文 件 , 以 保 存 新 的 定 义 。 不 要 忘 记 以 后 用 文 本 编 辑 器 编 辑 Resource.h 文 件 , 为 ID_APP_EXIT , ID_VIEW_TOOLBAR , ID_VIEW_STATUS_BAR 和
ID_APP_ABOUT 删 除 那 些 不 需 要 的 定 义 。
下 一 步 , 是 将 DiskPie1.rc 文 件 添 加 到 项 目 中 。 从 Properties 菜 单 中 选 择 Add To Project 命 令 , 然 后 单 击 显 示 在 下 面 的 级 联 菜 单 中 的 Files:
双 击 在 文 件 列 表 里 的 新 的 DiskPie1.rc 文 件 , 将 它 添 加 到 项 目 中 。 对 Resource.h 文 件 不 需 要 进 行 相 同 的 操 作 ,因为 Visual C++ 自 动 识 别 这 个 头 文 件 作 为 项 目 的 支持 文 件 。 从 这 点 来 看 , DiskPie1 是 一 个 实 际 的 项 目 。 接 着 , 我 们 将 为 D iskPie1 创 建 一 个 资 源 , 由 于 D iskPie1.rc 文 件 已 经 存 在 , 我 们 将 使 用 Save ( 保 存 ) 命 令来 保 存 资 源 , 而 不 是 用 Save A s( 另 存 为 ) 命 令 。
你 可 能 使 用 文 本 编 辑 器 来 查 看 Visual C++ 写 到 D iskPie1.rc 文 件 的 菜 单 脚 本 。通 过单 击 File ( 文 件 ) 菜 单 上 的 Open ( 打 开 ) 命 令 , 将 RC 文 件 作 为 文 本 文 档 调 入 , 来 显 示 Open ( 打 开 ) 对 话 框 。 从 对 话 框 底 部 的 Open A s( 打 开 类 型 ) 组 合 框 里选 择 Text , 然 后 , 双 击 文 件 列 表 里 的 DiskPie1.rc 。 这 里 是 显 示 在 文 件 里 的 新 菜 单
脚 本 :
IDR_MAINFRAME MENU DISCARDABLE BEGIN
POPUP "&File" BEGIN
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Chart" BEGIN
MENUITEM "Memory\tCtrl+M", IDM_MEMORY MENUITEM SEPARATOR
END
POPUP "&View" BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Help" BEGIN
MENUITEM "&About DiskPie1...", ID_APP_ABOUT
END
END
图 4-7 显 示 了 D iskPie1 已 经 完 成 的 菜 单 外 观 。 Chart 菜 单 的 Disk C 和 D isk D 命 令不 会 显 示 在 上 面 的 菜 单 脚 本 中 ,因 为 这 些 命 令 是 在 运 行 时 添 加 到 菜 单 上 的 。标 题栏 上 的 图 标 在 本 章 后 面 创 建 。
图 4-7 DiskPie1 的菜单系统
如 果 你 想 在 继 续 下 一 节 之 前 从 屏 幕 上 消 除 菜 单 编 辑 器 , 那 么 从 File( 文 件 ) 菜 单或 从 W indows 菜 单 上 选 择 Clos e( 关 闭 ) 命 令 。 在 使 用 这 个 命 令 时 , 要 确 定 编 辑 器具 有 输 入 焦 点 。
为 DiskPie1 创 建 加 速 键
在 Visual C++ 将 来 的 版 本 中 , 可 能 可 以 在 菜 单 脚 本 里 搜 索 加 速 组 合 键 , 并 自 动 生成 一 个 相 应 的 加 速 键 表 。 但 是 现 在 , 我 们 将 不 得 不 手 工 做 这 些 事 。 由 于 上 面 的 脚本 只 有 一 个 加 速 键 , 对 应 于 Memory 命 令 的 Ctrl+M , 你 可 能 以 为 DiskPie1.rc 文件 里 的 加 速 键 表 很 小 , 并 且 很 简 单 。 但 是 , 实 际 上 这 个 表 是 相 当 大 的 , 因 为 我 们不 得 不 为 那 些 还 没 有 在 菜 单 上 但 可 能 在 运 行 时 被 添 加 的 项 添 加 按 键 。我 们 将 使 用Visual C++ 编 辑 器 做 这 些 。
对 于 已 经 存 在 的 加 速 键 表 ,例 如 一 个 通 过 AppWizard 创 建 的 加 速 键 表 ,从 项 目 的ResourceView ( 资 源 查 看 ) 窗 格 里 打 开 加 速 键 编 辑 器 , 就 如 同 你 打 开 其 他 任 何 资源 编 辑 器 一 样 。 双 击 在 Accelerator 文 件 夹 里 的 条 目 来 启 动 这 个 编 辑 器 。 要 为D iskPie1 这 样 的 项 目 从 头 开 始 创 建 一 个 新 表 , 通 过 从 Insert 菜 单 里 选 择Resource , 并 双 击 在 Resource Type 列 表 里 的 Accelerator 打 开 加 速 键 编 辑 器 。
图 4-8 显 示 了 D iskPie1 加 速 键 列 表 的 一 部 分 , 它 包 括 对 应 于 Memory 命 令 的Ctrl+M , 以 及 从 C 到 Z 的 24 个 键 。 这 些 字 母 键 表 示 磁 盘 驱 动 器 , 作 为 D iskPie1 在 运 行 时 添 加 到 Chart 菜 单 的 Disk 命 令 的 加 速 键 。因 为 磁 盘 驱 动 器( 包 括 远 程 驱动 器 ) 可 以 指 定 最 多 到 Z 的 任 何 字 母 , 所 以 , D iskPie1.rc 必 须 在 加 速 键 表 里 包 括所 有 可 能 的 加 速 键 。 当 程 序 运 行 时 , 这 不 会 造 成 任 何 麻 烦 , 因 为 D iskPie1 忽 略不 与 已 有 的 驱 动 器 相 对 应 的 按 键 。
图 4-8 Visual C++ 加速器编辑器创建 DiskPie1 的加速器表
要 添 加 一 个 加 速 键 到 表 中 , 双 击 新 项 框 ( 它 以 一 个 点 框 显 示 ), 来 打 开 Accel Properties 对 话 框 , 然 后 输 入 加 速 键 和 它 的 标 识 符 。 例 如 , 在 Key 控 件 里 和 在 ID 控 件 里 的 IDM_MEMORY 中 输 入 M , 为 D iskPie1 的 M emory 命 令 添 加 Ctrl+M 加速 键 。 在 菜 单 编 辑 器 里 给 Ctrl+M 加 速 键 指 定 同 Memory 命 令 相 同 的 标 识 符 , 我
们 保 证 在 D iskPie1 里 按 下 Ctrl+M 和从 Chart 菜 单 里 选 择 M emory 命 令 具 有 相 同的 效 果 。 在 任 何 一 种 情 况 下 , 会 调 用 相 同 的 过 程 , 以 显 示 表 示 内 存 使 用 状 况 的 饼图 。
对 应 于 D iskPie1 的 D isk 命 令 的 加 速 键 都 有 像 IDM_DISK_C 、IDM_DISK_D 等 的标 识 符 。注 意 ,在 图 4-8 里 ,这 些 加 速 键 没 有 一 个 是 同 其 他 的 键( 像 Ctrl 或 Shift ) 进 行 组 合 , 这 样 就 允 许 用 户 仅 仅 按 下 一 个 字 母 键 , 例 如 C 或 D , 来 显 示 C 或 D 磁 盘 的 使 用 状 况 饼 图 。 要 为 一 个 加 速 键 设 置 或 移 去 一 个 组 合 键 , 在 Accel Properties 对 话 框 里 的 Modifiers 域 选 定 或 不 选 定 Ctrl, Alt 或 Shift 复 选 框 。
在 加 速 键 编 辑 器 里 , 从 表 里 移 去 加 速 键 是 很 容 易 的 :仅 仅 选 择 表 里 的 条 目 , 然 后按 下 Delete 键 。要 选 择 一 批 条 目 ,单 击 这 些 条 目 中 的 第 一 个 条 目 ,然 后 按 下 Shift 键 , 并 单 击 最 后 一 个 条 目 。 在 表 中 添 加 名 称 是 比 较 麻 烦 的 工 作 , 特 别 是 如 果 要 添加 一 大 批 键 的 时 候 。 对 于 有 连 续 名 字 的 符 号 标 识 符 , 例 如 那 些 在 D iskPie1 表 中的 , 使 用 兼 容 宏 的 文 本 编 辑 器 有 时 会 更 方 便 。 如 果 你 使 用 一 个 文 本 编 辑 器 在 RC 文 件 里 创 建 加 速 键 表 , 那 么 , 记 住 在 Resource.h 文 件 里 添 加 适 当 的 定 义 。 如 果 一个 加 速 键 对 应 于 一 个 菜 单 命 令 , 要 记 住 , 也 需 要 给 加 速 键 同 菜 单 项 相 同 的 标 识符 。
当 在 加 速 键 编 辑 器 里 添 加 一 组 具 有 相 近 名 字 ( 例 如 IDM_DISK_C 直 到IDM_DISK_Z ) 的 加 速 键 时 , 可 以 利 用 剪 贴 板 。 完 整 地 输 入 第 一 个 条 目 , 从 列 表里 选 择 它 , 然 后 按 下 Ctrl+C , 把 它 拷 贝 到 Windows 剪 贴 板 , 然 后 重 复 按 Ctrl+V ,
粘 贴 一 系 列 的 副 本 到 加 速 键 编 辑 器 里 。 接 着 , 双 击 第 一 个 条 目 打 开 Accel Properties 对 话 框 , 然 后 单 击 图 钉 按 钮 , 以 便 对 话 框 保 留 在 屏 幕 上 。 你 可 以 下 移此 列 表 选 择 条 目 , 并 按 需 要 修 改 标 识 符 名 字 和 键 。
单 击 File 菜 单 上 的 Save 来 保 存 新 的 加 速 键 表 。 编 辑 器 给 这 个 资 源 提 供 标 识 符 , 如 IDR_ACCELERATOR1 ,你 可 以 从 Workspac e( 工 作 空 间 )窗 口 的 ResourceView
( 资 源 查 看 ) 窗 格 中 看 到 。 对 于 D iskPie1 来 说 , 这 不 是 令 人 满 意 的 名 字 , 出 于相 同 的 原 因 , IDR_MAINFRAME1 对 菜 单 资 源 来 说 也 不 令 人 满 意 。 右 击ResourceView ( 资 源 查 看 ) 窗 格 里 的 标 识 符 , 并 单 击 弹 出 的 上 下 文 菜 单 里 的Properties , 然 后 将 资 源 的 符 号 名 字 改 为 IDR_MAINFRAM E, 如 图 4-9 所 示 。 它与 以 前 给 菜 单 资 源 的 名 字 相 同 。
图 4-9 为 加 速 键 表 更 改 标 识 符 名
再 次 选 择 Sav e( 保 存 )命 令 ,来 为 加 速 键 表 设 置 新 的 IDR_MAINFRAME 标 识 符 。在 更 新 的 DiskPie1.rc 文 件 里 , 如 下 代 码 段 显 示 了 加 速 键 表 目 前 的 样 子 :
IDR_MAINFRAME ACCELERATORS DISCARDABLE
BEGIN
"C", |
IDM_DISK_C, |
VIRTKEY, NOINVERT |
---|---|---|
"D", |
IDM_DISK_D, |
VIRTKEY, NOINVERT |
"E", . . |
IDM_DISK_E, |
VIRTKEY, NOINVERT |
. ."X", |
IDM_DISK_X, |
VIRTKEY, NOINVERT |
续 表 | ||
---|---|---|
"Y", |
IDM_DISK_Y, |
VIRTKEY, |
NOINVERT |
||
"Z", |
IDM_DISK_Z, |
VIRTKEY, NOINVERT |
END
D iskPie1 的 Resource.h 文 件 包 含 了 与 这 些 标 识 符 相 应 的 定 义 :
#define IDM_MEMORY 130
#define IDM_DISK_C 131
#define IDM_DISK_D 132
#define IDM_DISK_E 133
.
.
.
#define IDM_DISK_X 152
#define IDM_DISK_Y 153
#define IDM_DISK_Z 154
IDM_DISK 标 识 符 的 实 际 值 是 什 么 无 所 谓 ,但 是 ,有 两 个 理 由 应 当 保 持 这 些 值 连续 。第 一 ,从 IDM_DISK_C 到 IDM_DISK_Z 之 间 使 用 连 续 值 ,便 可 以 在 D iskPie1 里 用 单 一 的 过 程 处 理 所 有 的 菜 单 命 令 , 或 者 , 通 过 使 用 MFC 的ON_COMMAND_RANGE 宏 , 来 处 理 从 C 到 Z 之 间 的 加 速 键 。 当 我 们 开 始 添 加代 码 到 D iskPie1 中 时 , 我 们 略 去 了 细 节 。 第 二 个 使 用 连 续 标 识 符 值 的 理 由 是 , 它 与 Windows 装 载 包 含 在 一 个 程 序 资 源 数 据 里 的 字 符 串 有 关 。 那 是 下 一 节 的 内容 。
字 符 串 资 源 和 状 态 栏
当 用 户 加 亮 一 个 菜 单 上 的 命 令 时 ,D iskPie1 显 示 了 在 窗 口 左 下 角 状 态 栏 里 的 命 令描 述 。 当 鼠 标 滑 过 工 具 栏 上 的 按 钮 时 , 将 发 生 同 样 的 事 情 。 这 些 描 述 是 字 符 串 资源 那 样 的 程 序 数 据 , 它 们 是 以 文 本 形 式 保 存 在 可 执 行 程 序 的 资 源 部 分 中 。 一 个W indows 程 序 可 以 保 存 任 何 种 类 的 只 读 文 本 作 为 字 符 串 资 源 ,状 态 栏 的 描 述 文 本
只 是 一 个 例 子 。
这 一 节 以 字 符 串 资 源 的 一 般 性 讨 论 开 始 , 接 着 , 缩 小 它 的 范 围 , 来 看 看 状 态 栏 描述 文 本 。最 后 ,介 绍 以 使 用 Visual C++ 字 符 串 编 辑 器 写 D iskPie1 的 状 态 栏 描 述 文本 。
字 符 串 资 源
字 符 串 资 源 同 程 序 数 据 里 其 他 字 符 串 没 有 什 么 不 同 ,只 是 它 必 须 从 可 执 行 的 文 件读 到 缓 冲 区 中 。C 程 序 通 过 调 用 LoadString API 函 数 读 取 字 符 串 资 源 ,MFC 程 序可 以 调 用 CString 类的 LoadString 成 员 函 数 读 取 。 并 且 , 至 少 在 状 态 栏 描 述 文 本的 情 况 下 , MFC 程 序 甚 至 还 不 必 做 这 些 。 MFC 提 供 了 默 认 代 码 , 可 以 自 动 加 载描 述 字 符 串 , 我 们 在 后 面 将 看 到 这 点 。
字 符 串 资 源 是 在 程 序 RC 文 件 里 的 字 符 串 表 里 定 义 的 , 它 是 用 STRINGTABLE
键 标 识 的 字 符 串 列 表 , 并 用 BEGING-END 语 句 或 大 括 号 括 在 一 起 :
STRINGTABLE
{
ID_STRING1 “ Text for string resource #1 ”
ID_STRING2 “ Text for string resource #2 ”
}
在 Win32 里 , 字 符 串 资 源 被 限 制 在 4096 个 字 符 之 内 , 并 在 资 源 脚 本 里 只 能 占 一个 独 立 的 行 。 一 个 RC 文 件 可 以 有 多 个 字 符 串 表 , 每 一 个 表 有 任 何 多 个 字 符 串 。
与 一 般 的 数 据 字 符 串 相 比 , 字 符 串 资 源 具 有 两 种 主 要 的 优 点 。 第 一 , 字 符 串 资 源只 在 需 要 时 才 加 载 到 内 存 中 ,并 允 许 程 序“ 脱 机 ”保 存 可 能 从 不 使 用 的 文 本 数 据 。考 虑 一 个 向 用 户 显 示 帮 助 提 示 的 程 序 ,它 可 能 在 消 息 框 里 显 示 。虽 然 很 多 用 户 可能 会 喜 欢 这 个 特 征 , 但 是 , 其 他 用 户 可 能 不 需 要 它 , 并 快 速 关 闭 这 个 选 项 。 通 过将 提 示 以 字 符 串 资 源 的 形 式 保 存 , 程 序 在 每 次 运 行 时 , 不 会 因 不 使 用 的 文 本 而 浪费 内 存 。 字 符 串 的 第 二 个 优 点 是 , 通 过 将 程 序 的 字 符 串 组 织 成 资 源 , 开 发 者 将 字符 串 保 存 在 一 个 地 方 , 而 不 是 零 散 地 放 置 在 几 个 资 源 模 块 中 。 同 其 他 优 点 相 比 , 这 样 , 翻 译 人 员 只 修 改 RC 文 件 中 的 脚 本 , 便 可 以 创 建 一 个 外 国 语 言 的 版 本 , 修改 完 之 后 , 开 发 者 可 以 重 新 编 译 和 链 接 , 而 不 需 要 接 触 程 序 源 代 码 。
你 可 以 通 过 文 本 编 辑 器 或 者 Visual C++ 字 符 串 编 辑 器 , 在 RC 文 件 添 加 或 修 改 字符 串 资 源 , 如 果 改 变 了 一 个 字 符 串 标 识 符 的 名 字 , 那 么 , 字 符 串 编 辑 器 还 可 以 自动 为 新 的 标 识 符 添 加 定 义 到 Resource.h 文 件 中 。然 而 , 字 符 串 编 辑 器 没 有 在 源 代码 里 放 置 新 的 标 识 符 来 代 替 旧 的 标 识 符 。
提 示 字 符 串 和 工 具 提 示
状 态 栏 里 的 命 令 描 述 ( 又 名 提 示 字 符 串 或 定 点 描 述 ) 迅 速 成 为 W indows 应 用 程序 的 标 准 过 程 。 对 其 简 洁 的 菜 单 命 令 ,以 及 抽 象 艺 术 形 式 的 令 人 难 以 理 解 的 工 具栏 按 钮 , 由 于 它 们 几 乎 没 有 提 供 有 关 其 功 能 的 线 索 , 我 们 都 曾 经 感 到 困 惑 。 你 可以 在 状 态 栏 里 仔 细 浏 览 , 那 里 有 提 示 字 符 串 , 使 新 用 户 不 再 需 要 有 经 验 的 用 户 的帮 助 。
好 在 要 显 示 提 示 字 符 串 , 在 程 序 中 并 不 需 要 做 很 多 工 作 。 你 通 过 给 所 有 三 个 元 素相 同 的 资 源 标 识 符 ,便 可 以 将 一 个 提 示 字 符 串 绑 定 到 一 个 指 定 的 菜 单 命 令 和 工 具栏 按 钮 上 。接着,创建一个状态栏 ,并 添 加 CBRS_FLYBY 标 记 到 工 具 栏 风 格 里 。MFC 处 理 其 余 的 工 作 , 当 一 个 菜 单 命 令 处 于 高 亮 状 态 , 或 鼠 标 光 标 停 在 一 个 工具 栏 按 钮 上 时 , 便 会 显 示 正 确 的 字 符 串 。
添 加 CBRS_TOOLTIPS 标 记 到 工 具 栏 风 格 里 , 可 以 生 成 工 具 提 示 , 这 是 提 示 字符 串 的 变 种 。工 具 提 示 是 一 个 小 弹 出 窗 口 , 当 鼠 标 光 标 从 一 个 工 具 栏 按 钮 上 移 过时 , 它 显 示 简 要 的 描 述 信 息 。 Visual C++ 环 境 使 用 工 具 提 示 来 标 识 它 自 己 的 工 具栏 按 钮 , 可 是 , 这 个 特 征 是 可 选 的 ( 要 在 Visual C++ 中 打 开 工 具 提 示 , 通 过 单 击
Tool(s
工 具 )菜 单 上 的 Customize 打开 Customi z(e
自 定 义 )对 话 框 ,再 打 开 Toolbars
选 项 卡 里 的 Show ToolTip s( 显 示 工 具 提 示 ) 复 选 框 。 工 具 提 示 文 本 是 提 示 字 符串 的 一 部 分 , 像 下 面 这 样 , 在 字 符 串 结 尾 添 加 一 个 \n 换 行 字 符 :
ID_PROMPT1 “ Prompt string text in the status bar \nTooltip tex t”
这 里 是 一 个 简 单 的 例 子 , 它 描 述 了 菜 单 、 工 具 栏 、 提 示 字 符 串 和 工 具 提 示 之 间 的关 系 。 虽 然 接 下 来 的 代 码 段 描 述 了 一 个 只 打 开 和 保 存 文 档 的 MFC 程 序 , 但 是 , 用 黑 体 字 显 示 的 相 关 步 骤 也 同 样 可 应 用 程 序 于 非 MFC 程 序 。
给 R C 资 源 脚 本 文 件 里 的 相 应 菜 单 项 、 工 具 栏 和 提 示 字 符 串 相 同 的 标 识 符
IDR_MAINFRAME MENU BEGIN
POPUP “ &File ” BEGIN
MENUITEM “ &Open ” , ID_FILE_OPEN
MENUITEM “ &Save ” , ID_FILE_SAVE
END
END
IDR_MAINFRAME BITMAP “ res\\Toolbar.bm p” IDR_MAINFRAME TOOLBAR 16, 15
BEGIN
BUTTON ID_FILE_OPEN BUTTON ID_FILE_SAVE
END STRINGTABLE BEGIN
ID_FILE_OPEN “ Open an exitsting document\nOpen ” ID_FILE_SAVE “ Save the active document\nSave”
END
在 源 代 码 里 创 建 菜 单
要 用 一 步 过 程 创 建 主 窗 口 , 并 配 上 菜 单 , 需 调 用 CFrameWnd::Create 成 员 函 数 :
Create(NULL ,” Simple Dem o” , WS_OVERLAPPEDWINDOW, rectDefault, NULL,
MAKEINT RESOURCE (IDR_MAINFRAME));
或 者 , 在 创 建 主 窗 口 后 , 使 用 此 代 码 来 单 独 加 载 菜 单 。Cmenu menu; menu.LoadMenu(IDR_MAINFRAME); SetMenu(&menu);
menu.Detach();
创 建 工 具 栏
CToolBar toolbar; //In the header file
//Style defaults to W S_CHILD | WS_VISIBLE | CBRS_TOP
toolbar.Create(this); toolbar.LoadToolBar(IDR_MAINFRAME);
//Add flyby and tooltip flags to style toolbar.SetBarStyle(toolbar.GetBarStyle()|CBRS_FLYBY|CBRS_TOOLTIPS);
创 建 并 初 始 化 状 态 栏
CstatusBar statusbar; //In the header file UINT nIndicator=ID_SEPARATOR; //Single pane in status bar statusbar.Create(this);
statusbar.SetIndicators(&nIndicator,1);
AppWizard 生 成 相 似 的 代 码 , 为 你 做 所 有 这 些 工 作 。 你 只 需 要 打 开 字 符 串 编 辑器 , 并 移 去 不 需 要 的 字 符 串 资 源 , 用 描 述 程 序 里 新 菜 单 命 令 的 字 符 串 代 替 它 们 , 但 是 , 首 先 将 遇 到 一 个 或 更 多 的 字 符 串 资 源 。
文 档 字 符 串
当 我 们 完 成 DiskPie1 时 , 它 将 有 六 个 程 序 资 源 , 每 一 个 都 用 IDR_MAINFRAME
标 识 符 进 行 标 记 :
-
应 用 程 序 图 标
-
主 窗 口 的 菜 单
-
菜 单 的 加 速 键 表
-
工 具 栏 窗 口
-
工 具 栏 位 图
-
表 示 文 档 的 字 符 串 资 源
列 表 里 的 最 后 一 项 叫 做 文 档 字 符 串 ,它 由 7 个 子 串 组 成 ,它 们 通 过 \n 换 行 符 分 开 。当 在 AppWizard 里 创 建 一 个 SDI 或 M D I 项 目 时 , 你 可 以 通 过 单 击 在 AppWizard 第 四 个 步 骤 里 的 Advance 按 钮 , 来 预 先 查 看 文 档 字 符 串 的 7 个 子 字 符 串 元 素
( Advance 按 钮 是 在 第 2 章 里 描 述 的 )。单 击 这 个 按 钮 显 示 Advanced Option s( 高级 选 项 ) 对 话 框 , 如 果 你 想 改 变 它 们 , 那 么 , 可 以 在 这 里 重 新 输 入 项 目 的 默 认 子字 符 串 。
如 果 我 们 使 用 AppWizard 创 建 D iskPie1 ,那 么 ,AppWizard 将在 DiskPie1.rc 文 件里 像 这 样 重 新 输 入 一 个 默 认 的 文 档 字 符 串 :
STRINGTABLE PRELOAD DISCARDABLE BEGIN -
IDR_MAINFRAME “ DiskPie1\n\nDiskPie1\n\n\nDiskPie1.Document\nDiskPie1 Document”
END
像 其 他 字 符 串 资 源 一 样 , 文 档 字 符 串 必 须 在 RC 文 件 里 以 单 行 显 示 , 但 是 , 由 于空 间 的 原 因 , 在 上 面 以 两 行 显 示 。 子 字 符 串 包 含 MFC 指 定 给 程 序 和 它 创 建 的 文档 的 文 本 和 名 字 。 按 显 示 的 顺 序 , 这 些 子 字 符 串 指 定 :
-
在 主 窗 口 标 题 栏 上 显 示 的 程 序 名 。
-
指 定 给 程 序 创 建 的 新 文 档 名 。
-
在 MDI 应 用 程 序 里 使 用 的 文 档 描 述 , 它 可 以 打 开 同 一
类 型 的 多 个 文档 。
-
以 常 规 表 达 式 文 件 形 式 组 合 的 文 档 描 述 , 就 如 同 显 示
在 Open 和 Save A s( 另 存 为 ) 对 话 框 的 文 件 类 型 列 表 一 样 。
-
给 程 序 创 建 的 文 档 的 默 认 扩 展 名 。
-
在 系 统 注 册 表 里 表 示 文 档 类 型 的 名 字 。
-
对 程 序 创 建 的 文 档 类 型 的 描 述 。
由 于 D iskPie1 并 不 创 建 文 档 , 所 以 , 我 们 对 文 档 字 符 串 感 兴 趣 只 是 因 为 第 二 个子 字 符 串 。 当 这 个 子 字 符 串 为 空 时 , MFC 给 出 新 文 档 一 个 叫 做 “ Untitld ” 的 默认 名 字 。你 可 能 已 经 注 意 到 ,通过 AppWizard 创 建 的 程 序 经 常 在 它 们 的 标 题 栏 里带 有 “ Untitled ” 文 件 名 。 对 于 像 D iskPie1 这 样 不 需 要 存 储 它 的 数 据 的 程 序 , 调用 它 的“ U titled ”显 示 ,只 能 使 用 户 感 到 混 乱 。一 个 解 决 办 法 是 提 供 描 述 程 序( 而不 是 文 档 ) 的 第 二 个 子 字 符 串 的 文 本 , 像 “ D isk Usage ”。 详 见 下 一 节 介 绍 。
为 DiksPie1 创 建 字 符 串 资 源
在 RC 脚 本 文 件 里 已 经 有 一 个 字 符 串 表 的 AppWizard 项 目 , 通 过 双 击 Worksapce 窗 口 ResourceView ( 资 源 查 看 ) 窗 格 里 的 String Table 打 开 字 符 串 编 辑 器 。 要 为一 个 像 D iskPie1 这 样 的 项 目 建 一 个 新 的 字 符 串 表 , 从 Insert 菜 单 里 选 择Resource , 然 后 双 击 Resource Type( 资 源 类 型 ) 列 表 里 的 String Table 。
字 符 串 编 辑 器 同 字 符 串 本 身 一 样 普 通 。 唯 一 有 趣 的 部 分 是 在 编 辑 器 窗 口 的 水 平线 , 你 可 以 在 图 4-10 看 到 。 这 些 线 是 字 符 串 表 里 的 分 隔 线 , 介 于 “ 段 ” 的 字 符
串 组 之 间 , 每 段 最 多 有 16 个 字 符 串 。 字 符 串 标 识 符 的 值 决 定 了 字 符 串 属 于 哪 一个 段 。 标 识 符 的 值 在 0 到 15 之 间 的 字 符 串 属 于 第 一 个 段 , 标 识 符 值 在 16 到 31 之 间 的 字 符 串 属 于 第 二 个 段 , 如 此 类 推 。
有 时 , 一 个 段 可 以 作 为 预 读 缓 冲 区 , 在 许 多 磁 盘 驱 动 器 上 都 有 这 种 缓 冲 区 , 在 预读 缓 冲 里 , 磁 盘 控 制 器 不 仅 读 取 需 要 的 磁 盘 上 的 扇 区 , 而 且 同 时 读 取 许 多 连 续 的扇 区 , 把 它 们 储 存 在 一 个 内 存 缓 冲 区 里 , 以 备 以 后 使 用 。 预 读 缓 冲 区 加 快 了 磁 盘使 用 的 速 度 , 因 为 一 次 磁 盘 操 作 通 常 会 伴 随 有 更 多 的 磁 盘 操 作 , 这 时 , 控 制 器 可以 读 取 缓 冲 区 的 内 容 , 而 不 是 磁 盘 中 的 内 容 。 用 同 样 的 逻 辑 , 系 统 从 可 执 行 文 件里 一 次 读 取 一 个 段 的 字 符 串 资 源 。当 一 个 程 序 LoadString API 函 数 从 它 的 资 源 数据 里 读 取 独 立 的 字 符 串 时 ,W indows 读 取 字 符 串 所 属 的 那 个 完 整 的 段 ,如 果 程 序现 在 想 要 一 个 字 符 串 , 那 么 它 将 很 快 会 要 求 其 他 的 字 符 串 。 出 于 这 个 原 因 , 你 应该 尝 试 通 过 给 字 符 串 连 续 的 标 识 符 值 将 相 关 的 字 符 串 分 组 。 你 可 能 已 经 这 样 做了 , 但 现 在 你 知 道 了 这 样 做 的 原 因 。
图 4-10 Visual C++ String 编辑器
同 其 他 Visual C++ 资 源 编 辑 器 一 样 ,字 符 串 编 辑 器 通 过 显 示 一 个 以 点 框 表 示 的 新项 框 指 出 表 中 下 一 个 字 符 串 的 位 置 。 要 输 入 一 个 新 的 字 符 串 , 可 选 择 新 项 框 , 然后 开 始 输 入 字 符 串 文 本 。String Properties 对 话 框 显 示 一 个 默 认 的 字 符 标 识 符 。如果 你 需 要 , 那 么 重 新 写 标 识 符 的 名 字 ,或 从 对 话 框 组 合 框 的 下 拉 列 表 里 选 择 一 个名 字 。这 个 列 表 包 含 了 为 这 个 项 目 定 义 的 所 有 标 识 符 ,包括那些在 A fxres.h 文 件
里 的 标 识 符 , 它 允 许 你 选 择 一 个 名 字 , 例 如 IDM_MEMORY ,而不是输入它。字符 串 编 辑 器 自 动 用 标 识 符 的 值 来 对 表 里 的 条 目 排 序 。
通 过 输 入 表 4-2 里 的 转 义 字 符 , 可 以 将 字 符 同 字 符 串 分 开 。 此 表 涉 及 到 ASCII
和 ANSI 值 的 列 表 , 请 参 阅 附 录 A 。
表 4-2 在 字 符 串 资 源 中 特 殊 字 符 的 转 义 序 列转 义 序 列 意 义
\n 新 行 ( ASCII 值 #10 )
\r 回 车 ( ASCII 值 #13 )
续 表
\t 制 表 符 ( ASCII 值 #9 )
\a 响 铃 字 符 ( ASCII 值 #7 )
\\ 反 斜 线 ( \)
\ddd 任 何 ANSI 字 符 , 其 中 ddd 是 一 个 8 位 字 节 数 字 , 范 围从 001 到 377(10 进 制 数 255), 用 于 标 识 字 符
D iskPie1.rc 文 件 里 的 字 符 串 表 包 含 程 序 所 有 的 字 符 串 资 源 :
STRINGTABLE DISCARDABLE BEGIN
IDR_MAINFRAME "DiskPie1\nDisk Usage\n\n\n\n\n\n" IDM_MEMORY "Memory usage\nMemory"
IDM_DISK_C "Usage for drive C\nDrive C"
IDM_DISK_D "Usage for drive D\nDrive D"
IDM_DISK_E "Usage for drive E\nDrive E"
.
.
.
IDM_DISK_X "Usage for drive X\nDrive X"
IDM_DISK_Y "Usage for drive Y\nDrive Y"
IDM_DISK_Z "Usage for drive Z\nDrive Z" AFX_IDS_IDLEMESSAGE "Ready"
AFX_IDS_SCSIZE "Change the window size"
AFX_IDS_SCMOVE "Change the window position" AFX_IDS_SCMINIMIZE "Reduce the window to an icon" AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
AFX_IDS_SCCLOSE "Close the DiskPie1 application" AFX_IDS_SCRESTORE "Restore the window to normal size"
END
列 表 里 的 第 一 个 字 符 串 是 DiskPie1 的 文 档 字 符 串 , 它 同 程 序 的 其 他 资 源 有 相 同的 标 识 符 :
IDR_MAINFRAME “ DiskPie1\nDisk Usage\n\n\n\n\n\n ”
这 个 指 定 的 文 本 代 替“ Untitled ” 标 题 , 否 则 , MFC 将 会 把 “ Untitled ” 写 在 标 题栏 中 。 注 意 一 下 图 4-20 里 D iskPie1 的 标 题 文 本 , 你 将 看 到 , MFC 怎 样 从 文 档 字符 串 的 前 两 个 子 串 获 取 标 题 栏 的 文 本 。虽 然 这 比 仅 仅 删 除 资 源 行 里 的 第 二 个 子 串更 麻 烦 , 但 是 , 还 会 可 能 从 标 题 栏 里 完 整 地 移 去 “ D isk Usage ”。 你 必 须 找 到CMainFrame::PreCreateWindw 虚 拟 函 数 , 清 除 MFC 默 认 添 加 给 窗 口 风 格 的FWS_ADDTOTITLE 标 记 :
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &=~FWS_ADDTOTITLE;
return CFrameWnd::PreCreateWindow(cs);
}
在 字 符 串 表 里 , 最 后 的 字 符 串 有 指 定 的 AFX_ 前 缀 标 识 符 , 它 指 示 这 些 符 号 是 在Afxres.h 文 件 中 定 义 的 。 例 如 , 当 程 序 在 等 待 用 户 输 入 时 , MFC 认 可AFX_IDS_IDLEMESSAGE 标 识 符 , 并 在 状 态 栏 里 显 示 被 赋 予 的 字 符 串 值 。 为 了方 便 起 见 , 字 符 串 只 是 读 取“ Ready ”。其他的 AFX_ 符 号 为 DiskPie1 的 系 统 菜 单标 识 提 示 字 符 串 ,你 可 以 通 过 单 击 程 序 的 图 标 或 右 击 标 题 栏 来 打 开 系 统 菜 单 。当用 户 从 系 统 菜 单 里 选 择 一 项 时 , 状 态 栏 中 将 显 示 适 当 的 AFX _ 字 符 串 。 我 们 将 看到 , 当 我 们 在 本 章 结 尾 写 DiskPie2 程 序 时 , 一 般 根 本 不 需 要 包 含 这 些 提 示 字 符串 。
位 图 、 工 具 栏 、 图 标 和 光 标
Visual C++ 图 形 编 辑 器 是 创 建 和 修 改 程 序 的 图 形 资 源 的 地 方 , 图 形 资 源 包 括 位图 、 工 具 栏 、 图 标 和 光 标 。 图 标 和 光 标 是 位 图 , 用 途 很 小 。 图 标 显 示 在 任 务 栏 按钮 上 或 在 目 录 列 表 里 , 光 标 就 是 为 鼠 标 光 标 而 设 计 的 , 当 鼠 标 放 置 在 程 序 的 用 户区 域 里 时 , 它 将 提 供 服 务 。 工 具 栏 是 包 含 几 个 位 图 图 形 的 窗 口 , 它 在 一 个 水 平 行中 显 示 几 个 按 钮 。 别 的 东 西 , 例 如 , 窗 口 里 的 图 形 , 或 对 话 框 里 的 动 态 图 片 , 均叫 做 位 图 。
Visual C++ 环 境 提 供 一 个 适 用 于 所 有 场 合 的 图 形 编 辑 器 , 所 以 , 你 不 需 要 去 学 四种 不 同 的 用 法 。 你 可 能 看 到 在 线 帮 助 里 的“ toolbar editor”或“ icon editor ” 参 考 , 但 是 , 这 些 只 是 意 味 着 , Visual C++ 图 形 编 辑 器 可 以 应 用 于 任 何 一 种 特 定 类 型 的资 源 。 图 形 编 辑 器 可 以 处 理 不 同 资 源 类 型 的 多 个 文 档 。 图 4-11 显 示 了 打 开 两 种不 同 文 档 的 编 辑 器 , 一 个 是 我 们 所 熟 悉 的 16 × 15 的 位 图 , 另 一 个 是 两 色 的 32 × 32 的 鼠 标 光 标 。
对 于 每 一 种 资 源 类 型 , 编 辑 器 的 外 观 差 别 不 大 ,文 档 窗 口 的 左 上 角 的 图 标 指 示 你正 在 使 用 的 资 源 类 型 。 表 4-3 显 示 每 一 种 资 源 文 档 对 应 的 图 标 , 并 列 出 这 个 图 形编 辑 器 可 以 读 写 的 文 件 类 型 的 扩 展 名 。
当 使 用 Open ( 打 开 ) 命 令 打 开 已 有 的 资 源 文 档 , 而 且 这 个 文 档 还 具 有 表 4-3 第三 列 里 的 某 个 扩 展 名 时 , Visual C++ 自 动 打 开 图 形 编 辑 器 , 并 调 整 自 己 , 以 适 合这 种 资 源 类 型 。
表 4-3 图 形 编 辑 器 图 标 和 文 件 类 型
资 源 图 标 输 入 文 件 类 型 输 出 文 件 类型
Bitmap |
( |
位 |
B M P, |
DIB, |
EPS, |
GIF, |
B M P |
---|---|---|---|---|---|---|---|
图 ) |
JPG |
Toolba
r( 工 具栏 )
Cursor
( 光标 )
B M P B M P
C U R CUR
Icon
( 图 标 ) ICO ICO
D iskPie1 有 菜 单 、 加 速 键 和 字 符 串 数 据 , 但 还 没 有 图 形 资 源 。 对 于 D iskPie11 这样 的 项 目 , 可 以 用 两 种 稍 有 不 同 的 方 法 来 创 建 一 种 新 的 图 形 资 源 。 选 择 什 么 方 法取 决 于 你 想 象 的 这 个 图 形 文 件 是 什 么 样 子 。如 果 打 开 一 个 项 目 , 并 想 添 加 一 个 新的 图 形 资 源 到 项 目 中 , 从 Insert 菜 单 中 选 择 Resource , 并 双 击 位 图 或 光 标 , 或 者
是 在 列 表 里 的 工 具 栏 。 Visual C++ 打 开 图 形 编 辑 器 , 在 标 题 栏 里 显 示 为 这 种 资 源文 档 指 定 的 标 识 符 。 根 据 资 源 类 型 的 不 同 , 标 识 符 是 像 IDB_BITMAP1 , IDC_CURSOR1 , IDI_ICON1 或 IDR_TOOLBAR1 这 样 的 名 字 。 以 后 在 编 辑 器 里打 开 的 资 源 将 得 到 相 似 的 标 识 符 , 只 是 在 数 字 上 加 1 , 例 如 IDI_ICON2 , IDI_ICON3 等 等 。 保 存 图 形 资 源 到 文 件 中 时 , Visual C++ 给 这 个 文 件 起 的 名 字 是标 识 符 减 去 前 缀 , 然 后 在 项 目 的 Resource.h 文 件 里 定 义 这 个 标 识 符 。 例 如 , 要 保存 名 为 IDB_BITMAP1 的 资 源 , 需 添 加 如 下 一 行 到 RC 文 件 :
IDB_BITMAP1 BITMAP DISCARDABLE “ res\\bitmap1.bmp”
并 添 加 下 面 一 行 到 Resource.h 文 件 里 :
#define IDB_BITMAP1 130
然 而 ,你 没 有 必 要 接 受 这 些 没 有 什 么 特 征 的 名 字 。在 保 存 资 源 前 ,通 过 单 击 View
( 查 看 ) 菜 单 上 的 Properties , 并 输 入 一 个 新 的 标 识 符 名 字 来 给 它 提 供 一 个 描 述性 的 标 识 符 。 在 相 同 的 Properties 对 话 框 里 , 也 可 以 给 这 个 图 形 文 件 指 定 一 个 名字 。
图 4-11 Visual C++ 图 形 编 辑 器 具 有 两 个 打 开 的 文 档
在 启 动 图 形 编 辑 器 的 第 二 种 方 法 中 , 你 可 以 创 建 一 个 新 的 图 形 资 源 ,但 不 添 加 它到 项 目 文 件 列 表 里 。 你 可 能 想 这 样 做 , 例 如 , 创 建 一 个 资 源 库 , 或 为 工 具 栏 按 钮设 计 位 图 。 这 种 方 法 不 要 求 打 开 项 目 , 只 单 击 File( 文 件 ) 菜 单 上 的 New , 并 在File 选 项 卡 里 , 从 列 表 里 选 择 你 想 要 的 资 源 类 型 : Bitmap File ( 位 图 文 件 ), Icon File ( 图 标 文 件 ) 或 Cursor File ( 光 标 文 件 )。
图 形 编 辑 器 的 工 作 区 是 分 成 两 个 窗 口 。默 认 状 态 下 , 左 边 窗 口 以 图 形 的 实 际 尺 寸显 示 图 形 , 右 边 窗 口 显 示 的 图 形 放 大 到 大 约 36 ( 6 × 6 ) 倍 。 放 大 的 图 形 有 一 个覆 盖 形 式 的 网 格 , 网 格 中 , 每 一 个 方 块 表 示 实 际 图 形 上 的 一 个 像 素 。 如 果 你 以 前使 用 过 画 图 程 序 ,例 如 Microsoft Windows 的 Paint 应 用 程 序 ,那 么 ,就 会 对 Visual C++ 图 形 编 辑 器 很 熟 悉 。
通 过 单 击 左 边 或 右 边 窗 口 中 的 任 何 地 方 , 来 选 择 要 绘 制 的 图 形 。 如 果 要 处 理 细节 , 可 以 在 大 的 工 作 区 域 里 进 行 , 并 在 实 际 尺 寸 图 形 窗 口 里 观 察 效 果 。 将 两 个 窗口 分 割 开 的 分 隔 条 是 可 以 移 动 ,只 要 用 鼠 标 向 左 或 向 右 拖 动 它 即 可 。要 开 始 画 图形 , 通 过 单 击 显 示 在 图 4-12 里 Graphics 工 具 栏 上 的 一 个 按 钮 , 来 选 择 一 个 合 适的 工 具 。 与 在 Visual C++ 环 境 里 使 用 其 他 工 具 栏 一 样 , 你 可 以 通 过 向 内 或 向 外 拖动 工 具 栏 来 缩 小 或 放 大 它 。
图 4-12 Visual C++ 图 形 编 辑 器 中 的 工 具
图 形 编 辑 器 工 具 很 灵 活 , 而 且 很 友 好 , 只 需 要 几 分 钟 就 可 以 学 会 , 然 而 , 有 几 点可 能 看 起 来 不 那 么 直 观 , 所 以 要 简 要 讨 论 一 下 。 首 先 , 图 形 的 背 景 颜 色 依 赖 于 图形 的 类 型 。图 标 和 光 标 只 有 一 种 透 明 的 背 景 色 ,在 编 辑 器 窗 口 里 用 蓝 绿 色 进 行 着色 。 当 W indows 在 屏 幕 上 画 图 标 或 光 标 时 , 它 只 画 前 景 色 , 在 透 明 背 景 色 下 的所 有 像 素 均 不 擦 除 。 另 一 方 面 , 位 图 的 背 景 色 是 不 透 明 的 。 一 个 位 图 在 屏 幕 上 是作 为 一 块 画 出 来 的 , 它 将 覆 盖 它 下 面 的 任 何 东 西 。 背 景 色 是 否 透 明 , 可 能 是 这 两种 图 形 资 源 类 型 之 间 的 最 大 区 别 。
当 你 单 击 Rectangle Selection( 矩 形 选 择 ), Irregular Selection ( 不 规 则 图 形 选 择 ) 或 Text 按 钮 时 ,透 明 选 择 框 显 示 在 Graphics 工 具 栏 的 底 部 ,它 也 是 编 辑 器 Image 菜 单 上 Draw Opaque ( 不 透 明 画 图 ) 命 令 的 工 具 栏 版 本 。 要 理 解 选 择 框 的 用 途 , 考 虑 一 下 一 个 分 为 两 层 的 图 形 , 一 层 覆 盖 在 另 一 层 上 。 上 层 是 一 个 漂 浮 的 图 形 , 你 可 以 移 动 , 或 设 定 它 的 位 置 。 下 面 这 一 层 叫 做 底 层 , 是 固 定 的 。 利 用 选 择 框 , 你 可 以 设 定 顶 层 的 背 景 透 明 度 ,但 不 能 影 响 底 层 的 透 明 度 。选 择 透 明 度 选 择 框 的顶 部 图 标 , 意 味 着 覆 盖 图 形 层 上 的 背 景 像 素 应 该 当 作 前 景 颜 色 , 使 上 面 的 一 层 成为 实 心 的 矩 形 框 。 选 择 框 的 底 部 图 标 使 上 面 一 层 透 明 , 实 际 上 , 是 从 这 一 层 移 去背 景 像 素 。 例 如 , 下 面 是 当 打 开 或 关 闭 透 明 度 时 , 在 底 层 图 形 上 输 入 字 母 “ A ” 时 的 外 观 :
不 管 透 明 度 的 设 定 如 何 , 底 层 位 图 图 形 的 背 景 颜 色( 在 当 前 情 况 下 是 白 色 ) 均 保持 不 透 明 , 以 便 在 屏 幕 上 显 示 的 位 图 覆 盖 位 图 矩 形 区 域 内 的 任 何 像 素 。 然 而 , 当显 示 一 个 位 图 时 , 程 序 可 以 模 拟 透 明 的 像 素 , 首 先 掩 盖 位 图 的 背 景 颜 色 , 然 后 用位 图 将 出 现 的 屏 幕 区 域 的 副 本 来 替 代 它 。如 果 你 对 这 个 技 术 感 兴 趣 ,完 全 可 以 从
Jeff Prosise ’ s Programming W indows 95 with MFC 里 题 为 “ Bitmap s, Palettes , and Region s” 那 章 的 透 明 化 位 图 教 程 中 , 找 到 详 细 的 说 明 。 通 常 , 你 只 是 想 确 保一 个 位 图 与 显 示 它 的 窗 口 拥 有 一 样 的 背 景 颜 色 , 以 便 得 到 一 种 透 明 的 假 象 。有 一种 简 单 的 方 法 可 以 实 现 这 种 操 作 , 下 一 节 将 详 细 说 明 。
另 一 种 图 形 编 辑 器 的 隐 藏 特 征 是 , 鼠 标 的 左 右 按 钮 分 别 对 应 于 前 景 色 和 背 景 色 。例 如 , 用 鼠 标 左 键 单 击 Colors 调 色 板 上 的 一 种 颜 色 , 来 选 择 前 景 色 , 用 鼠 标 右击 选 择 背 景 色 。 你 可 以 在 图 形 上 通 过 拖 动 或 单 击 适 当 的 鼠 标 按 钮 , 来 选 择 使 用 一种 颜 色 画 图 。
表 4-4 总 结 了 在 图 形 编 辑 器 里 能 够 看 到 的 工 具 栏 按 钮 。如 图 4-12 所 示 ,在 G raphics 工 具 栏 里 , 按 钮 是 以 平 面 方 式 显 示 的 。 表 4-4 显 示 了 处 于 凸 起 状 态 下 的 按 钮 , 这可 以 帮 助 我 们 区 别 每 一 个 按 钮 。
图 4-4 Graphics 工 具 栏 按 钮
按 钮 说 明
利
用 Rectangle Selection 和 Irregular Selection 工 具 , 可以 标 记 要
移 动 、 清 除 或 复 制 的 图 像 部 分 。 单 击 按 钮 , 然 后 , 拖
动 交 叉 十 字 或 光 标 , 指 向 要 标 记 的 矩 形 或 区域 。 在 释 放
鼠 标 按 钮 时 , 在 标 记 的 区 域 周 围 将 出 现 选择 框 。 你 可 以
移 动 选 择 内 容 , 方 法 是 使 用 鼠 标 拖 动它 ; 要 清 除 它 , 则
按 Del 键 ; 复 制 它 到 剪 贴 板 的 方 法是 按 Ctrl+C
利
用 Select Colo r( 取 色 ) 工 具 , 可 以 从 图 像 中 选 取 颜色 ,而
不 是 从 Colors 调 色 板 中 。单 击 工 具 栏 上 的 按 钮 , 然 后 单
击 要 选 取 颜 色 的 图 像 上 的 区 域 。 使 用 鼠 标 左 键可 以 选 取
前 景 色 , 使 用 鼠 标 右 键 可 以 选 取 背 景 色
续 表
Eras
e( 橡 皮 擦 ) 工 具 将 光 标 改 为 一 个 方 块 , 可 以 在 图像 上
拖 动 它 , 来 擦 除 像 素 。 擦 除 的 像 素 改 变 为 当 前 前景 色 ,
这 要 取 决 与 当 前 的 资 源 类 型 。 前 面 提 到 过 , 在Colors 调
色 板 的 左 上 角 , 图 标 和 光 标 的 背 景 是 不 透 明的 颜 色 。 要
改 变 擦 除 块 的 大 小 , 可 以 单 击 工 具 栏 底 部选 择 框 中 的 一
个 尺 寸 图 标
Fil
l( 填 充 )工 具 将 颜 色 的 像 素 改 变 为 当 前 的 前 景 或 背景 色
。 单 击 Fill 按 钮 , 然 后 单 击 要 改 变 的 颜 色 中 的 任何 地 方
。 若 使 用 鼠 标 左 键 , 则 填 充 前 景 色 ; 使 用 鼠 标右 键 则 填
充 背 景 色 。 编 辑 器 将 更 改 此 颜 色 的 所 有 连 续像 素 , 来 填
充 颜 色 。 像 素 必 须 水 平 或 垂 直 接 触 , 以 对角 方 式 接 触 的
像 素 被 认 为 是 不 连 续 的
续表
要
改 变 所 选 择 图 形 的 大 小 , 可 以 使 用 M agnif y( 放 大 ) 工
具 , 并 选 择 一 个 值 1 , 2 , 6 或 8 。 放 大 值 指 定 对 应于 实
际 图 形 中 一 个 像 素 的 实 际 像 素 数 。 如 果 放 大 的 图形 有 网
格 , 则 放 大 值 确 定 的 是 每 个 网 格 的 宽 度 和 高 度
单
击 左 边 的 图 片 按 钮 , 可 以 手 绘 图 , 然 后 , 拖 动 鼠 标按 钮
, 以 留 下 像 素 的 轨 迹 , 颜 色 是 前 景 色 或 背 景 色 。Pencil
( 铅 笔 ) 工 具 只 画 出 一 个 像 素 宽 的 细 线 。 使 用Brus h( 刷
子 ) 可 以 画 出 粗 线 , 在 工 具 栏 底 部 的 选 择 框中 可 以 选 择
刷 子 的 宽 度
A
ir Brush ( 喷 雾 ) 工 具 可 以 画 出 随 机 的 颜 色 图 案 , 模拟 在
画 布 上 轻 微 喷 射 的 效 果 。 在 工 具 栏 的 选 择 框 中 , 可 以
选 择 喷 射 的 密 度 和 尺 寸
续表
画
线 工 具 可 以 画 直 线 , 还 可 以 画 曲 线 , 曲 线 从 初 始 位置 开
始 弹 性 弯 曲 。 单 击 要 开 始 画 线 的 位 置 , 拖 动 光 标到 线 的
终 点 , 然 后 释 放 鼠 标 键 来 确 定 此 线 。 Curve 工具 还 额 外 需
要 一 个 步 骤 : 在 释 放 鼠 标 键 设 置 终 点 后 , 移 动 光 标 来
设 置 曲 线 的 曲 率 。 在 曲 线 以 自 己 需 要 的 方式 成 形 后 , 双
击 便 可 以 确 定 曲 线 ( 双 击 的 鼠 标 键 必 须与 拖 动 光 标 的 鼠
标 键 相 同 )。 如 果 在 画 线 的 过 程 中 改变 了 主 意 , 可 以 按
Esc , 或 者 单 击 另 一 个 鼠 标 键 , 来重 新 开 始
续表
Text(
文 本 ) 工 具 显 示 一 个 小 窗 口 , 可 以 从 中 输 入 在图 形 中 出
现 的 文 字 , 所 用 的 颜 色 是 当 前 的 前 景 色 。 如前 所 述 , 在
透 明 选 择 框 中 选 择 文 字 的 透 明 性 , 然 后 , 在 选 择 完 Text
工 具 时 , 按 Esc 键
这 些 工 具 可 以 画 矩 形 、 圆 角 矩 形 和 椭 圆 形 , 这 些 图 形可 以 是 实 心 的 , 也 可 以 是 空 心 的 。 选 择 一 个 工 具 , 然后 , 以 前 景 色 或 背 景 色 来 画 出 形 状 , 方 法 是 在 图 形上 ,从 左 上 角 向 右 下 角 拖 动 鼠 标 光 标 。按 下 Shift 键 可以 强 制 画 出 某 种 形 状 , 使 矩 形 画 为 正 方 形 , 或 者 将 椭圆 画 为 圆 形 。 在 拖 动 光 标 的 过 程 中 , 如 果 要 取 消 操作 , 可 以 按 Esc , 或 者 单 击 另 一 个 鼠 标 键
位 图
在 为 一 个 新 的 位 图 打 开 图 形 编 辑 器 时 , 它 提 供 一 个 边 长 为 48 像 素 的 正 方 形 的 干净 区 域 。 然 而 , 位 图 不 要 求 一 定 是 正 方 形 , 它 们 可 以 是 边 长 不 大 于 2048 个 像 素的 任 何 尺 寸 的 矩 形 。要 调 整 工 作 区 域 的 大 小 , 拖 动 工 作 区 域 边 界 上 一 个 调 整 大 小的 手 柄 , 在 拖 动 手 柄 的 同 时 , 注 意 一 下 编 辑 器 状 态 栏 里 的 新 尺 寸 。 也 可 以 通 过 单
击 View ( 查 看 ) 菜 单 上 的 Properties 打开 Bitmap Propertie s( 位 图 属 性 ) 对 话 框 , 从 中 输 入 想 得 到 的 大 小 。
这 里 是 一 个 C 程 序 如 何 显 示 位 图 资 源 的 例 子 。 此 代 码 段 假 设 位 图 最 初 是 保 存 在文 件 Res\Bitmap.bmp 里 ,并 在 程 序 的 RC 文 件 里 ,通过 BitmapDemo 名 进 行 标 识 , LoadBitmap 函 数 用 和 名 字 相 同 的 字 符 串 加 载 资 源 。
// Resource declaration in the RC file
BitmapDemo BITMAP “ res\\bitmap.bm p”
// In the C source file
HBITMAP hbm; // Declare a globa handle for the bitmap
.
.
.
// Load the bitmap in WinMain or the InitInstance procedure static char szAppName [ ] = “ BitmapDemo ” ;
hbm = LoadBitmap( hInstance, szAppName);
.
.
.
// Display the bitmap in the window procedure case WM_PAINT:
hdc = BeginPaint( hwnd, &ps ) ’
hdcMemory = CreateCompatibleDC( hdc ); GetObject ( hbm, sizeof (BITAMP),&bm); SelectObject( hdcMemory, hbm);
BitBlt( hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMemory, 0, 0, SRCCOPY ) ’
DeleteDC( hdcMemory);
EndPaint( hwnd,&ps); break;
在 MFC 程 序 里 ,显 示 这 个 位 图 的 步 骤 是 相 似 的 。首 先 ,用 资 源 初 始 化 一 个 CBitmap
对 象 :
bitmap.LoadBitmap(szAppName);
然 后 , 在 窗 口 的 OnDraw 函 数 里 显 示 这 个 位 图 :
BITMAP bm;
CDC dcMemory;
bitmap.GetObject( sizeof (BITMAP), &bm ); dcMemory.CreateCompatibleDC( Pdc ); dcMemory.SelectObject( &bitmap );
PDc->BitBlt ( x, y, bm.bmWidth, bm.bmHeight, &dcMemory, 0, 0, SRCCOPY );
在 结 束 这 一 节 中 有 关 位 图 的 说 明 之 前 ,让 我 们 再 次 看 一 下 ,上 一 次 讨 论 的 有 关 位
图 透 明 性 的 题 目 。 我 们 已 经 知 道 , 位 图 的 背 景 色 是 不 透 明 的 , 但 是 , 如 果 这 个 位图 的 背 景 色 是 白 色 , 而 且 , 这 个 位 图 将 显 示 在 一 个 背 景 色 也 是 白 色 的 窗 口 里 , 那么 , 这 个 位 图 的 正 方 形 形 状 会 被 掩 盖 。 如 果 给 出 透 明 背 景 色 的 设 想 , 那 么 , 只 有不 是 白 色 的 前 景 色 可 以 显 示 出 来 。 当 时 , 如 果 窗 口 的 背 景 色 不 是 白 色 的 , 将 是 什么 样 的 呢 ? 在 那 种 情 况 下 , 在 先 前 代 码 段 里 显 示 的 位 图 将 暴 露 出 它 的 正 方 形 外形 , 这 可 能 不 是 你 想 要 的 效 果 。
应 用 程 序 窗 口 一 般 采 用 标 识 为 COLOR_WINDOW 的 系 统 窗 口 颜 色 , 默 认 状 态下 , 它 是 白 色 的 。 然 而 , 一 个 程 序 可 以 通 过 调 用 SetSysColors 来 改 变 系 统 窗 口 的颜 色 , 或 者 , 用 户 可 以 在 W indows Control Panel 里 的 D isplay( 显 示 ) 部 分 改 变
颜 色( 如 果 想 试 一 试 ,那 么 ,在 D isplay Properti e(s 显 示 属 性 )对 话 框 ,从 Appearance
( 外 观 ) 选 项 卡 上 的 Item 组 合 框 里 选 择 W indow ,从 Color 下 拉 列 表 里 选 择 一 个新 的 颜 色 , 然 后 单 击 OK ( 确 定 ))。 通 过 使 用 LoadImage API 函 数 , 而 不 是LoadBitmap 函 数 , 来 装 载 位 图 , 并 像 下 面 这 样 指 定 LR_LOADTRANSPARENT 标 记 , 程 序 可 以 保 证 位 图 的 背 景 色 总 是 同 COLOR_WINDOW 颜 色 一 致 :
hbm=LoadImage( hInstance,szAppName,IMAGE_BITMAP,
0,0,LR_LOADTRANSPARENT);
这 个 函 数 查 看 图 像 里 的 第 一 个 像 素 的 颜 色 , 它 处 于 矩 形 位 图 的 左 上 角 , 推 测 起来 , 应 该 是 背 景 的 一 部 分 。 然 后 , LoadImage 函 数 用 当 前 的 COLOR_WINDOW 颜 色 来 代 替 位 图 颜 色 表 里 相 应 的 条 目 。这 样 , 在 这 个 位 图 里 组 成 背 景 的 所 有 像 素
都 用 默 认 的 窗 口 颜 色 显 示 。 唯 一 的 警 告 是 , 如 果 位 图 有 256 多 种 颜 色 , 那 么
LR_LOADTRANSPARENT 将 不 起 作 用 。
我 们 还 没 有 完 全 使 用 LoadImage 函 数 。正 如 我 们 将 在 下 一 节 中 看 到 的 那 样 ,这 个函 数 也 可 以 装 载 图 标 。 但 是 现 在 , 让 我 们 看 一 下 位 图 怎 样 成 为 工 具 栏 。
工 具 栏
在 Visual C++ 中 创 建 工 具 栏 , 只 不 过 是 设 计 包 含 工 具 栏 按 钮 图 形 的 位 图 。 这 个 位图 作 为 一 个 B M P 文 件 保 存 , 并 在 项 目 的 RC 文 件 里 用 一 个 标 识 符 名 字 引 用 它 :
IDR_TOOLBAR BITMAP “ res\\toolsbar.bm p”
标 识 符 的 名 字 和 文 件 名 都 由 你 决 定 。D iskPie1 用 IDR_MAINFRAME 命 名 它 的 工具 栏 , 同 程 序 的 其 他 资 源 保 持 一 致 , 如 前 所 述 , 允 许 调 用 到 CSingleDocTemple 构 造 器 。
工 具 栏 位 图 是 一 系 列 覆 盖 工 具 栏 按 钮 的 图 形 , 每 一 个 按 钮 都 有 一 个 图 形 。默 认 状态 下 , 每 一 个 图 形 都 是 16 个 像 素 宽 , 15 个 像 素 高 , 它 适 合 标 准 的 24 个 像 素 、宽 22 个 像 素 高 的 工 具 栏 按 钮 。通 过 以 典 型 的 W indows 方 式 拖 动 编 辑 器 工 作 空 间的 边 界 , 可 以 设 置 一 个 图 形 的 尺 寸 是 大 一 点 , 还 是 小 一 点 , 是 宽 一 点 , 还 是 窄 一点 。 由 于 你 不 能 使 一 个 工 具 栏 里 按 钮 具 有 不 同 的 尺 寸 , 所 以 , 新 尺 寸 将 应 用 于 所
有 的 工 具 栏 图 形 。 当 保 存 工 作 时 , Visual C++ 自 动 指 定 RC 文 件 里 工 具 栏 按 钮 的新 尺 寸 。
如 果 AppWizard 为 你 生 成 项 目 , 那 么 , 它 在 项 目 的 Res 文 件 夹 中 创 建 一 个 叫 做Toolbar.bmp 的 文 件 。 这 个 文 件 包 含 对 应 于 命 令 New , Open , Save , Cu t, Copy , Paste , Print 和 Help 的 工 具 栏 按 钮 的 图 形 。 图 4-13 是 在 Toolbar.bmp 里 放 大 的 位图 和 最 终 的 工 具 栏 。
图 4-13 AppWizard 生成的默认工具栏
在 下 一 段 代 码 中 , 显 示 了 AppWizard 项 目 中 RC 文 件 的 创 建 工 具 栏 的 脚 本 。工 具栏 脚 本 里 的 每 一 个 按 钮 , 都 具 有 对 应 于 本 章“ 菜 单 和 加 速 键 ” 一 节 脚 本 里 列 出 的菜 单 命 令 的 相 同 标 识 符 。
IDR_MAINFRAME BITMAP MOVEABLE PURE
“ res\\Toolbar.bm p”
IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15
BEGIN
BUTTON ID_FILE_NEW
BUTTON ID_FILE_OPEN
BUTTON ID_FILE_SAVE SEPARATOR
BUTTON ID_EDIT_CUT
BUTTON ID_ EDIT_COPY
BUTTON ID_ EDIT _PASTE SEPARATOR
BUTTON ID_ FILE_PRINT
BUTTON ID_ APP_ABOUT
END
脚 本 里 的 BITMAP 语 句 指 向 保 存 位 图 的 项 目 的 Toolbar.bmp 文 件 。 TOOLBAR 语句 用 IDR_MAINFRAME 值 标 识 工 具 栏 资 源 , 并 为 每 个 按 钮 指 定 尺 寸 为 16 × 15 个 像 素 的 图 形 。 SEPARATOR 语 句 使 得 邻 近 按 钮 之 间 有 些 空 隙 , 它 是 通 过BUTTON 语 句 定 义 的 。
MFC 程 序 通 过 调 用 CToolBar::Create 来 创 建 工 具 栏 。当 函 数 返 回 时 , 它 创 建 的 工具 栏 只 不 过 是 一 个 空 的 子 窗 口 。 下 一 步 是 调 用 CToolBar::LoadToolBar 函 数 , 来读
取 工 具 栏 按 钮 数 据 , 装 载 工 具 栏 位 图 , 并 画 出 这 些 按 钮 , 所 有 这 些 都 在 一 步 内 完成 。
窗 口 为 每 一 个 在 工 具 栏 脚 本 里 的 BUTTON 语 句 提 供 一 个 空 按 钮 , 并 在 每 个 按 钮上 画 出 一 个 对 应 的 位 图 图 形 区 。 例 如 , 要 装 载 在 上 面 脚 本 里 定 义 的 工 具 栏 , 程 序可 以 声 明 一 个 CToolBar 对 象 , 叫 做 m_toolbar, 并 在 资 源 里 包 含 这 些 行 :
m_toolbar.Create( this ); // Create the toolbar window m_toolbar.LoadToolBar ( IDR_MAINFRAME ); // Load the bitmap images
在 Visual C++ 里 , 有 两 种 方 法 可 以 从 头 开 始 创 建 一 个 工 具 栏 。 第 一 个 方 法 是 我 们
很 熟 悉 的 : 在 一 个 打 开 的 项 目 里 , 单 击 Insert 菜 单 上 的 Resource , 并 双 击 在Resource Type 列 表 里 的 Toolbar。这 将 启 动 图 形 编 辑 器 , 以 便 对 工 具 栏 进 行 改 变 , 在 图 4-14 里 , 图 形 编 辑 器 显 示 了 三 个 分 割 的 窗 口 。 底 部 的 两 个 窗 口 显 示 了 你 正在 工 作 的 当 前 工 具 栏 按 钮 的 实 际 尺 寸 ,以 及 放 大 尺 寸 的 视 图 ,上 部 的 窗 口 显 示 了一 个 工 具 栏 的 完 整 视 图 。开 始 在 一 个 按 钮 上 工 作 时 , 按 钮 图 形 自 动 显 示 在 工 具 栏视 图 里 , 在 你 编 辑 时 , 实 时 改 变 按 钮 显 示 。 当 完 成 了 一 个 按 钮 时 , 单 击 上 面 窗 口里 空 的 新 项 目 按 钮 , 为 下 一 个 按 钮 刷 新 工 作 区 域 。 你 可 以 在 工 具 栏 里 拖 动 它 , 以改 变 按 钮 的 位 置 , 或 把 它 完 全 拉 离 工 具 栏 , 以 便 删 除 按 钮 。 要 在 如 图 4-14 里 所示 的 按 钮 之 间 添 加 分 割 空 隙 ,向 左 或 向 右 拖 动 一 个 按 钮 到 大 约 半 个 按 钮 宽 度 就 可以 了 。 你 可 以 用 同 样 的 方 法 去 掉 这 个 空 隙 。
图 4-14 在 Visual C++ 图 形 编 辑 器 中 创 建 工 具 栏
保 存 工 具 栏 时 , 不 要 担 心 空 的 项 目 按 钮 会 一 起 保 存 。 在 编 辑 器 写 到 RC 文 件 里 的工 具 栏 脚 本 里 , 不 会 包 括 空 的 项 目 按 钮 。 当 在 一 个 程 序 的 主 工 具 栏 中 工 作 时 , 应当 给 每 一 个 按 钮 同 菜 单 项 对 应 的 相 同 标 识 符 , 例 如 ID_FILE_NEW 或ID_FILE_PRINT 。在 Toolbar Button Properties ( 工 具 栏 按 钮 属 性 ) 对 话 框 里 输 入
按 钮 的 标 识 符 , 通 过 在 工 作 区 域 里 的 任 何 地 方 双 击 鼠 标 , 或 通 过 从 View ( 查 看 ) 菜 单 上 选 择 Propertie s, 来 显 示 上 述 对 话 框 。
在 创 建 工 具 栏 的 第 二 种 方 法 中 , 要 求 先 设 计 位 图 图 形 , 然 后 , 将 得 到 的 结 果 转 化为 工 具 栏 。 对 于 D iskPie1 , 这 种 方 法 更 加 方 便 些 。
为 DiskPie1 创 建 工 具 栏
D iskPie1 是 与 众 不 同 的 , 它 在 运 行 时 决 定 需 要 的 工 具 栏 按 钮 , 以 及 它 们 对 应 的 图形 的 个 数 。 在 D iskPie1.rc 文 件 里 , 工 具 栏 脚 本 只 有 一 个 入 口 :
IDR_MAINFRAME TOOLBAR 16, 15 BEGIN
BUTTON IDM_MEMORY
END
在 程 序 启 动 时 , 便 添 加 了 为 磁 盘 驱 动 器 显 示 使 用 状 况 饼 图 的 按 钮 。 例 如 , 如 果D iskPie1 找 到 了 四 个 磁 盘 驱 动 器 , 分 别 指 定 为 C , D , P 和 R , 那 么 , 在 它 创 建工 具 栏 时 , 它 指 定 五 个 按 钮 : 一 个 对 应 于 Memory 命 令 , 其 余 四 个 对 应 于 四 个 磁
盘 驱 动 器 。 由 于 在 D iskPie1 运 行 之 前 , 没 有 办 法 知 道 系 统 中 运 行 着 多 少 个 磁 盘驱 动 器 , 所 以 , DiskPie1 的 工 具 栏 位 图 有 24 个 不 同 磁 盘 驱 动 器 的 按 钮 图 形 , 它们 分 别 以 C 到 Z 标 记 。 由 于 这 25 个 图 形 都 是 16 个 像 素 宽 , 所 以 , D iskPie1 完整 的 工 具 栏 位 图 是 400 个 像 素 宽 、 15 个 像 素 高 。 在 图 4-15 中 , 可 以 看 到 一 些 按钮 图 形 的 特 写 视 图 。
图 4-15 DiskPie1 的 工 具 栏 位 图
可 以 看 到 , 生 成 位 图 并 不 是 十 分 困 难 , 只 用 了 大 约 20 分 钟 的 时 间 。 这 个 秘 密 就是 , 告 诉 图 形 编 辑 器 你 正 在 创 建 一 个 位 图 , 而 不 是 一 个 工 具 栏 。 第 一 步 在 下 列 两种 情 况 下 是 一 样 的 : 通 过 单 击 Insert 菜 单 上 的 Resource, 来 打 开 图 形 编 辑 器 。 为了 用 重 复 的 图 形 加 宽 如 图 4-15 所 示 的 位 图 , 从 资 源 类 型 列 表 里 选 择 Bitmap , 而不 是 Toolbar。 这 将 可 以 在 一 个 连 续 的 条 中 操 作 按 钮 图 形 , 而 单 独 操 作 每 个 按 钮 。在 图 形 编 辑 器 里 , 将 普 通 位 图 转 换 为 工 具 栏 是 很 容 易 的 , 设 计 它 就 是 做 这 个 的 。
这 里 是 使 用 重 复 图 形 生 成 加 宽 的 位 图 的 步 骤 。双 击 编 辑 器 工 作 区 域 的 空 白 区 域 的任 何 地 方 , 打 开 Bitmap Properties 对 话 框 。 输 入 工 具 栏 标 识 符 , 对 于 D iskPie1 ,
是 IDR_MAINFRAM E , 并 给 B M P 文 件 起 一 个 文 件 名 。 通 过 增 加 按 钮 的 数 目 , 来 增 加 一 个 工 具 栏 按 钮 的 宽 度 ,并 输 入 这 个 数 字 作 为 位 图 的 宽 度 。 位 图 的 高 度 是一 个 按 钮 的 高 度 。 对 于 DiskPie1 , 对 话 框 看 起 来 像 这 样 :
按 下 Enter 键 返 回 工 作 区 域 , 现 在 它 有 了 新 的 尺 寸 。 下 一 步 , 用 亮 灰 色 画 出 整 个工 作 区 域 , 以 便 每 一 个 图 形 能 和 它 的 按 钮 相 融 合 。 在 Color 调 色 板 里 单 击 亮 灰 色框 , 并 选 择 Graphics 工 具 栏 里 的 Fill 工 具 。
单 击 工 作 区 域 格 子 里 的 任 何 地 方 , 来 用 亮 灰 色 画 整 个 区 域 。 现 在 , 在 工 作 区 域 里的 一 个 16 × 15 的 块 里 , 画 第 一 个 按 钮 的 图 形( 或 是 任 何 的 按 钮 尺 寸 )。 一 旦 已 经画 出 第 一 个 图 形 , 就 可 以 通 过 单 击 Rectangle Selection 工 具 来 复 制 它 , 并 在 图 形的 16 × 15 方 块 上 拖 动 光 标 。 是 用 鼠 标 左 键 , 还 是 用 右 键 拖 动 , 取 决 于 你 是 移 动这 个 位 图 , 还 是 拷 贝 它 。 如 果 想 移 动 图 形 到 位 图 工 作 区 域 的 其 他 地 方 , 那 么 使 用鼠 标 左 键 。 当 你 释 放 鼠 标 按 钮 时 , 在 图 形 的 周 围 出 现 一 个 选 择 框 , 此 时 可 以 拖 动它 来 重 新 定 位 选 择 区 域 。按 下 Ctrl 键 拖 动 选 择 框 ,便 移 动 了 被 选 择 图 形 的 一 个 副本 , 而 不 是 图 形 本 身 , 但 是 , 有 一 种 更 好 的 方 法 来 复 制 图 形 。
要 生 成 一 个 图 形 的 副 本 , 需 单 击 Rectangle Selection ( 选 择 ) 工 具 , 并 用 按 下 鼠标 右 键( 而 不 是 鼠 标 左 键 ) 来 选 择 图 形 。 释 放 鼠 标 按 钮 时 , 被 选 择 图 形 的 一 个 副
本 将 跟 随 鼠 标 光 标 而 移 动 。 将 副 本 定 位 在 工 作 区 域 的 任 何 地 方 , 并 单 击 , 将 它 放置 在 选 择 的 位 置 上 。单 击 左 键 将 放 下 图 形 的 一 个 副 本 , 单 击 右 键 将 放 下 图 形 的 遮罩 , 其 中 , 前 景 像 素 转 化 为 当 前 图 形 的 背 景 颜 色 , 图 形 里 的 背 景 像 素 被 当 作 透 明的 小 洞 。 你 可 以 用 这 种 方 法 生 成 任 何 数 量 的 副 本 。 完 成 操 作 时 , 按 下 ESC 键 , 或 选 择 另 一 个 工 具 来 返 回 一 般 编 辑 模 式 。
你 将 发 现 图 形 横 越 整 个 16 × 15 方 块 , 像 图 4-16 里 的 磁 盘 驱 动 器 图 形 一 样 , 那 么定 位 它 将 更 加 容 易 。 如 果 图 形 比 方 块 窄 , 那 么 在 方 块 的 顶 部 或 底 部 画 一 条 16 个像 素 宽 的 临 时 黑 线 。 然 后 , 当 你 拷 贝 图 形 时 , 就 可 以 准 确 看 到 正 在 拖 动 什 么 。 如果 你 打 算 使 用 文 本 标 记 每 一 个 按 钮 , 像 图 4-15 里 所 做 的 那 样 , 那 么 , 最 后 , 在所 有 的 图 形 都 到 位 后 , 将 添 加 标 记 。 单 击 Text 工 具 , 输 入 文 字 , 并 拖 动 文 字 图形 到 指 定 位 置 。 在 做 完 每 一 个 文 字 之 后 , 按 下 ESC 键 取 消 Text 工 具 。
图 4-16 复 制 选 择 的 图 形
完 成 了 位 图 的 设 计 时 ,单 击 Image 菜 单 上 的 Toolbar Editor,来 转 化 位 图 到 一 个 工具 栏 上 , 在 New Toolbar Resource ( 新 工 具 栏 资 源 ) 对 话 框 里 , 接 受 建 议 的 16 × 15 的 按 钮 尺 寸 。 你 可 以 使 用 相 同 的 Toolbar Editor 命 令 , 在 工 具 栏 和 位 图 之 间 来回 转 换 。 单 击 File( 文 件 ) 菜 单 上 的 Sav e( 保 存 ) 命 令 , 将 新 的 工 具 栏 脚 本 写 到RC 文 件 里 , 并 将 工 具 栏 位 图 保 存 成 在 前 面 Bitmap Properties 对 话 框 里 命 名 的B M P 文 件 。 Visual C++ 为 新 工 具 栏 脚 本 中 的 按 钮 指 定 默 认 的 标 识 符 值 , 现 在 , 在D iskPie1.rc 文 件 里 , 它 们 看 起 来 像 下 面 这 样 :
IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15 BEGIN
BUTTON ID_BUTTON40030 BUTTON ID_BUTTON40031
BUTTON ID_BUTTON40032
.
.
. END
按 钮 标 识 符 最 终 必 须 改 成 同 对 应 菜 单 命 令 的 标 识 符 相 同 的 标 识 符 , 即IDM_MEMORY , IDM_DISK_C , IDM_DISK_D 等 等 。这 将 保 证 单 击 一 个 工 具 栏按 钮 有 同 选 择 相 应 菜 单 命 令 相 同 的 效 果 。 我 们 应 该 使 用 Toolbar Button Properties 对 话 框 ,在 图 形 编 辑 器 里 具 有 指 定 的 正 确 按 钮 标 识 符 , 调 用 这 个 对 话 框 的 方 法 是选 择 一 个 按 钮 ,并 双 击 工 作 区 域 的 任 何 地 方 。但 是 ,这 没 有 什 么 必 要 。当 D iskPie1 确 定 运 行 时 必 须 在 工 具 栏 上 显 示 多 少 按 钮 时 , D iskPie1 给 按 钮 指 定 正 确 的 值 。 在后 面 , 我 们 将 编 辑 工 具 栏 脚 本 , 用 在 这 节 开 头 引 用 的 简 短 的 脚 本 来 代 替 它 , 同 时也 从 Resource.h 文 件 中 移 去 为 按 钮 标 识 符 定 义 的 多 余 的 #define 语 句 。
图 标
图 标 是 特 殊 的 位 图 , 设 计 用 来 用 图 形 方 式 表 示 程 序 或 文 档 。 一 般 情 况 下 , 图 标 指定 给 一 个 框 架 窗 口 ,以 便 在 窗 口 的 标 题 栏 里 显 示 图 形 , 当 图 标 指 定 给 程 序 的 主 窗口 时 ,图 标 资 源 叫 做 程 序 图 标 或 应 用 程 序 图 标 。本 节 集 中 讲 述 怎 样 创 建 应 用 程 序图 标 , 它 是 最 普 遍 使 用 的 一 种 图 标 资 源 。 但 是 , 不 管 图 标 是 表 示 主 窗 口 , 还 是 屏幕 上 的 另 一 个 对 象 , 图 标 不 过 就 是 图 标 , 它 是 在 Visual C++ 图 形 编 辑 器 里 创 建的 , 而 且 创 建 的 方 式 相 同 。
-
个 图 标 资 源 包 含 多 个 图 形 , 它 们 经 常 是 同 样 设 计 的 不
同 尺 寸 的 图 形 。 例 如 , M icrosoft 建 议 , W indows 程 序 提 供 给 它 图 标 资 源 的 三 个 图 形 , 每 一 个 图 形 具 有不 同 的 尺 寸 :
-
一 个 边 长 为 16 个 像 素 的 正 方 形 , 16 色 图 形 , Windows
将 在 程 序 的 标题 栏 、 任 务 栏 和 用 小 图 标 显 示 的 目 录 列 表 里 显 示 它 。
-
边 长 为 32 个 像 素 的 正 方 形 , 16 色图形,在 Abou t( 关 于
) 对 话 框 这 样的 对 话 框 窗 口 里 使 用 , 或 在 桌 面 上 表 示 程 序 , 或 在 用 大 图 标 显 示 的 目录 列 表 里 显 示 。
-
边 长 为 48 个 像 素 的 256 色 图 形 , 在 系 统 D isplay
Properties 对 话 框 里 , 若 选 中 Effects( 效 果 ) 选 项 卡 里 的 Use Large Ico n( 使 用 大 图 标 ) 选 项
-
时 , 它 在 Windows 98 里 代 替 32 × 32 图 标 ( 要 打 开 这 个 对 话 框 , 在 桌面 空 白 区 域 按 下 鼠 标 右 键 , 并 选 择 Properties 。 W indows 95 要 求 安 装M icrosoft Plus! 包 ,在 这 种 情 况 下 ,Use Large Icons 选 项 在 对 话 框 的 Plus! 选 项 卡 里 )。
你 可 以 在 Explorer( 资 源 管 理 器 ) 窗 口 里 看 到 大 的 和 小 的 应 用 程 序 图 标 的 例 子 , 或 在 Visual C++ 环 境 里 通 过 打 开 Save A s( 另 存 为 )或 Ope n( 打 开 ) 对 话 框 看 到 。在 目 录 列 表 窗 口 的 空 白 区 域 右 击 , 并 从 上 下 文 菜 单 的 View 命 令 中 选 择 Large Icon s( 大 图 标 )。同 一 个 菜 单 里 的 Small Icon s( 小 图 标 )命 令 显 示 16 × 16 的 图 形 。
在 W indows 编 程 中 , 应 当 使 用 具 有 独 特 魅 力 的 图 标 , 但 这 不 是 必 须 的 。 如 果 一个 程 序 在 它 的 资 源 里 根 本 不 包 括 任 何 图 标 , 它 仍 可 以 使 用 在 W inuser.h 文 件 里 的标 准 系 统 图 标 , 像 IDI_APPLICATION 和 IDI_WINLOGO 。 当 系 统 图 标 处 于 16
× 16 像 素 尺 寸 状 态 下 , 它 们 看 起 来 像 下 面 这 样 :
在 一 个 图 标 资 源 里 封 装 的 三 个 图 形 , 可 以 将 可 执 行 文 件 的 大 小 增 加 大 约 5000 个字 节 。如 果 它 看 起 来 太 大 ,便 可 以 用 一 个 单 独 的 16 × 16 或 32 × 32 图 形 创 建 一 个图 标 , 当 用 其 他 尺 寸 显 示 图 标 时 , W indows 按 适 当 的 比 例 显 示 。 然 而 , 你 可 能 对这 个 结 果 感 到 失 望 , 因 为 曲 线 和 斜 线 将 产 生 边 界 粗 糙 的 效 果 。
下 一 节 显 示 怎 样 用 Visual C++ 图 形 编 辑 器 创 建 一 个 图 标 , 但 是 , 首 先 让 我 们 看 一下 程 序 怎 样 加 载 图 标 资 源 。 通 常 , C 程 序 在 它 创 建 主 程 序 窗 口 时 加 载 应 用 程 序 图标 。 如 果 图 标 资 源 只 包 含 一 个 图 形 尺 寸 , 那 么 程 序 可 以 调 用 LoadIcon API 函 数
( 在 旧 的 W indows 版 本 里 使 用 的 方 法 )。 但 是 , 要 从 相 同 的 图 标 资 源 里 加 载 多 个图 形 , 这 个 程 序 应 该 使 用 LoadImage 函 数 代 替 前 面 的 函 数 。 由 于 使 用 旧 版 本 的WNDCLASS 结 构 的 RegisterClass 函 数 只 接 受 一 个 图 标 句 柄 , 所 以 , 程 序 也 必 须调 用 指 向 WNDCLASSEX 结 构 的 RegisterClassEx 函 数 , 为 窗 口 类 设 定 大 的 和 小的 图 标 。 这 里 是 一 个 加 载 两 个 图 标 图 形 的 代 码 段 , 一 个 是 边 长 为 16 个 像 素 的 正方 形 , 另 一 个 是 边 长 为 32 个 像 素 的 正 方 形 :
// Declare the icon in the .RC file
IconDemo ICON “ res\\appicon.ico ”
//In WinMain, initialize the WNDCLASSEX structure with image handles static char szAppName[]= ” IconDem o” ;
WNDCLASSEX wndclass; wndclass.cbSize = sizeof (wndclass);
wndclass.hIcon = LoadImage( nhInstance, szAppName,IMAGE_ICON,
32,32 LR_DEFAULTCOLOR );
wndclass.hIconSm = LoadImage(hInstance,szAppName,IMAGE_ICON,
16,16, LR_DEFAULTCOLOR );
.
.
.
RegisterClassEx( &wndclass );
MFC 程 序 不 需 要 担 心 任 何 上 面 这 种 情 况 。 AppWizard 为 项 目 提 供 两 个 图 标 , 一个 图 标 提 供 应 用 程 序 图 标 的 功 能 , 另 一 个 表 示 应 用 程 序 创 建 的 文 档 。 RC 文 件 用IDR_MAINFRAME 和 IDR_project_TYPE 标 识 图 标 资 源 , 这 里 的 project 代 表 项目 名 。 AppWizard 保 存 图 标 , 如 下 所 示 , 在 项 目 的 Res 文 件 夹 里 以 project.ico 和projectDoc.ico 表 示 :
AppWizard 自 动 生 成 正 确 加 载 同 程 序 的 其 他 资 源 在 一 起 的 应 用 程 序 图 标 的 代码 。 要 使 用 你 设 计 的 图 标 来 代 替 常 规 的 AppWizard 图 标 , 需 关 闭 项 目 的 工 作 空间 , 并 从 File( 文 件 ) 菜 单 里 选 择 New 。 双 击 在 File 选 项 卡 里 的 Icon File ( 图 标文 件 )来 打 开 图 形 编 辑 器 ,设 计 这 个 新 图 标 ,并 把 它 保 存 在 项 目 的 Res 文 件 夹 里 , 重 新 覆 盖 已 经 存 在 的 project.ico 和 projectDoc.ico 文 件 。
如 果 你 已 经 能 够 不 使 用 AppWizard 的 帮 助 来 写 MFC 程 序 , 那 么 , 加 载 应 用 程 序的 图 标 仍 然 是 很 简 单 的 。 如 果 主 窗 口 类 是 来 自 CFrameWnd , 那 么 , 使 用 在 MFC 的 Afres.h 文 件 里 定 义 的 AFX_IDI_STD_FRAME 值 来 标 识 ICO 文 件 。 例 如 , 在项 目 的 RC 文 件 中 , 在 名 为 AppIcon.ico 文 件 里 保 存 的 图 标 资 源 按 如 下 方 式 进 行标 识 :
#include "afxres.h"
.
.
.
AFX_IDI_STD_FRAME ICON appicon.ico
如 果 窗 口 类 来 自 CMDIFrameWnd , 那 么 使 用 这 一 行 代 替 上 面 这 一 行 。
AFX_IDI_STD_MDIFRAME ICON appicon.ico
如 果 图 标 文 件 同 时 包 含 一 个 大 的 和 一 个 小 的 图 形 , 那 么 MFC 加 载 这 些 图 形 , 并把 它 们 同 窗 口 框 架 正 确 关 联 , 以 便 小 图 形 显 示 在 标 题 栏 上 , 大 图 形 显 示 在 About
( 关 于 ) 对 话 框 里 。如 果 你 浏 览 MFC 源 代 码 , 来 学 习 有 关 这 些 工 作 的 更 多 信 息 , 那 么 你 将 看 到 CWinApp::LoadIcon 并 不 像 前 面 描 述 的 那 样 调 用 ::LoadImage 。 相
反 , 它 调 用 使 用 RT_GROUP_ICON 值 的 ::FindResource 函 数 , 来 从 图 标 资 源 里 加载 所 有 的 图 形 , 然 后 搜 索 图 形 资 源 , 来 查 找 最 符 合 所 需 要 尺 寸 的 图 形 。CWinApp::LoadIcon 检 索 图 形 的 方 法 是 ,使用 ::FindResource 函 数 返 回 的 实 例 值 来调 用 ::LoadIcon 函 数 。
为 DiskPie1 创 建 图 标
创 建 D iskPie1 应 用 程 序 图 标 的 过 程 是 , 在 打 开 的 项 目 里 单 击 Visual C++ Insert 菜单 上 的 Resource 命 令 , 然 后 , 双 击 Resource Type 列 表 里 的 Icon 。 图 形 编 辑 器 默认 打 开 一 个 边 长 为 32 个 像 素 的 正 方 形 16 色 工 作 区 域 ,Windows 在 里 面 调 用 大 的或 标 准 的 图 标 尺 寸 。 编 辑 器 在 工 作 区 域 上 面 的 Device 组 合 框 中 , 显 示 当 前 的 标准 (32 × 32) 尺 寸 。 组 合 框 的 下 拉 列 表 中 只 包 含 一 个 尺 寸 , 这 意 味 着 , 你 当 前 正 在操 作 的 图 标 有 一 个 图 形 , 并 且 是 边 长 为 32 个 像 素 的 正 方 形 。
Visual C++ 图 形 编 辑 器 可 以 创 建 有 任 何 图 形 数 目 的 图 标 资 源 , 每 一 个 都 有 不 同 的尺 寸 ,或 含 有 不 同 的 颜 色 。要 看 其 他 可 用 的 尺 寸 ,可 以 按 下 Insert 键 、选 择 Image 菜 单 的 New Device Image , 或 者 单 击 New Device Image 按 钮 :
上 述 方 法 都 会 打 开 图 4-17 里 的 New Icon Image 对 话 框 , 在 这 里 , 显 示 了 可 用 的图 形 尺 寸 , 但 是 还 没 有 与 图 标 关 联 。 如 果 你 在 列 表 里 没 有 看 到 想 要 的 尺 寸 , 可 单击 Custom 按 钮 , 并 指 定 一 个 新 的 图 形 尺 寸 。
图 4-17 为图标选择新的图形
在 New Icon Image 对 话 框 中 ,提 供 了 在 一 个 图 标 资 源 里 包 含 多 个 图 形 的 方 法 。在你 画 完 这 个 标 准 的 32 × 32 大 小 的 图 形 之 后 , 从 对 话 框 里 选 择 另 一 个 尺 寸 , 并 重新 开 始 。 如 果 你 想 切 换 回 原 来 的 32 × 32 大小的图形,在 Device 组 合 框 里 单 击 下拉 箭 头 , 并 从 打 开 的 列 表 里 选 择 Standard(32 × 32)。 当 你 从 New Icon Image 对 话
框 里 选 择 了 新 的 图 形 尺 寸 时 ,这 个 条 目 从 对 话 框 的 列 表 里 消 失 , 并 传 递 给 组 合 框列 表 。换 句 话 说 ,Device 组 合 框 列 出 当 前 在 图 标 里 的 图 形 尺 寸 ,而 New Icon Image 对 话 框 显 示 可 添 加 到 图 标 的 尺 寸 。要 从 图 标 里 移 去 当 前 图 形 ,单击 Image 菜 单 上的 Delete Device Image( 删 除 设 备 图 形 )。
D iskPie1 图 标 有 三 个 图 形 尺 寸 , 范 围 从 边 长 为 16 个 像 素 到 48 个 像 素 的 正 方 形 :
- 般 情 况 下 , 程 序 图 标 里 的 图 形 是 相 同 的 图 片 , 但 是 尺
寸 不 同 。 我 给 出 了 三 种 不同 的 设 计 图 形 , 来 清 楚 地 显 示 W indows 从 DiskPie1 的 资 源 数 据 里 提 取 正 确 的 图形 ,而 不 是 按 比 例 显 示 图 形 。双 击 编 辑 器 工 作 区 域 的 任 何 地 方 打 开 Icon Properties
对 话 框 , 并 把 IDR_MAINFRAM 标 识 符 指 定 给 资 源 , 并 保 存 工 作 。
鼠 标 光 标
就 DiskPie1 这 个 程 序 来 说 , 不 需 要 设 计 一 个 定 制 的 鼠 标 光 标 , 但 是 , 让 我 们 花一 些 时 间 ,来 看 一 下 Visual C++ 是 怎 样 做 这 些 工 作 的 。鼠 标 光 标 是 一 个 边 长 为 32 个 像 素 的 单 色 位 图 , 它 有 透 明 的 背 景 和 一 个 “ 热 点 ”。 热 点 是 位 图 里 的 一 个 单 独的 像 素 , W indows 把 它 当 做 鼠 标 的 坐 标 。 例 如 , 当 一 个 程 序 接 收 到 一 个W M _ M O U S E M O V E 或 一 个 WM_LBUTTONDOWN 消 息 时 , 鼠 标 光 标 的 x 和 y 坐 标 保 存 在 消 息 的 lParam 值 里 , 表 明 这 个 在 光 标 热 点 下 面 的 像 素 坐 标 :
case WM_LBUTTONDOWN:
x= LOWORD(lParam);//x-coordinate of mouse click y= HIWORD(lParam);//y-coordinate of mouse click
要 创 建 一 个 鼠 标 光 标 , 或 者 从 File 菜 单 里 选 择 New ( 新 建 ) 命 令 , 然 后 双 击 在File 选 项 卡 里 的 Cursor File ( 光 标 文 件 ), 或 者 , 对 于 一 个 已 经 存 在 的 项 目 , 从Insert 菜 单 里 选 择 Resource 命 令 。 双 击 列 表 里 的 Cursor, 可 以 提 供 一 个 空 白 的 方块 , 你 可 以 在 上 面 设 计 新 光 标 。 如 果 要 从 一 个 标 准 的 W indows 光 标 图 形 开 始 设计 , 那 么 , 展 开 Cursor 标 题 , 并 从 IDC_NODROP , IDC_POINTER 或
IDC_POINTER_COPY 里 选 择 。 编 辑 器 显 示 一 个 边 长 为 32 个 像 素 的 工 作 区 域 , 你 将 在 上 面 画 光 标 。如 果 你 已 经 有 了 想 使 用 的 图 形 ,但 它 是 另 一 种 形 式 ,例如 32
× 32 的 位 图 , 那 么 , 首 先 在 图 形 编 辑 器 里 打 开 位 图 , 并 按 下 Ctrl+C 将 图 形 拷 贝到 剪 贴 板 。 然 后 打 开 一 个 新 的 光 标 , 并 按 下 Ctrl+V 来 粘 贴 位 图 到 光 标 工 作 区 域 。位 图 里 的 颜 色 被 转 化 为 黑 色 或 透 明 色 ,这 取 决 于 它 们 的 亮 度 。如 果 你 不 喜 欢 这 个结 果 , 那 么 按 下 Del 键 删 除 光 标 图 形 。
当 图 形 编 辑 器 加 载 一 个 光 标 图 形 时 , 一 个 Set Hotspo t( 设 置 热 点 ) 按 钮 显 示 在 工作 区 域 窗 口 的 上 面 。 你 可 以 在 图 4-18 里 看 到 这 个 用 坐 标 ( 0 , 13 ) 标 记 的 按 钮 , 将 热 点 放 在 图 中 啮 齿 动 物 的 鼻 子 上 。 单 击 Set Hotspo t( 设 置 热 点 ) 按 钮 , 然 后 单击 图 形 表 格 里 想 设 置 光 标 热 点 的 点 。 完 成 时 , 从 File ( 文 件 ) 菜 单 里 选 择 Save , Visual C++ 将 把 这 个 图 形 保 存 成 一 个 C U R 文 件 , 像 下 面 这 样 添 加 定 义 到 项 目 的RC 文 件 里 :
IDC_CURSOR1 COUSOR DISCARDABLE "res\\cursor1.cur"
图 4-18 在 Visual C++ 图形编辑器中创建定制的鼠标光标
设 置 新 的 光 标 作 为 程 序 的 默 认 光 标 , 需 要 调 用 LoadCursor API 函 数 。 在 一 个 C 程 序 里 , 当 为 窗 口 初 始 化 WNDCLASS 或 WNDCLASSEX 结 构 时 , 这 是 典 型 的做 法 。 这 里 是 设 置 新 的 IDC_CURSOR1 资 源 的 方 式 :
WNDCLASSEX wndclass; wndclass.hCursor = LoadCursor( hInstance,
MAKEINTRESOURCE (IDC_CURSOR1) );
.
.
.
RegisterClassEx( &wndclass);
对 于 通 过 字 符 串 名 标 识 的 光 标 资 源 , 字 符 串 是 名 字 , 而 不 是 值 , 方 法 几 乎 和 下 面一 样 :
//Resource declaration in the RC file
MouseDemo CURSOR “ mouse.cur”
//Load and set resource during initialization in the C source file static char szAppName[ ] = “ MouseDem o”
WNDCLASSEX wndclass;
wndclass.hCursor = LoadCursor( hInstance, szAppName );
你 可 以 在 一 个 MFC 程 序 里 使 用 AfxRegisterWndClass 全 局 函 数 做 相 同 的 事 。下 面的 例 子 为 AfxRegisterWndClass 函 数 的 最 后 一 个 参 数 使 用 一 个 常 规 图 标 , 但 是 , 真 正 的 应 用 程 序 应 该 提 供 它 自 己 的 图 标 句 柄 :
CString wndclass = AfxRegisterWndClass( CS_HREDRAW | CS_VREDRAW,
::LoadCursor( hInstance,szAppName ), (HBRUSH) (COLOR_WINDOW + ),
theApp.LoadStandardIcon( IDI_APPLICATION ) );
利 用 这 些 命 令 ,无 论 鼠 标 指 针 位 于 程 序 用 户 区 域 的 任 何 地 方 ,W indows 都 会 显 示新 的 鼠 标 。 图 4-19 显 示 了 上 面 设 计 的 光 标 在 一 个 程 序 的 外 观 ( 你 可 以 从 随 书 所附 CD 里 的 Code\Chaper.04\Mouse 子 文 件 夹 里 找 到 这 个 很 小 的 C 程 序 源 代 码 )。
图 4-19 新 的 鼠 标 光 标 在 程 序 中 出 现
光 标 就 讲 这 些 吧 , 我 们 再 来 谈 谈 DiskPie1 程 序 。
向 DiskPie1 添 加 代 码
现 在 , D iskPie1 有 菜 单 、 加 速 键 、 工 具 栏 、 状 态 栏 和 图 标 , 这 些 是 需 要 的 所 有 资源 。 现 在 , 可 以 添 加 代 码 使 它 执 行 。 如 果 你 在 本 章 里 依 照 DiskPie1 的 生 成 过 程进 行 , 那 么 , 你 将 可 以 识 别 在 图 4-20 里 的 用 户 界 面 元 素 。 应 用 程 序 图 标 、 菜 单 、工 具 栏 和 状 态 栏 是 在 前 面 几 节 里 用 Visual C++ 资 源 编 辑 器 设 计 的 。
在 创 建 主 窗 口 的 过 程 中 , D iskPie1 将 找 到 所 有 连 接 的 固 定 磁 盘 , 包 括 远 程 驱 动 器和 RAM 驱 动 器 , 每 找 到 一 个 它 , 都 要 做 下 面 这 些 工 作 :
图 4-20 DiskPie1 程序,显示 8MB RAM 磁盘上的可用空间
-
向 Chart 菜 单 添 加 一 个 叫 做 Disk x 的 命 令 ,这 里 x 是 磁 盘
的 指 定 字 母 。
-
在 工 具 栏 里 添 加 一 个 按 钮 , 从 表 示 驱 动 器 C 到 Z 的 工
具 栏 位 图 中 , 从
24 个 图 像 中 选 择 按 钮 的 图 形 。
左 下 角 的 文 本 指 出 饼 图 的 类 型 , 或 者 是 内 存 , 或 者 是 本 地 固 定 的 驱 动 器 、 R A M 驱 动 器 或 远 程 驱 动 器 。 饼 图 由 两 部 分 组 成 , 分 别 标 记 为 “ Used ” 和 “ Free ”。 内存 的 总 数 量 或 磁 盘 的 容 量 通 过 右 下 角 的 图 表 表 示 。
虽 然 DiskPie1 是 一 个 相 当 小 的 程 序 , 但 是 , 它 使 用 通 用 的 C++ 方 式 进 行 编 译 , 将 类 分 开 放 在 分 开 的 资 源 文 件 里 。 完 整 的 程 序 列 在 后 面 , 在 随 书 附 带 的 CD 里 的Code\Chapter.04\DiskPie1 子 文 件 夹 里 , 可 以 读 取 这 些 程 序 。如 果 你 已 经 跟 随 本 章里 的 步 骤 , 为 新 的 D iskPie1 项 目 创 建 了 资 源 , 那 么 , 你 可 能 想 完 成 这 个 项 目 , 并 为 这 个 程 序 建 立 你 自 己 的 版 本 。 在 这 种 情 况 下 , 拷 贝 H 和 CPP 资 源 文 件 到 你的 项 目 文 件 夹 , 并 使 用 Projec t( 项 目 ) 菜 单 里 的 Add To Project 命 令 添 加 CPP 文件 。 此 代 码 要 求 有 一 个 Abou t( 关 于 ) 对 话 框 , 所 以 , 使 用 文 本 编 辑 器 从 CD 上的 DiskPie1.rc 文 件 里 拷 贝 和 粘 贴 脚 本 到 你 自 己 的 RC 文 件 。要 记 住 ,需除掉工具栏 脚 本 , 使 它 像 “ 为 DiskPie1 创 建 工 具 栏 ” 一 节 中 给 出 的 那 样 。
下 面 的 目 录 描 述 了 D iskPie1 源 文 件 , 可 以 帮 助 你 理 解 在 列 表 4-1 中 的 代 码 。
源 文 件 说 明
D iskPie InitInstance 函 数 , 显 示 About 对话
M ainFrm1 创 建 主 窗 口 , 确 定 可 用 的 驱 动 器 , 并 为 每 个 驱 动 器 添 加菜 单 命 令 和 工 具 栏 按 钮
D iskDoc 确 定 当 前 内 存 和 磁 盘 的 使 用 状 况
D iskView 包含 OnDraw 函 数 , 它 为 当 前 的 使 用 状 况 数 据 显 示 饼 图
列表 4-1 DiskaPie1 源文件
Resource.h
// ********************************************************************
//
// Resource.h
//
// ********************************************************************
#define IDD_ABOUTBOX 100
#define IDR_MAINFRAME 101
#define IDM_MEMORY 130
#define IDM_DISK_C 131
#define IDM_DISK_D 132
#define IDM_DISK_E 133
#define IDM_DISK_F 134
#define IDM_DISK_G 135
#define IDM_DISK_H 136
#define IDM_DISK_I 137
#define IDM_DISK_J 138
#define IDM_DISK_K 139
#define IDM_DISK_L 140
#define IDM_DISK_M 141
#define IDM_DISK_N 142
#define IDM_DISK_O 143
#define IDM_DISK_P 144
#define IDM_DISK_Q 145
#define IDM_DISK_R 146
#define IDM_DISK_S 147
#define IDM_DISK_T 148
#define IDM_DISK_U 149
#define IDM_DISK_V 150
#define IDM_DISK_W 151
#define IDM_DISK_X 152
#define IDM_DISK_Y 153
#define IDM_DISK_Z 154
DiskPie1.rc
// ********************************************************************
//
// DiskPie1.rc
//
// ********************************************************************
#include "resource.h"
#include "afxres.h"
IDR_MAINFRAME ICON "res\\diskpie1.ico"
IDR_MAINFRAME BITMAP "res\\toolbar.bmp"
IDR_MAINFRAME MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Chart"
BEGIN
MENUITEM "&Memory\tCtrl+M", IDM_MEMORY
MENUITEM SEPARATOR
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
"F", IDM_DISK_F, VIRTKEY
"G", IDM_DISK_G, VIRTKEY
"H", IDM_DISK_H, VIRTKEY
"I", IDM_DISK_I, VIRTKEY
"J", IDM_DISK_J, VIRTKEY
"K", IDM_DISK_K, VIRTKEY
"L", IDM_DISK_L, VIRTKEY
"M", IDM_DISK_M, VIRTKEY
"N", IDM_DISK_N, VIRTKEY
"O", IDM_DISK_O, VIRTKEY
"P", IDM_DISK_P, VIRTKEY
"Q", IDM_DISK_Q, VIRTKEY
BUTTON IDM_MEMORY
END
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 240, 65
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About DiskPie1"
FONT 8, "MS Sans Serif"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,10,22,20,20
LTEXT "DiskPie1 Version 1.0",IDC_STATIC,45,10,115,8
LTEXT """Microsoft Visual C++ Programmer's Guide""",IDC_STATIC,45,26,140,8
IDM_DISK_H "Usage for drive H\nDrive H"
IDM_DISK_I "Usage for drive I\nDrive I"
IDM_DISK_J "Usage for drive J\nDrive J"
IDM_DISK_K "Usage for drive K\nDrive K"
IDM_DISK_L "Usage for drive L\nDrive L"
IDM_DISK_M "Usage for drive M\nDrive M"
IDM_DISK_N "Usage for drive N\nDrive N"
IDM_DISK_O "Usage for drive O\nDrive O"
IDM_DISK_P "Usage for drive P\nDrive P"
IDM_DISK_Q "Usage for drive Q\nDrive Q"
IDM_DISK_R "Usage for drive R\nDrive R"
IDM_DISK_S "Usage for drive S\nDrive S"
IDM_DISK_T "Usage for drive T\nDrive T"
IDM_DISK_U "Usage for drive U\nDrive U"
IDM_DISK_V "Usage for drive V\nDrive V"
IDM_DISK_W "Usage for drive W\nDrive W"
IDM_DISK_X "Usage for drive X\nDrive X"
IDM_DISK_Y "Usage for drive Y\nDrive Y"
IDM_DISK_Z "Usage for drive Z\nDrive Z"
AFX_IDS_IDLEMESSAGE "Ready"
AFX_IDS_SCSIZE "Change the window size"
AFX_IDS_SCMOVE "Change the window position"
AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
END
DiskPie1.h
// ********************************************************************
//
// DiskPie.h
//
// ********************************************************************
class CDiskPieApp : public CWinApp
{
public:
virtual BOOLInitInstance();
afx_msg voidOnAppAbout();
DECLARE_MESSAGE_MAP()
};
DiskPie.cpp
// ********************************************************************
//
// DiskPie.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include <afxext.h>
#include "resource.h"
#include "DiskPie.h"
#include "DiskDoc.h"
#include "MainFrm1.h"
#include "DiskView.h"
CDiskPieApp theApp;
BEGIN_MESSAGE_MAP (CDiskPieApp, CWinApp)
ON_COMMAND (ID_APP_ABOUT, OnAppAbout)
END_MESSAGE_MAP ()
BOOL CDiskPieApp::InitInstance()
{
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME,
RUNTIME_CLASS (CDiskDoc),
RUNTIME_CLASS (CMainFrame),
RUNTIME_CLASS (CDiskView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
if (!ProcessShellCommand(cmdInfo))
return FALSE;
return TRUE;
}
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
enum { IDD = IDD_ABOUTBOX };
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CDiskPieApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
DiskDoc.h
// ********************************************************************
//
// DiskDoc.h
//
// ********************************************************************
class CDiskDoc : public CDocument
{
DECLARE_DYNCREATE (CDiskDoc)
public:
static int iDriveType[24];
static DWORDdwTotal, dwFree;
static int iChartType;
static UINT nCurrent;
int GetDriveCount();
void GetMemoryUsage();
void GetDiskUsage( UINT nID );
};
DiskDoc.cpp
// ********************************************************************
//
// DiskDoc.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include "resource.h"
#include "DiskPie.h"
#include "DiskDoc.h"
#define PIE_MEMORY 0;
IMPLEMENT_DYNCREATE (CDiskDoc, CDocument)
int CDiskDoc::iDriveType[24],
int CDiskDoc::iChartType = PIE_MEMORY;
UINT CDiskDoc::nCurrent = IDM_MEMORY;
D W O R D CDiskDoc::dwTotal, CDiskDoc::dwFree;
void CDiskDoc::GetMemoryUsage ()
{
MEMORYSTATUSms;
::GlobalMemoryStatus( &ms );
dwTotal= ms.dwTotalPhys;
dwFree = ms.dwAvailPhys;
iChartType = PIE_MEMORY;
nCurrent = IDM_MEMORY;
}
void CDiskDoc::GetDiskUsage( UINT nID )
{
char szDrive[] = "x:\\\0";
DWORD dwSectsPerClust, dwBytesPerSect, dwFreeClusts, dwTotalClusts;
DWORD dwBytesPerClust;
GetDriveCount();
if (iDriveType[nID - IDM_DISK_C] == DRIVE_FIXED ||
iDriveType[nID - IDM_DISK_C] == DRIVE_REMOTE ||
iDriveType[nID - IDM_DISK_C] == DRIVE_RAMDISK)
{
szDrive[0] = (char) (nID - IDM_DISK_C) + 'C';
if (::GetDiskFreeSpace( szDrive, &dwSectsPerClust, &dwBytesPerSect,
&dwFreeClusts, &dwTotalClusts ))
{
dwBytesPerClust = dwSectsPerClust * dwBytesPerSect;
dwTotal = dwBytesPerClust * dwTotalClusts;
dwFree = dwBytesPerClust * dwFreeClusts;
iChartType = iDriveType[nID - IDM_DISK_C];
nCurrent = nID;
}
}
}
int CDiskDoc::GetDriveCount()
{
int i, cDrives = 0;
char szDrive[] = "x:\\\0";
for (szDrive[0]='C'; szDrive[0] <= 'Z'; szDrive[0]++)
{
i = (int) (szDrive[0] - 'C');
iDriveType[i] = ::GetDriveType( szDrive );
if (iDriveType[i] == DRIVE_FIXED ||
iDriveType[i] == DRIVE_REMOTE ||
iDriveType[i] == DRIVE_RAMDISK)
{
cDrives++;
}
}
return cDrives;
}
DiskView.h
// ********************************************************************
//
// DiskView.h
//
// ********************************************************************
class CDiskView : public CView
{
DECLARE_DYNCREATE (CDiskView)
private:
static COLORREF rgbColor[2];
static CString strType[];
void GetLabel( CString* str, double e, PCSTR strTail );
protected:
virtual void OnDraw( CDC* pDC );
afx_msg void OnMemoryUpdate( CCmdUI* pCmdUI );
afx_msg void OnDiskUpdate( CCmdUI* pCmdUI );
DECLARE_MESSAGE_MAP ()
};
DiskView.cpp
// ********************************************************************
//
// DiskView.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include "resource.h"
#include "DiskView.h"
#include "DiskDoc.h"
#include "math.h"
#define PI 3.141592654
#define RADIUS 900
#define SLICE_OFFSET 12
#define MEM_COLOR RGB (0, 255, 255) // Cyan
#define DISK_COLOR RGB (0, 255, 0) // Green
COLORREF CDiskView::rgbColor[2] = { MEM_COLOR, DISK_COLOR };
CString CDiskView::strType[] = { " Memory",
-
Fixed disk",
-
Remote drive",
-
RAM disk" };
IMPLEMENT_DYNCREATE (CDiskView, CView)
BEGIN_MESSAGE_MAP (CDiskView, CView)
ON_UPDATE_COMMAND_UI (IDM_MEMORY, OnMemoryUpdate)
ON_UPDATE_COMMAND_UI_RANGE (IDM_DISK_C, IDM_DISK_Z, OnDiskUpdate)
END_MESSAGE_MAP()
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Paint the pie chart
void CDiskView::OnDraw( CDC* pDC )
{
Cpen pen;
CBrush brush;
CRect rect;
Cstring str;
int x, y, i, iColor;
double dUseSweep, dFreeSweep;
// Color is cyan for memory chart, green for drive charts
iColor = (CDiskDoc::nCurrent == IDM_MEMORY) ? 0 : 1;
// Set coordinate system so that origin is at center of client area
GetClientRect( rect );
pDC->SetMapMode( MM_ISOTROPIC );
pDC->SetWindowExt( RADIUS+100, RADIUS+100 );
pDC->SetViewportExt( rect.right/2, -rect.bottom/2 );
pDC->SetViewportOrg( rect.right/2, rect.bottom/2 );
// Create solid brush of current color to paint "Used" pie slice
pen.CreatePen( PS_SOLID, 1, rgbColor[iColor] );
brush.CreateSolidBrush( rgbColor[iColor] );
pDC->SelectObject( &pen );
pDC->SelectObject( &brush );
// Sweep angles in radians for "Free" and "Used" pie slices
dFreeSweep = (double) (PI*2 * CDiskDoc::dwFree/CDiskDoc::dwTotal);
dUseSweep = (double) PI*2 - dFreeSweep;
// Paint "Used" slice first, sweeping counter-clockwise from due north
x = -(int) (sin( dUseSweep ) * RADIUS);
y = (int) (cos( dUseSweep ) * RADIUS);
pDC->Pie( -RADIUS, RADIUS, RADIUS, -RADIUS, 0, RADIUS, x, y );
// Create hatched brush of current color to paint "Free" pie slice
pDC->SelectStockObject( WHITE_BRUSH );
pDC->SelectStockObject( BLACK_PEN );
brush.DeleteObject();
pen.DeleteObject();
pen.CreatePen( PS_SOLID, 1, rgbColor[iColor] );
brush.CreateHatchBrush( HS_CROSS, rgbColor[iColor] );
pDC->SelectObject( &pen );
pDC->SelectObject( &brush );
// Compute new center for "Free" slice, slightly offset from
// original center, then paint the "Free" slice
x = (int) (sin( PI - dUseSweep/2 ) * SLICE_OFFSET);
y = -(int) (cos( PI - dUseSweep/2 ) * SLICE_OFFSET);
pDC->OffsetWindowOrg( x, y );
pDC->OffsetViewportOrg( x, y );
x = (int) (sin( dFreeSweep ) * RADIUS);
y = (int) (cos( dFreeSweep ) * RADIUS);
if(abs (x) > 4)
pDC->Pie( -RADIUS, RADIUS, RADIUS, -RADIUS, x, y, 0, RADIUS );
pDC->SelectStockObject( BLACK_PEN );
pDC->SelectStockObject( WHITE_BRUSH );
pDC->SetBkMode( TRANSPARENT );
pen.DeleteObject();
brush.DeleteObject();
// Label "Free" slice
GetLabel( &str, CDiskDoc::dwFree, "Free" );
pDC->TextOut( 10, RADIUS/2, str );
// Label "Used" slice, making sure it doesn't occur near the "Free" label
x = -(int) (sin( dUseSweep/2 ) * RADIUS);
y = (int) (cos( dUseSweep/2 ) * RADIUS);
if ( y > 0 && (y - RADIUS/2) < 25)
{
x = -(RADIUS - 10);
y = 0;
}
GetLabel( &str, (CDiskDoc::dwTotal - CDiskDoc::dwFree), "Used" );
pDC->TextOut( x, y, str );
// Restore original mapping mode so we can use DrawText function
pDC->SetMapMode( MM_TEXT );
pDC->SetWindowExt( rect.right, rect.bottom );
pDC->SetViewportExt( rect.right, rect.bottom );
pDC->SetViewportOrg( 0, 0 );
pDC->SetWindowOrg( 0, 0 );
// Write "Total" at bottom right corner of window
GetLabel( &str, CDiskDoc::dwTotal, "Total " );
pDC->DrawText( str, rect, DT_SINGLELINE | DT_BOTTOM | DT_RIGHT );
// Write device type at bottom left corner of window
i = 0;
if (CDiskDoc::iChartType == DRIVE_FIXED)
i = 1;
if (CDiskDoc::iChartType == DRIVE_REMOTE)
i = 2;
if (CDiskDoc::iChartType == DRIVE_RAMDISK)
i = 3; pDC->DrawText( strType[i], rect, DT_SINGLELINE | DT_BOTTOM | DT_LEFT ); } void CDiskView::GetLabel( CString* str, double d, PCSTR strTail ) { charch = 'K'; // 'K ' for kilobytes d /= 1024; if (d > 1024) // If amount is greater than |
||||
---|---|---|---|---|
{ | // |
1024 kilobytes, divide |
||
d ch |
/= 1024; = 'M '; |
// // |
again by 1024 to convert to megabytes |
|
} |
str->Format( "%.2f %c%s%s", d, ch, "b ", strTail );
}
/ / / / / / / / / / / / / / / / / / / / / / / / / // / / / / / / // / / / / / / / // / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Make sure menu check marks and toolbar buttons are in sync
void CDiskView::OnMemoryUpdate( CCmdUI* pCmdUI )
{
pCmdUI->SetCheck( CDiskDoc::nCurrent == IDM_MEMORY );
}
void CDiskView::OnDiskUpdate( CCmdUI* pCmdUI )
{
pCmdUI->SetCheck( CDiskDoc::nCurrent == pCmdUI->m_nID );
}
MainFrm1.h
// ********************************************************************
//
// MainFrm1.h
//
// ********************************************************************
class CMainFrame : public CFrameWnd
{
DECLARE_DYNCREATE (CMainFrame)
private:
CToolBartoolbar;
CStatusBar statusbar;
CDiskDocdiskdoc;
protected:
afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
afx_msg voidOnMemory ();
afx_msg voidOnDisk( UINT nID );
afx_msg voidOnSetFocus( CWnd* );
DECLARE_MESSAGE_MAP()
};
MainFrm1.cpp
// ********************************************************************
//
// MainFrm1.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include <afxext.h>
#include <afxcmn.h>
#include "resource.h"
#include "DiskPie.h"
#include "DiskDoc.h"
#include "MainFrm1.h"
#include "DiskView.h"
IMPLEMENT_DYNCREATE (CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)
ON_WM_CREATE ()
ON_WM_SETFOCUS ()
ON_COMMAND (IDM_MEMORY, OnMemory)
ON_COMMAND_RANGE (IDM_DISK_C, IDM_DISK_Z, OnDisk)
END_MESSAGE_MAP ()
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Create main window, toolbar, and status bar
int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
int i, j;
char szMenu[] = "Disk &x\tx\0";
CMenu* pmenu;
static const UINT indicator = ID_SEPARATOR;
static const UINT nButtons[] = { IDM_MEMORY, ID_SEPARATOR,
IDM_DISK_C, IDM_DISK_D, IDM_DISK_E, IDM_DISK_F,
IDM_DISK_G, IDM_DISK_H, IDM_DISK_I, IDM_DISK_J,
IDM_DISK_K, IDM_DISK_L, IDM_DISK_M, IDM_DISK_N,
IDM_DISK_O, IDM_DISK_P, IDM_DISK_Q, IDM_DISK_R,
IDM_DISK_S, IDM_DISK_T, IDM_DISK_U, IDM_DISK_V,
IDM_DISK_W, IDM_DISK_X, IDM_DISK_Y, IDM_DISK_Z };
if (CFrameWnd::OnCreate( lpCreateStruct ) == -1)
return -1;
statusbar.Create( this );
statusbar.SetIndicators( &indicator, 1 );
toolbar.Create( this );
toolbar.SetWindowText( "Charts" );
toolbar.LoadToolBar( IDR_MAINFRAME );
toolbar.SetBarStyle( toolbar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC );
toolbar.SetButtons( nButtons, diskdoc.GetDriveCount() + 2 );
toolbar.SetButtonStyle( 0, TBBS_CHECKGROUP );
pmenu = GetMenu()->GetSubMenu( 1 );
for (i=0, j=2; i < 24; i++)
{
if(CDiskDoc::iDriveType[i] == DRIVE_FIXED ||
CDiskDoc::iDriveType[i] == DRIVE_REMOTE ||
CDiskDoc::iDriveType[i] == DRIVE_RAMDISK)
{
szMenu[6] = 'C' + (char) i;
szMenu[8] = 'C' + (char) i;
pmenu->InsertMenu( 0xFFFF, MF_BYPOSITION, IDM_DISK_C+i, szMenu );
toolbar.SetButtonInfo( j++, IDM_DISK_C+i, TBBS_CHECKGROUP, i+1 );
}
}
toolbar.EnableDocking( CBRS_ALIGN_ANY );
EnableDocking( CBRS_ALIGN_ANY );
DockControlBar( &toolbar );
return 0;
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Respond to menu/toolbar/accelerator commands
void CMainFrame::OnMemory ()
{
diskdoc.GetMemoryUsage ();
Invalidate ();
}
void CMainFrame::OnDisk( UINT nID )
{
diskdoc.GetDiskUsage( nID );
Invalidate ();
}
/ / / / / / / / / / / / / / / / / // / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// When focus regained, refresh display in case data has changed
void CMainFrame::OnSetFocus( CWnd* )
{
if(CDiskDoc::nCurrent == IDM_MEMORY)
diskdoc.GetMemoryUsage();
else
diskdoc.GetDiskUsage( CDiskDoc::nCurrent );
}
如 果 从 程 序 的 逻 辑 流 来 看 , 那 么 , 你 将 发 现 , 最 重 要 的 步 骤 在 MainFrm1.cpp 模块 里 。不 管 什 么 时 候 , 只 要 W indows 发 送 一 条 WM_SETFOCUS 消 息 , 通 知 获 得输 入 焦 点 的 主 窗 口 , 便 将 调 用 CMainFrame::OnSetFocus 函 数 。 当 D iskPie1 首 先启 动 时 , 或 无 论 何 时 , 只 要 用 户 从 其 他 程 序 切 换 到 D iskPie1 时 , 将 发 生 这 个 事件 。 这 样 , 这 个 函 数 提 供 两 种 用 途 的 服 务 。 它 使 CMainFrame::OnCreate 免 于 在程 序 开 始 启 动 时 调 用 DiskDoc::GetMemoryUsage 来 初 始 化 数 据 , 并 且 , 它 也 保 证当 用 户 运 行 其 他 程 序 , 或 删 除 一 个 文 件 时 , 当 DiskPie1 重 新 获 得 焦 点 时 , 自 动重 画 当 前 的 饼 图 , 来 反 映 新 的 状 况 。
通 过 给 CMainFrame::OnCreate 函 数 提 供 一 个 连 接 的 驱 动 器 列 表 , 函 数 添 加 Chart 菜 单 命 令 , 例 如 为 每 个 连 接 的 驱 动 器 添 加 D ISK C 和 DISK D 这 样 的 命 令 。 它 也为 每 一 个 驱 动 器 添 加 一 个 工 具 栏 按 钮 ,根 据 驱 动 器 指 定 的 字 母 选 择 工 具 栏 位 图 的合 适 部 分 。 例 如 , 驱 动 器 D 的 按 钮 是 用 位 图 的 16 × 15 这 部 分 画 的 , 其 中 包 含 这个 磁 盘 驱 动 器 图 像 和 字 母 D ( 含 有 25 个 位 图 块 的 完 整 工 具 栏 位 图 显 示 在 图 4-15 中 ) 。
用 户 可 以 请 求 内 存 状 况 饼 图 或 磁 盘 驱 动 器 的 饼 图 , 你 可 以 通 过 下 面 步 骤 完 成 :
-
从 Chart 菜 单 选 择 一 个 命 令 。
-
单 击 工 具 栏 按 钮 。
-
要 查 看 内 存 , 按 下 Ctrl+M , 或 要 查 看 磁 盘 驱 动 器 , 按
下 Ctrl 和 从 C 到
Z 对 应 于 驱 动 器 的 字 母 。
这 些 事 件 是 通 过 CMainFrame::OnMemory 和 CMainFrame::OnDisk 函 数 处 理 的 , 它 通 过 类 的 消 息 映 射 接 收 控 制 :
BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)
.
.
.
ON_COMMAND (idm_memory,OnMemory)
ON_COMMAND_RANGE (IDM_DISK_C, IDM_DISK_Z, OnDisk)
END_MESSAGE_MAP ()
你 可 能 回 想 起 , 在 本 章 前 面 创 建 D iskPie1 加 速 键 时 的 情 形 , 我 们 必 须 保 证 从IDM_DISK_C 到 IDM_DISK_Z 的 标 识 符 值 是 连 续 排 列 的 。 上 面 的 消 息 映 射 显 示了 为 什 么 要 这 样 。 因 为 标 识 符 有 连 续 的 值 , 程 序 可 以 使 用 MFC 的ON_COMMAND_RANGE 宏 来 为 任 何 磁 盘 驱 动 器 发 送 请 求 给 OnDisk 函 数 。根 据
作 为 参 数 传 递 的 磁 盘 驱 动 器 标 识 符 , OnDisk 决 定 用 户 要 求 用 饼 图 显 示 的 磁 盘 。
OnMemory 不 要 求 ON_COMMAND_RANG E , 因 为 只 有 一 个 内 存 饼 图 。
决 定 内 存 和 磁 盘 使 用 状 况 的 机 制 是 在 D iskDoc.cpp 模 块 里 使 用 两 个 函 数 。 这 两 个函 数 CDiskDoc::GetMemoryUsage 和 CDiskDoc::GetDiskUsage 使 用 了 相 似 的 逻 辑结 构 。 它 们 通 过 调 用 GlobalMemoryStatus 和 GetDiskFreeSpace API 函 数 , 从 系 统中 找 到 它 们 要 求 的 信 息 , 然 后 , 使 用 这 个 信 息 来 决 定 dwTotal 和 dwFree 内 存 变量 的 值 ,它 包 含 当 前 饼 图 的 总 字 节 数 和 未 使 用 的 字 节 数 。 变 量 中 的 数 据 不 管 是 表示 内 存 , 还 是 磁 盘 空 间 , 对 于 画 图 程 序 来 说 , 都 没 有 什 么 区 别 。 在 决 定 了 当 前 使用 状 况 数 据 之 后 ,OnMemory 和 OnDisk 函 数 调 用 Invalidate 来 强 制 显 示 一 个 新 的饼 图 。
现 在 , 应 该 介 绍 DiskView.cpp 文 件 里 CDiskView::OnDraw 函 数 了 。 这 个 函 数 使用 了 公 共 的 dwTotal 和 dwFree 值 , 来 决 定 饼 图 的 两 个 分 块 所 占 用 的 角 度 :
//Sweep angles in radians for “ Free ” and “ Used ” pie slices
dFreeSweep = (double) (PI*2 * CDiskDoc::dwFree/CDiskDoc::dwTotal); dUseSweep = (double) PI*2 - dFreeSweep;
OnDraw 先 画 出 “ Used ( 使 用 的 )” 的 那 一 部 分 , 通 过 dUseSweep 角 度 , 来 决 定
从 12 点 位 置 反 时 针 转 过 的 角 度 。“ Fre e( 空 闲 )” 块 是 剩 余 的 那 部 分 。OnDraw 为
每 一 块 关 联 一 个 标 签 , 并 显 示 这 个 饼 图 。 如 果 需 要 画 另 一 个 饼 图 , 就 必 须 重 新 开始 整 个 过 程 。
一 个 饼 图 快 速 提 供 了 目 前 的 使 用 状 况 。 当 D iskPie1 获 得 焦 点 时 , 刷 新 饼 图 的 唯一 方 便 的 方 法 是 按 下 对 应 于 这 个 饼 图 的 加 速 键 。 在 W indows 这 样 的 抢 占 式 多 任务 系 统 里 ,内 存 使 用 状 况 的 变 化 特 别 快 ,每 一 微 秒 都 在 发 生 变 化 。如 果 你 在 Visual C++ 中 , 在 后 台 编 译 一 个 项 目 时 , 连 续 按 下 Ctrl+M 键 , 那 么 , 你 可 以 看 到 快 速分 配 和 释 放 物 理 内 存 的 效 果 。 添 加 OnTimer 函 数 可 以 定 期 更 新 显 示 。
更 严 重 的 是 , DiskPie1 无 法 解 决 驱 动 器 连 接 的 动 态 变 化 问 题 。 我 们 已 经 看 到 , CMainFrame::OnCreate 函 数 怎 样 添 加 菜 单 命 令 ,以 及 如 何 为 连 接 到 系 统 上 的 磁 盘驱 动 器 添 加 工 具 栏 按 钮 , 包 括 任 何 通 过 网 络 提 供 的 远 程 驱 动 器 。 然 后 , 在 程 序 的生 存 期 内 , 菜 单 和 工 具 栏 保 持 不 变 ,即 使 用 户 后 来 可 能 添 加 或 卸 载 一 个 网 络 驱 动器 ,或 由 于 服 务 器 端 出 现 问 题 ,而 使 一 个 连 接 消 失 。然 而 ,这 并 不 会 致 命 ,D iskPie1 仍 然 正 常 工 作 ,因 为 CDiskDoc::GetDiskUsage 总 是 在 显 示 一 个 饼 图 之 前 列 举 驱 动器 。 增 强 程 序 将 添 加 重 新 检 查 刷 新 显 示 时 驱 动 器 的 连 接 状 态 的 逻 辑 ,从 而 根 据 情况 添 加 或 移 去 菜 单 命 令 和 工 具 栏 按 钮 。
再 谈 未 结 合 命 令
前 面 的 章 节 描 述 了 怎 样 通 过 指 定 键 盘 组 合 键 和 工 具 栏 按 钮 打 开 命 令 ,来 设 置 名 为
WordUpperCase 和 WordLowerCase 的 命 令 , 将 它 们 与 文 本 编 辑 命 令 结 合 。 Visual C++ 环 境 也 提 供 许 多 为 图 形 编 辑 器 设 计 的 有 用 的 未 结 合 命 令 , 你 可 以 完 全 使 用 第
3 章 “ 文 本 编 辑 器 ” 中 描 述 的 过 程 。 要 看 到 图 形 编 辑 器 的 未 结 合 和 结 合 命 令 的 列表 ,单 击 在 Hel p( 帮 助 )菜 单 上 的 Keyboard Ma p( 键 盘 映 射 ),并 从 Help Keyboard
( 帮 助 键 盘 ) 对 话 框 的 组 合 框 里 选 择 Image 。 图 4-21 显 示 了 一 个 相 似 的 列 表 。
图 4-21 图形编辑器的命令,通过从 Help 菜单中选择 Keyboard Map 来 显 示
列 表 里 的 许 多 Image 命 令 已 经 有 了 键 盘 指 定 。 例 如 , 图 4-21 显 示 了 按 下 A 键 打开 Airbus h( 喷 雾 器 ) 工 具 , 按 下 + 或 - 键 增 加 或 减 少 其 尺 寸 。 但 是 , 其 他 命 令 在为 它 们 指 定 按 键 或 创 建 组 合 键 后 , 才 可 以 使 用 。 为 了 证 明 这 点 , 本 节 显 示 了 怎 样为 列 表 里 的 第 一 个 名 为 Image3dRectangleTool 的 命 令 指 定 一 个 组 合 键 , 它 是 图 形编 辑 器 上 Rectangle ( 矩 形 ) 工 具 的 一 个 变 种 。
从 Tool 菜 单 上 选 择 Customize , 并 单 击 Keyboard 选 项 卡 。 从 Category 和 Editor
组 合 框 里 选 择 Image , 它 将 告 诉 Visual C++ , 只 在 图 形 编 辑 器 中 使 用 新 的 键 盘 命令 ( 也 叫 做 图 像 编 辑 器 )。 从 命 令 列 表 里 选 择 Image3dRectangleToo l, 单 击 New Shortcut Key ( 新 的 快 捷 键 ) 文 本 框 , 然 后 为 命 令 输 入 一 个 组 合 键 , 例 如Shift+Ctrl+3 。对 话 框 显 示 说 明 目 前 没 有 分 配 的 组 合 键 , 所 以 , 我 们 不 必 担 心 是 否从 其 他 命 令 取 走 Shift+Ctrl+3 。 单 击 Assign 按 钮 , 然 后 单 击 Close ( 关 闭 ) 按 钮来 除 去 对 话 框 。
Image3dRectangleTool 命 令 是 为 位 图 设 计 的 , 所 以 , 要 在 运 行 中 看 到 它 , 通 过 选择 File 菜 单 里 的 New 打 开 图 形 编 辑 器 , 并 双 击 Files 选 项 卡 里 的 Bitmap Fil e( 位图 文 件 )。按 下 Shift+Ctrl+3 组 合 键 时 ,或 者 按 下 指 定 给 这 个 命 令 的 任 何 其 他 组 合键 时 , 图 形 光 标 变 成 Rectangle ( 矩 形 ) 工 具 使 用 的 十 字 形 。 但 是 , 当 画 一 个 矩形 时 , 新 的 光 标 会 稍 微 不 同 的 效 果 。 当 你 从 左 上 角 拖 动 光 标 到 右 下 角 时 , 上 边 和左 边 用 目 前 的 前 景 色 , 而 右 边 和 底 部 用 背 景 色 显 示 。通 过 用 鼠 标 右 键 拖 动 来 修 改颜 色 。 使 用 正 确 的 颜 色 组 合 , 嵌 套 的 矩 形 显 示 一 个 三 维 外 观 , 可 以 快 速 生 成 下 面这 样 的 图 标 :
在 图 形 编 辑 器 里 工 作 时 , Image3dRectangleTool 只 是 许 多 有 用 的 键 盘 命 令 中 的 一个 。 例 如 , 当 设 计 自 画 的 按 钮 时 , 相 似 的 ImageWindowRectangle 命 令 快 速 画 出按 钮 处 于 正 常 状 态 、 按 下 或 非 活 动 状 态 下 的 位 图 图 像 。 在 列 表 中 浏 览 , 并 看 一 下你 喜 欢 的 命 令 。 如 果 想 为 命 令 创 建 工 具 栏 按 钮 , 可 查 看 第 3 章 的 “ 未 结 合 命 令 ” 一 节 。
修 整 资 源 数 据
由 于 有 不 使 用 的 或 效 率 低 下 的 资 源 数 据 ,W indows 程 序 经 常 是 过 度 负 载 ,那 些 程序 使 程 序 的 文 件 尺 寸 增 大 , 更 糟 糕 的 是 , 它 占 用 内 存 。 即 使 从 来 都 没 有 使 用 的 资源 , 也 可 以 进 入 内 存 , 但 只 是 闲 在 那 里 , 占 用 有 效 的 共 享 资 源 。 你 可 以 解 决 这 种问 题 , 所 需 要 付 出 的 努 力 也 不 大 。 这 一 节 研 究 一 些 减 小 程 序 资 源 数 据 大 小 的 技术 , 并 通 过 对 DiskPie1 程 序 做 一 些 修 改 , 来 证 明 我 们 常 常 可 以 修 整 一 个 程 序 里
资 源 数 据 的 有 效 数 量 。
要 记 住 的 第 一 件 事 是 ,你 不 必 保 留 AppWizard 提 供 给 你 的 每 一 件 东 西 。字 符 串 是罪 魁 祸 首 , 因 为 它 们 太 长 了 , 或 者 根 本 不 需 要 它 们 。 W in32 资 源 字 符 串 保 存 在 一个 程 序 文 件 里 , 作 为 Unicode 字 符 串 , 这 意 味 着 , 你 删 除 的 每 一 个 字 符 保 存 在 两个 字 节 里 , 而 不 是 一 个 字 节 。 如 果 你 从 通 过 AppWizard 生 成 的 RC 文 件 里 移 去 一个 菜 单 命 令 , 那 么 , 你 要 确 定 移 去 和 它 在 一 起 的 提 示 字 符 串 , 并 且 不 要 忘 记 对 应的 加 速 键 。
AppWizard 添 加 提 示 字 符 串 到 RC 文 件 里 , 它 描 述 了 一 个 程 序 的 系 统 菜 单 :
STRINGTABLE BEGIN
AFX_IDS_SCSIZE "Change the window size"
AFX_IDS_SCMOVE "Change the window position" AFX_IDS_SCMINIMIZE "Reduce the window to an icon" AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" AFX_IDS_SCCLOSE "Close the active window"
AFX_IDS_SCRESTORE "Restore the window to normal size"
.
.
.
END
MFC 库 文 件 包 含 这 些 相 同 的 字 符 串 ,所 以 ,如 果 你 的 程 序 使 用 MFC 动 态 链 接 库 , 那 么 , 你 可 以 安 全 地 从 RC 文 件 里 删 除 这 些 字 符 串 , 而 不 用 改 变 程 序 的 行 为( 然而 , 如 果 你 的 程 序 是 面 向 国 际 市 场 的 ,它 有 可 能 运 行 在 配 置 不 同 使 用 语 言 系 统 的机 器 上 , 其 他 因 素 可 能 影 响 你 是 否 使 用 MFC 库 文 件 提 供 的 字 符 串 的 决 定 。 看 一下 第 2 章 开 始 的 有 关 海 外 市 场 和 动 态 链 接 到 MFC 的 讨 论 )。通 过 释 放 一 些 资 源 字符 串 , 动 态 链 接 到 MFC , 而 不 是 静 态 链 接 , 将 明 显 减 少 可 执 行 文 件 的 尺 寸 , 因为 MFC 代 码 是 在 DLL 里 的 , 而 不 是 在 调 用 的 程 序 里 。 当 然 , 只 有 在 两 个 或 两 个以 上 的 程 序 同 时 使 用 MFC 库 运 行 时 , 用 户 才 会 获 益 。
我 在 前 面 的 章 节 里 提 到 , 如 果 一 个 应 用 程 序 只 提 供 一 个 边 长 为 32 个 像 素 的 正 方形 图 标 , W indows 将 自 动 将 图 形 按 需 要 成 比 例 转 换 成 16 × 16 或 48 × 48 的 正 方形 。 如 果 图 标 图 形 只 包 含 直 线 和 矩 形 , 比 例 变 换 一 般 不 会 改 变 图 形 。 对 于 不 受 比例 变 换 影 响 的 图 形 , 你 可 能 考 虑 只 包 含 一 个 32 × 32 的 图 形 , 而 不 是 两 个 或 三 个
不 同 尺 寸 的 图 形 。
你 可 以 通 过 使 它 们 的 颜 色 数 最 小 , 来 进 一 步 减 少 图 标 和 位 图 要 求 的 空 间 。 例 如 , 默 认 状 态 下 , 图 形 编 辑 器 的 New Icon Image ( 新 图 标 图 像 ) 对 话 框 ( 显 示 在 图 4- 17 上 ) 为 边 长 为 48 个 像 素 的 正 方 形 图 标 图 像 设 置 256 种 颜 色 。但 是 ,许 多 图 标 图形 , 像 D iskPie1 的 图 标 , 只 包 含 几 种 颜 色 。 为 一 个 图 形 指 定 16 种 颜 色 , 一 个 像素 只 使 用 4 位 ; 而 不 是 使 用 256 色 的 图 形 , 每 个 像 素 占 8 位 。 通 过 减 半 48 × 48 图 形 占 用 的 空 间 , 来 减 少 图 标 文 件 的 大 小 , 这 是 最 简 单 的 步 骤 。 在 保 存 时 , 同 时保 存 一 个 包 含 在 图 标 里 的 颜 色 表 , 将 增 加 2K 字 节 大 小 的 资 源 数 据 。 要 在 图 形 编辑 器 里 创 建 一 个 16 色 的 48 × 48 的 图 标 图 形 ,按 下 Insert 键 ,打开 New Icon Image 对 话 框 , 单 击 对 话 框 里 的 Custom 按 钮 , 并 填 写 适 当 的 控 件 框 。
D iskPie1 使 用 了 大 量 的 资 源 空 间 , 来 保 存 它 那 巨 大 的 工 具 栏 位 图 , 正 如 图 4-15 所 示 的 那 样 。 在 位 图 里 有 25 个 图 形 , 其 中 24 个 是 副 本 , 只 有 在 重 复 的 磁 盘 图 形上 显 示 的 字 母 是 不 同 的 。 在 这 种 情 况 下 , 可 以 把 它 存 成 一 个 图 形 , 并 提 供 任 何 数目 的 工 具 栏 按 钮 的 服 务 。再 增 加 一 点 附 加 的 代 码 ,它 可 以 提 供 工 具 栏 图 形 中 其 他23 个 图 形 的 作 用 。 这 就 大 量 节 省 了 程 序 的 尺 寸 。 下 面 说 明 怎 样 实 现 它 。
程 序 DiskPie2
D iskPie1.exe 的 发 行 版 本 文 件 大 小 是 24579 字 节 。 通 过 去 掉 其 资 源 数 据 中 的 许 多无 用 数 据 , 新 的 DiskPie2 程 序 大 小 减 小 到 17920 字 节 , 在 没 有 明 显 改 动 程 序 的
同 时 , 减 少 了 几 乎 三 分 之 一 的 大 小 。D iskPie2 用 四 种 技 术 来 减 少 它 的 资 源 数 据 的大 小 :
-
通 过 接 收 一 个 “ Ready( 就 绪 )” 消 息 , 这 个 程 序 没 有 在
它 的 资 源 数 据里 包 含 提 示 字 符 串 , 而 通 过 MFC 库 文 件 提 供 提 示 字 符 串 ,D iskPie2 在它 的 状 态 栏 里 为 所 有 的 命 令 显 示 一 般 性 的 提 示 信 息 , 但 那 些 在 Chart 菜 单 里 选 择 的 命 令 除 外 。
-
由 于 没 有 提 示 字 符 串 , D iskPie2 必 须 在 需 要 的 时 候 生
成 工 具 提 示 。 生成 工 具 提 示 的 代 码 比 工 具 提 示 字 符 串 本 身 占 用 更 小 的 空 间 , 导 致 程 序大 小 整 体 降 低 。
-
48 × 48 图 标 图 像 有 一 个 16 色 表 , 而 不 是 256 色 表 。
-
D iskPie2 工 具 提 示 位 图 只 有 两 个 图 像 , 而 不 是 像 D
iskPie1 那 样 要 求 的
25 个 图 像 。
这 两 个 工 具 栏 位 图 的 视 图 显 示 了 DiskPie2 的 工 具 栏 按 钮 所 使 用 的 图 像 :
这 些 图 像 复 制 了 D iskPie1 中 工 具 栏 的 前 两 个 图 形 , 只 是 第 二 个 图 形 没 有 标 记 , 并 使 它 适 于 表 示 任 何 磁 盘 驱 动 器 。 运 行 时 , D iskPie2 给 按 钮 的 磁 盘 驱 动 器 图 形 添加 像 “ C :”和 “ D :” 这 样 的 名 称 。 你 可 以 在 图 4-22 里 看 到 这 个 结 果 。
图 4-22 DiskPie2 程序
新 的 DiskPie2 程 序 要 求 改 变 DiskPie1 的 三 个 源 文 件 , 来 创 建 叫 做 D iskPie2.rc ,
M ainFrm2.h 和 M ainFrm.cpp 文 件 的 升 级 版 本 。 列 表 4-2 显 示 了 修 订 的 代 码 , 在D iskPie1.rc 里 去 掉 了 不 需 要 的 提 示 字 符 串 , 在 MainFrm2.cpp 里 接 收 为 标 记 工 具栏 按 钮 构 造 工 具 提 示 文 本 而 添 加 的 指 令 。
IDR_MAINFRAME ICON"res\\DiskPie2.ico"
IDR_MAINFRAME BITMAP "res\\toolbar.bmp"
IDR_MAINFRAME MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Chart"
BEGIN
MENUITEM "&Memory\tCtrl+M", IDM_MEMORY
MENUITEM SEPARATOR
END
POPUP "&View"
BEGIN
MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
END
POPUP "&Help"
BEGIN
MENUITEM "&About DiskPie2...", ID_APP_ABOUT
END
END
IDR_MAINFRAME ACCELERATORS
BEGI N
"M", IDM_MEMORY, VIRTKEY, CONTROL
"C", IDM_DISK_C, VIRTKEY
"D", IDM_DISK_D, VIRTKEY
"E", IDM_DISK_E, VIRTKEY
"F", IDM_DISK_F, VIRTKEY
"G", IDM_DISK_G, VIRTKEY
"H", IDM_DISK_H, VIRTKEY
"I", IDM_DISK_I, VIRTKEY
"J", IDM_DISK_J, VIRTKEY
"K", IDM_DISK_K, VIRTKEY
"L", IDM_DISK_L, VIRTKEY
"M", IDM_DISK_M, VIRTKEY
"N", IDM_DISK_N, VIRTKEY
"O", IDM_DISK_O, VIRTKEY
"P", IDM_DISK_P, VIRTKEY
"Q", IDM_DISK_Q, VIRTKEY
"R", IDM_DISK_R, VIRTKEY
"S", IDM_DISK_S, VIRTKEY
"T", IDM_DISK_T, VIRTKEY
"U", IDM_DISK_U, VIRTKEY
"V", IDM_DISK_V, VIRTKEY
"W", IDM_DISK_W, VIRTKEY
"X", IDM_DISK_X, VIRTKEY
END
IDR_MAINFRAME TOOLBAR 16, 15
BEGIN
BUTTON IDM_MEMORY
END
IDD_ABOUTBOX DIALOG 0, 0, 240, 65
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About DiskPie2"
FONT 8, "MS Sans Serif"
BEGIN
MainFrm2.h
// ********************************************************************
//
// MainFrm2.h
//
// ********************************************************************
class CMainFrame : public CFrameWnd
{
DECLARE_DYNCREATE (CMainFrame)
private:
CToolBartoolbar;
CStatusBar statusbar;
CDiskDocdiskdoc;
protected:
afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
afx_msg voidOnNewChart( UINT nID );
afx_msg voidOnSetFocus( CWnd* );
afx_msg BOOLOnTooltip( UINT id, NMHDR* pNMHDR, LRESULT* );
DECLARE_MESSAGE_MAP()
};
MainFrm2.cpp
// ********************************************************************
//
// MainFrm2.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include <afxext.h>
#include <afxcmn.h>
#include "resource.h"
#include "DiskPie.h"
#include "DiskDoc.h"
#include "MainFrm2.h"
#include "DiskView.h"
IMPLEMENT_DYNCREATE (CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)
ON_WM_CREATE ()
ON_WM_SETFOCUS ()
ON_COMMAND_RANGE (IDM_MEMORY, IDM_DISK_Z, OnNewChart)
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnTooltip )
END_MESSAGE_MAP ()
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Create main window, toolbar, and status bar
int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
int i, j;
char szDisk[] = "x:\0";
char szMenu[] = "Disk &x\tx\0";
CMenu* pmenu;
static const UINT indicator = ID_SEPARATOR;
if (CFrameWnd::OnCreate( lpCreateStruct ) == -1)
return -1;
statusbar.Create( this );
statusbar.SetIndicators( &indicator, 1 );
toolbar.Create( this );
toolbar.SetWindowText( "Charts" );
toolbar.LoadToolBar( IDR_MAINFRAME );
toolbar.SetBarStyle( toolbar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC );
toolbar.SetButtons( NULL, diskdoc.GetDriveCount() + 2 );
toolbar.SetButtonInfo( 0, IDM_MEMORY, TBBS_CHECKGROUP, 0 );
toolbar.SetButtonText( 0, "Memory" );
// The second "button" is a separator
toolbar.SetButtonInfo( 1, ID_SEPARATOR,
TBBS_SEPARATOR | TBBS_CHECKGROUP, 0 );
pmenu = GetMenu()->GetSubMenu( 1 );
for (i=0, j=2; i < 24; i++)
{
if(CDiskDoc::iDriveType[i] == DRIVE_FIXED ||
CDiskDoc::iDriveType[i] == DRIVE_REMOTE ||
CDiskDoc::iDriveType[i] == DRIVE_RAMDISK)
{
szDisk[0] = 'C' + (char) i;
szMenu[6] = 'C' + (char) i;
szMenu[8] = 'C' + (char) i;
pmenu->InsertMenu( 0xFFFF, MF_BYPOSITION, IDM_DISK_C+i, szMenu );
toolbar.SetButtonInfo( j, IDM_DISK_C+i, TBBS_CHECKGROUP, 1 );
toolbar.SetButtonText( j++, szDisk );
}
}
toolbar.SetSizes( CSize( 45, 40 ), CSize( 16, 15 ) );
toolbar.EnableDocking( CBRS_ALIGN_ANY );
EnableDocking( CBRS_ALIGN_ANY );
DockControlBar( &toolbar );
return 0;
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// Respond to menu/toolbar/accelerator commands
void CMainFrame::OnNewChart( UINT nID )
{
CDiskDoc::nCurrent = nID;
OnSetFocus( NULL );
Invalidate();
toolbar.Invalidate(); // Necessary when bar is floating
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// When focus regained, refresh display in case data has changed
void CMainFrame::OnSetFocus( CWnd* )
{
if (CDiskDoc::nCurrent == IDM_MEMORY)
diskdoc.GetMemoryUsage();
else
diskdoc.GetDiskUsage( CDiskDoc::nCurrent );
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// When TTN_NEEDTEXT notification received. Generate tooltip text
BOOL CMainFrame::OnTooltip( UINT id, NMHDR* pNMHDR, LRESULT* )
{
static char szMemTip[] = "Memory usage chart\0";
static char szDiskTip[] = "Usage chart for drive x\0";
TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*) pNMHDR;
UINT nID = pNMHDR->idFrom;
if (nID == IDM_MEMORY)
pTTT->lpszText = szMemTip;
else
{
szDiskTip[22] = (char) (nID - IDM_DISK_C) + 'C';
pTTT->lpszText = szDiskTip;
除 了 文 件 大 小 的 差 别 外 ,D iskPie1 和 D iskPie2 之 间 唯 一 明 显 的 差 别 在 于 它 们 工 具栏 的 外 观 。 由 于 D iskPie2 为 它 的 工 具 栏 按 钮 使 用 单 一 的 磁 盘 驱 动 器 图 像 , 所 以 , 程 序 必 须 在 运 行 时 用 文 字 标 记 它 们 。CMainFrame::OnCreate 函 数 在 For 循 环 里 处理 这 个 任 务 , 这 个 循 环 运 行 通 过 每 一 个 连 接 的 驱 动 器 。
for (i=0, j=2; i < 24; i++)
{
.
.
.
pmenu->InsertMenu( 0xFFFF, MF_BYPOSITION, IDM_DISK_C+i, szMenu );
toolbar.SetButtonInfo( j, IDM_DISK_C+i, TBBS_CHECKGROUP, 1 );
toolbar.SetButtonText( j++, szDisk );
}
toolbar.SetSizes(Csize(45,40),Csize(16,15));
对 CToolBar::SetButtonInfo 的 调 用 与 在 D iskPie1 里 的 指 令 相 同 , 不 同 的 是 最 后 的参 数 , 它 是 在 工 具 栏 位 图 里 按 钮 图 形 的 下 标 , 以 0 开 始 。 D iskPie1 使 用 循 环 计 数器 从 24 个 可 用 的 图 形 中 选 择 按 钮 的 图 形 。D iskPie2 只 处 理 一 个 磁 盘 驱 动 器 图 形 。但 是 , 为 了 不 使 每 一 个 图 标 看 起 来 都 相 似 , 代 码 也 调 用 CToolBar::SetButtonText 添 加 驱 动 器 名 称 。 添 加 的 文 本 要 求 每 一 个 按 钮 都 有 更 多 的 空 间 , 所 以 , 代 码 通 过调 用 CToolBar::SetSizes 来 增 大 按 钮 的 尺 寸 到 45 × 40 ,而 不 是 D iskPie1 的 24 × 22 像 素 。
按 要 求 出 现 的 工 具 提 示 和 提 示 字 符 串
由 于 在 D iskPie2 的 资 源 数 据 中 没 有 提 示 字 符 串 , 所 以 , 它 在 运 行 时 , 根 据 需 要来 配 置 其 工 具 提 示 。 当 系 统 要 显 示 一 个 工 具 提 示 窗 口 时 , 它 通 过 一 个TTN_NEEDTEXT 通 知 消 息 来 通 知 程 序 。D iskPie2 在 它 的 CMainFrame::OnTooltip 函 数 里 处 理 它 。 这 个 消 息 提 供 了 一 个 指 向 TOOLTIPTEXT 结 构 的 指 针 , 它 是N M H D R 结 构 的 扩 展 形 式 :
typedef struct
{
NMHDR hdr;
LPTSTR lpszText;
char szText[80]; HINSTANCE hinst; UINT uFlags;
}TOOLTIPTEXT, FAR *LPTOOLTIPTEXT;
hdr.idFrom 的 值 标 识 光 标 停 留 处 的 工 具 栏 按 钮 ,通 过 这 个 值 ,OnTooltip 决 定 合 适的 工 具 提 示 , lpszText 指 向 新 的 文 本 字 符 串 , 并 返 回 一 个 TRUE 值 。 函 数 在 它 的两 个 静 态 的 字 符 串 里 保 留 它 的 工 具 提 示 :
static char szMemTip[] = " Memory usage chart\0 " ; static char szDiskTip[] = " Usage chart for drive x\0 " ;
hdr.idFrom 里 的 IDM_MEMORY 的 值 表 明 , 第 一 个 工 具 栏 按 钮 需 要 工 具 提 示 文本 。 在 这 种 情 况 下 , 代 码 将 lpszText 的 结 构 成 员 指 向 字 符 串 szMemTip 。 如 果hdr.idFrom 标 识 从 IDM_DISK_C 到 IDM_DISK_Z 中 的 一 个 驱 动 器 状 况 按 钮 , OnTooltip 将 lpszText 指向 szDiskTip 字 符 串 , 并 将 其 中 的 字 符 x 所 处 的 位 置 用 C 到 Z 的 合 适 的 驱 动 器 字 母 代 替 。这 样 , 由 于 这 些 工 具 提 示 大 多 只 差 一 个 字 符 ,所以 , DiskPie2 的 工 具 提 示 很 容 易 创 建 。
通 过 相 似 的 技 术 , 就 可 以 写 D iskPie2 , 使 它 按 要 求 生 成 它 缺 少 的 状 态 栏 提 示 信息 。 状 态 栏 提 示 信 息 需 要 进 行 大 量 的 测 试 , 来 决 定 光 标 是 位 于 一 个 工 具 栏 按 钮上 , 还 是 在 菜 单 命 令 上 。 在 空 闲 时 间 中 , MFC 框 架 自 动 完 成 这 些 工 作 , 通 过 程序 的 CCmdUI 对 象 来 连 续 更 新 状 态 栏 。 随 时 产 生 滚 动 提 示 信 息 的 秘 密 只 是 提 供足 够 的 字 符 串 资 源 , 来 利 用 框 架 的 碰 撞 测 试 , 然 后 , 建 立 一 个 超 越CStatusBar::OnSet 函 数 的 完 整 的 提 示 字 符 串 。 例 如 , D iskPie2 将 在 程 序 的 RC 文件 里 使 用 驱 动 器 分 配 字 母 作 为 最 小 的 提 示 字 符 串 :
STRINGTABLE BEGIN
IDM_MEMORY " Memory usage" IDM_DISK_C " C "
IDM_DISK_D " D "
.
.
.
IDM_DISK_X " X "
IDM_DISK_Y " Y "
IDM_DISK_Z " Z "
END
要 钩 住 OnSetText 函 数 , 你 必 须 声 明 一 个 来 自 CStatusBar 的 类 , 并 使 用 它 在
CMainFrame 来 创 建 状 态 栏 :
class CStatusHook : public CStatusBar
{
protected;
afx_msg LRESULT OnSetText( WPARAM wParam, LPARAM lparam ); DECLARE_MESSAGE_MAP()
};
class CMainFrame : public CFrameWnd
{
DECLARE_DYNCREATE (CMainFrame)
private:
CStatusHook statusbar;
当 系 统 要 在 状 态 栏 里 显 示 一 个 简 单 的 提 示 字 符 串 时 , 一 个 消 息 映 射 和 OnSetText 处 理 函 数 捕 获 发 送 的 WM_SETTEXT 消 息 。 处 理 函 数 通 过 将 这 个 单 独 的 字 符 提示 插 入 一 个 冗 长 的 文 本 字 符 串 里 , 来 生 成 一 个 完 整 的 提 示 字 符 串 , 将 lParam 重新 指 向 构 造 的 字 符 串 , 并 传 递 控 制 到 低 级 的 OnSetText 函 数 。 现 在 , 状 态 栏 中 不是 只 显 示 单 独 的 字 母 ,像“ C ”,而 是 更 加 有 用 的 字 符 串 ,如“ D isk C usage chart ”。下 面 是 处 理 函 数 建 立 这 样 一 个 提 示 字 符 串 的 方 式 :
BEGIN_MESSAGE_MAP (CStatusHook,CStatusBar) ON_MESSAGE( WM_SETTEXT,OnSetText )
END_MESSAGE_MAP ()
LRESULT CStatusHook::OnSetText( WPARAM wParam, LPARAM lparam )
{
// Constructed string must be static
static char szDisk[] = " Disk x usage chart\0 " ;
//If display is onl 1 character, convert it to full string if (lstrlen( (LPCTSTR) lparm )==1)
{
szDisk[5] = *((LPCTSTR) lparam); //Set drive letter lparam =(LPARAM) szDisk; //Repoint lparam
}
return CStatusBar::OnSetText( wParam, lparam );
}
只 有 在 实 现 代 码 比 它 所 代 替 的 资 源 数 据 占 用 更 少 的 空 间 时 ,在 运 行 时 生 成 提 示 字符 串 才 物 有 所 值 。 不 管 怎 样 , 当 提 示 字 符 串 必 须 反 映 某 些 动 态 的 程 序 状 态 时 , 例如 用 户 输 入 的 不 能 预 料 的 只 读 字 符 串 资 源 , 这 个 技 术 有 时 是 很 有 用 的 。
第 5 章 对 话 框 和 控 件
我 们 经 常 同 时 介 绍 对 话 框 和 控 件 , 这 是 因 为 它 们 经 常 同 时 出 现 。控 件 是 具 有 特 殊用 途 的 子 窗 口 ( 例 如 , 按 钮 、 复 选 框 或 进 度 指 示 器 ), 而 对 话 框 是 在 其 客 户 区 内 包含 了 一 个 或 多 个 控 件 的 父 窗 口 。对 话 框 和 控 件 之 间 的 联 系 非 常 密 切 ,以 至 于 我 们干 脆 就 将 其 整 个 组 合 叫 做 “ 对 话 ”。
许 多 对 话 ( 例 如 About 对 话 框 ) 的 作 用 是 向 用 户 传 递 信 息 , 而 其 他 对 话 则 用 于 询 问输 入 信 息 , 为 键 入 文 件 名 或 单 击 按 钮 做 出 选 择 提 供 一 个 方 便 的 地 方 。如 果 此 时 你想 起 了 工 具 栏 , 那 么 你 就 对 了 , 工 具 栏 就 是 对 话 的 一 种 类 型 。 像 工 具 栏 一 样 , 大多 数 对 话 都 是 组 成 程 序 资 源 的 用 户 界 面 元 素 的 组 成 部 分 。
然 而 , 有 些 对 话 框 则 不 是 程 序 资 源 数 据 的 组 成 。 像 消 息 框 这 样 的 对 话 , 以 及 所 谓的 通 用 对 话 是 由 系 统 提 供 的 , 它 们 可 以 通 过 像 M essageBox 和 GetOpenFileName 这 样 的 API 函 数 或 像 CFileDialog 这 样 的 MFC 类 来 调 用 。 你 甚 至 可 以 在 运 行 时使 用 D ialogIndirect API 函 数 为 一 个 程 序 设 计 和 创 建 对 话 , 这 个 API 函 数 可 以 把结 构 作 为 输 入 , 而 不 是 来 自 该 程 序 的 资 源 区 域 的 数 据 。这 样 的 对 话 严 格 说 来 属 于编 程 问 题 , 而 不 是 你 在 Visual C++ 中 创 建 的 资 源 , 因 此 , 你 在 这 里 找 不 到 有 关 它们 的 任 何 讨 论 。
本 章 将 接 着 前 一 章 讨 论 资 源 数 据 的 另 一 方 面 。 首 先 , 我 们 将 看 一 看 在 项 目 的 RC 文 件 中 定 义 对 话 的 资 源 脚 本 , 然 后 进 入 Visual C++ 对 话 编 辑 器 , 在 那 里 , 可 以 像单 击 一 样 轻 松 地 进 行 对 话 设 计 。本 章 将 用 几 个 例 程 来 说 明 编 辑 器 的 功 能 , 其 中 有一 个 例 子 显 示 了 如 何 创 建 属 性 表 ( 也 多 选 项 卡 对 话 )。
对 话 脚 本
向 程 序 中 添 加 对 话 是 件 很 容 易 的 事 情 。每 个 对 话 都 在 资 源 数 据 区 中 做 为 一 系 列 命令 而 存 在 , 而 这 些 命 令 是 由 该 项 目 的 RC 文 件 中 的 脚 本 编 译 而 来 的 。 它 们 用 来 指定 诸 如 对 话 窗 口 大 小 、标 题 栏 中 的 标 题 以 及 控 件 的 放 置 之 类 的 详 细 资 料 。要 修 改对 话 , 通 常 仅 仅 需 要 在 RC 文 件 中 编 辑 脚 本 。
为 了 举 一 个 例 子 , 让 我 们 来 看 一 看 第 4 章 的 Resource , 在 那 里 , AppWzard 将 在Help 菜 单 上 生 成 一 个 命 令 , 并 为 Abou t( 关 于 ) 框 生 成 所 有 必 需 的 源 代 码 , 以 及具 有 当 前 在 Windows 程 序 中 越 来 越 普 遍 的 其 他 特 征 。 AppWizard 还 在 项 目 的 RC 文 件 中 编 写 用 来 定 义 对 话 及 控 件 外 观 的 脚 本 。
下 面 是 该 脚 本 的 另 一 种 表 示 :
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 217, 55
CAPTION "About Demo"
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif" BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
LTEXT "Demo Version 1.0",
IDC_STATIC,40,10,119,8,SS_NOPREFIX
LTEXT "Copyright (C) 1998", IDC_STATIC,40,25,119,8
DEFPUSHBUTTON "OK",IDOK,178,7,32,14,WS_GROUP
END
脚 本 的 第 一 行 用 符 号 IDD_ABOUTBOX 来 标 识 资 源 ,该 符 号 在 项 目 的 Resource.h 文 件 中 定 义 。 DISCARDABLE 关 键 字 后 面 跟 着 的 四 个 数 字 , 用 来 指 定 对 话 的 大小 。 前 两 个 数 字 (0 , 0) 用 来 设 定 对 话 窗 口 左 上 角 的 原 点 坐 标 。 脚 本 中 的 所 有 其 他坐 标 都 相 对 于 原 点 , 正 值 的 X 是 向 右 , 正 值 的 Y 是 向 下 。 后 两 个 数 用 来 确 定 对话 窗 口 的 尺 寸 , 在 本 例 中 , 窗 口 的 宽 度 是 217 个 单 元 , 高 度 是 55 个 单 元 。
对 话 单 元 不 是 像 素 , 而 且 , 在 X 和 Y 方 向 上 代 表 的 距 离 也 不 一 定 相 同 。 对 话 单元 的 尺 寸 取 决 于 用 于 对 话 文 字 的 字 体 , 而 对 话 字 体 在 默 认 状 态 下 为 系 统 字 体 ( 在上 面 的 脚 本 中 , 可 选 的 FONT 指 令 将 对 话 字 体 指 定 为 8 磅 MS Sans Serif) 。 水 平X 方 向 的 一 个 对 话 单 元 等 于 用 于 该 对 话 字 体 的 1/4 平 均 字 符 宽 。 在 垂 直 Y 方 向 , 一 个 对 话 单 元 是 1/8 字 符 高 。因 为 在 W indows 采 用 的 字 体 测 量 系 统 里 面 ,将 字 符高 度 作 为 字 体 的 大 小 , 因 此 , 对 于 一 个 使 用 了 8 磅 字 体 的 对 话 来 说 , 一 个 垂 直 对话 单 元 就 是 1 磅 , 或 1/12 英 寸 。
尽 管 与 可 视 化 控 件 相 比 , 完 成 控 件 的 布 局 要 复 杂 些 , 但 将 对 话 单 元 与 字 体 大 小 结合 起 来 ,就 意 昧 着 一 个 对 话 框 将 在 不 同 的 屏 幕 分 辨 率 下 保 持 同 一 尺 寸 。它 还 可 以确 保 当 对 话 的 字 体 改 变 时 , 控 件 之 间 的 相 对 位 置 保 持 不 变 ,虽 然 大 一 点 儿 或 小 一点 儿 的 字 体 仅 仅 是 导 致 对 话 窗 口 及 其 内 容 在 尺 寸 上 扩 大 或 缩 小 。在 运 行 时 , 在 对话 窗 口 之 中 放 置 控 件 的 程 序 应 该 首 先 通 过 调 用 GetDialogBaseUnits API 函 数 来 确定 该 对 话 的 “ 基 本 单 元 ”。 基 本 单 元 定 义 了 当 前 屏 幕 分 辨 率 下 的 对 话 单 元 与 像 素之 间 的 关 系 。 M apDialogRect 函 数 可 以 自 动 实 现 会 话 , 将 对 话 单 元 中 的 坐 标 翻 译成 相 等 数 量 的 屏 幕 像 素 。 M S D N 在 线 帮 助 十 分 详 细 地 介 绍 了 这 两 个 API 函 数 。
对 话 脚 本 中 的 STYLE 伪 指 令 指 定 了 影 响 对 话 外 观 的 各 种 标 志 , 例 如 , 为 对 话 提供 标 题 栏 的 WS_CAPTION 标 志 。DS_MODALFRAME 标 志 与 对 话 的 模 态 样 式 无关 , 它 仅 仅 取 决 于 程 序 创 建 对 话 的 方 式 。 模 态 样 式 的 意 思 是 , 在 对 话 可 见 期 间 , 只 有 属 于 其 他 程 序 的 窗 口 才 可 以 接 收 输 入 焦 点 , 因 此 , 用 户 在 运 行 负 责 该 对 话 的程 序 ( 或 至 少 是 线 程 )之 前 必 须 先 关 闭 它 。 例 如 , Abou t( 关 于 ) 框 就 是 模 态 对 话 ,
它 可 以 阻 塞 程 序 执 行 , 直 至 被 放 弃 。 非 模 态 对 话 则 不 太 明 显 , 它 允 许 用 户 不 必 关闭 对 话 , 就 可 以 在 程 序 内 切 换 到 另 一 个 窗 口 。Visual C++ 文 本 编 辑 器 的 Find 命 令是 非 模 态 对 话 的 好 例 子 。 将 要 在 本 章 稍 后 介 绍 的 名 为 Color 的 范 例 程 序 , 说 明 了如 何 使 用 Visual C++ 来 创 建 非 模 态 样 式 的 对 话 。
尽 管 名 字 叫 做 W S_SYSMENU ,但 这 个 标 志 只 不 过 是 在 对 话 标 题 栏 的 最 右 边 放 置了 一 个 Close 按 钮 而 已 , 因 为 子 窗 口 控 件 是 不 会 有 真 正 的 系 统 菜 单 的 。 可 选 的CAPTION 指 令 指 定 了 将 要 在 标 题 栏 中 出 现 的 文 字 。
对 话 的 控 件 定 义 语 句 被 括 在 BEGIN 和 END 语 句 之 间 。每 条 定 义 都 包 含 有 与 脚 本第 一 行 一 样 的 相 同 类 型 的 四 数 字 系 列 。在 那 里 ,前 两 个 数 字 给 出 了 控 件 左 上 角 相对 于 对 话 原 点 的 X 和 Y 坐 标 , 后 两 个 数 字 用 于 指 定 控 件 窗 口 的 宽 度 和 高 度 。 再重 复 一 遍 , 所 有 的 坐 标 和 尺 寸 都 是 以 对 话 单 元 表 示 的 。
这 个 对 话 脚 本 为 About ( 关 于 ) 框 提 供 了 一 个 标 签 为 O K 的 推 压 式 按 钮 , 以 及 三个 静 态 控 件 , 其 中 一 个 控 件 包 含 有 程 序 图 标 的 一 个 副 本 。 我 们 将 在 本 章 后 面 的 范例 代 码 中 遇 到 这 些 控 件 及 其 他 控 件 。如 果 想 获 得 包 括 有 普 遍 控 件 在 内 的 一 个 完 整控 件 列 表 , 请 访 问 MSDN 在 线 帮 助 , 或 查 阅 一 些 参 考 书 , 例 如 Charles Petzold 编 著 的 Programming Windows 95 ( Windows 95 编 程 ) 。
你 可 以 对 AppWizard 提 供 的 About 对 话 进 行 改 进 。如 果 没 有 别 的 改 进 的 话 ,就 在版 权 行 中 添 上 你 的 名 字 。 让 我 们 首 先 来 看 一 看 Visual C++ 对 话 编 辑 器 , 然 后 使 用这 个 编 辑 器 向 AppWizard 创 建 的 对 话 框 中 添 加 一 些 其 他 东 西 。
对 话 编 辑 器
在 以 前 进 行 W indows 编 程 的 时 候 , 开 发 者 们 设 计 对 话 框 的 过 程 大 概 是 这 样 的 , 它 们 不 得 不 在 RC 文 件 中 编 写 脚 本 , 然 后 , 再 编 译 和 运 行 程 序 , 才 能 看 到 对 话 框实 际 的 样 子 。 这 个 不 断 摸 索 反 复 试 验 的 过 程 , 通 常 需 要 反 复 多 次 , 才 能 正 确 地 放置 控 件 , 并 使 其 工 作 。 但 是 , 那 个 时 代 已 经 结 束 了 。 就 是 这 个 资 源 编 辑 器 而 不 是其 他 任 何 东 西 , 使 得 Visual C++ 变 得 “ 形 象 ” 了 , 一 旦 你 已 经 开 始 用 对 话 编 辑 器来 设 计 对 话 , 那 么 就 再 也 不 用 回 到 旧 方 法 了 。 你 不 仅 可 以 通 过 单 击 几 下 鼠 标 , 把专 业 质 量 的 对 话 放 在 一 起 , 当 你 创 建 它 的 时 候 , 看 着 它 在 屏 幕 上 形 成 表 单 , 而 且还 可 以 在 编 辑 器 中 对 对 话 的 工 作 模 态 进 行 测 试 。 控 件 看 上 去 不 对 吗 ? 想 改 变 助 记键 吗 ? 利 用 这 个 编 辑 器 , 修 改 工 作 会 很 轻 松 愉 快 。 当 你 完 成 之 后 , 也 就 知 道 了 对话 的 确 切 工 作 方 式 以 及 它 们 在 运 行 程 序 中 的 样 子 。正 如 我 们 将 要 在 下 一 章 中 看 到的 , 对 话 编 辑 器 与 ClassWizard 结 合 得 也 很 好 , 后 者 可 以 自 动 生 成 代 码 , 来 初 始化 和 检 索 来 自 对 话 控 件 的 数 据 。
至 于 其 他 资 源 , 你 可 能 会 发 现 , 通 过 使 用 文 本 编 辑 器 编 辑 RC 文 件 , 以 便 更 容 易地 对 现 有 的 对 话 脚 本 做 出 小 小 的 修 改 。 这 一 点 儿 都 没 有 错 。 但 对 大 多 数 修 改 来说 , 特 别 是 当 你 创 建 一 个 新 对 话 的 时 候 , 对 话 编 辑 器 应 该 是 你 最 好 的 选 择 。 与 其他 的 Visual C++ 资 源 编 辑 器 类 似 , 可 以 用 两 种 方 法 之 一 来 启 动 对 话 编 辑 器 , 究 竟使 用 哪 一 种 方 法 取 决 于 你 是 想 创 建 一 个 新 对 话 框 ,还 是 想 继 续 使 用 已 经 在 项 目 的RC 文 件 中 存 在 的 那 个 对 话 框 。如 果 想 从 头 开 始 创 建 一 个 新 对 话 框 ,请 单 击 Insert
( 插 入 ) 菜 单 上 的 Resource 来 打 开 Insert Resource ( 插 入 资 源 ) 框 , 然 后 从 列 表中 选 择 D ialog :
展 开 Insert Resource 框 中 的 D ialog 条 目 , 将 展 现 出 代 表 特 殊 对 话 形 状 的 标 识 符 , 例 如 具 有 工 具 栏 尺 寸 的 IDD_DIALOGBAR 。 如 果 想 创 建 一 个 带 有 默 认 的 O K 和
Cancel 按 钮 的 通 用 对 话 , 请 双 击 D ialog 而 不 展 开 它 。
如 果 想 继 续 在 现 有 的 对 话 上 工 作 , 请 打 开 项 目 。并 且 单 击 Workspac e( 工 作 空 间 ) 窗 口 ResourceView( 资 源 视 图 ) 窗 格 中 列 出 的 对 话 标 识 符 。如 果 你 想 在 非 当 前 项目 的 一 个 项 目 中 编 辑 对 话 , 请 单 击 File ( 文 件 ) 菜 单 , 并 打 开 另 一 个 项 目 的 RC 文 件 。该 操 作 将 打 开 其 他 项 目 的 资 源 列 表 ,你 可 以 从 中 选 取 需 要 的 对 话 框 。不 过 , 你 不 能 将 该 资 源 存 入 当 前 的 项 目 , 原 因 是 Visual C++ 不 能 将 来 自 RC 文 件 的 对 话脚 本 合 并 到 另 一 个 对 话 脚 本 之 中 。文 本 编 辑 器 为 将 另 一 个 项 目 的 对 话 复 制 到 当 前的 项 目 提 供 了 最 现 实 的 办 法 。可 以 按 照 第 4 章 中 介 绍 的 方 法 在 文 本 编 辑 器 中 打 开其 他 项 目 的 RC 文 件 ,选 择 和 复 制 所 需 要 的 脚 本 ,并 将 其 粘 贴 进 当 前 的 RC 文 件 。另 外 , 还 要 在 项 目 Resource.h 文 件 中 定 义 必 要 的 标 识 符 。 然 后 , 你 就 可 以 打 开 当前 项 目 中 的 资 源 , 并 对 其 进 行 正 常 的 编 辑 了 。
图 5-1 显 示 了 用 于 Demo 这 个 虚 构 的 AppWizard 项 目 的 Workspace( 工 作 空 间 ) 窗 口 , 在 里 面 , 单 击 ADD_ABOUTBOX 标 识 符 , 可 以 启 动 对 话 编 辑 器 , 并 加 载程 序 的 About ( 关 于 ) 框 对 话 。
图 5-1 在 Workspace 窗 口 中 , 双 击 一 个 对 话 标 识 符 , 将 启 动 对 话 编 辑 器
为 现 有 的 对 话 启 动 对 话 编 辑 器 的 时 候 , 该 编 辑 器 将 读 取 RC 文 件 的 脚 本 , 并 且 在编 辑 器 工 作 区 中 复 制 这 个 对 话 (如 果 Workspace 或 Output( 输 出 ) 窗 口 处 于 连 接模 式 之 中 , 它 可 能 会 覆 盖 掉 对 话 编 辑 器 窗 口 。 如 果 是 这 样 的 话 , 请 右 击 每 个 覆 盖
的 窗 口 , 并 从 上 下 文 菜 单 中 选 择 H ide( 隐 藏 ) 命 令 )。 图 5-2 显 示 了 已 加 载 到 编辑 器 中 准 备 修 改 的 Demo 的 About 对 话 框 。
尽 管 这 样 看 上 去 已 经 足 够 真 实 了 , 但 图 5-2 中的 Abou t( 关 于 ) 框 只 不 过 是 一 个没 有 运 行 的 演 示 图 片 而 已 。 单 击 对 话 工 作 区 中 的 按 钮 或 编 辑 框 , 可 以 选 中 控 件 , 但 不 激 活 它 。 图 5-2 中 所 显 示 的 规 则 指 导 是 可 选 的 , 但 是 , 你 可 能 通 过 从 Layout
( 布 局 )菜 单 中 选 择 Guide Settin g(s 指 南 设 置 )来 将 它 们 关 闭 。这 两 个 叫 做 Controls
和 Dialog 的 工 具 栏 需 要 详 细 解 释 一 下 。
图 5-2 对 话 编 辑 器
Contro l( 控 件 ) 工 具 栏
利 用 Control( 控 件 ) 工 具 栏 , 你 可 以 单 击 访 问 对 话 窗 口 中 放 置 的 控 件 。 单 击 代
表 你 想 要 的 工 具 栏 按 钮 , 并 且 , 将 控 件 从 工 具 栏 拖 入 到 对 话 框 中 的 位 置 。 在 你 拖动 的 时 候 , 一 个 点 划 线 的 矩 形 显 示 了 控 件 窗 口 的 轮 廓 , 这 样 , 在 你 释 放 鼠 标 按 钮放 置 控 件 之 前 , 就 可 以 对 控 件 的 尺 寸 和 位 置 一 目 了 然 。 另 一 种 方 法 是 , 只 需 在 从Controls ( 控 件 ) 工 具 栏 选 中 一 个 按 钮 , 然 后 , 在 对 话 窗 口 的 任 何 地 方 单 击 即 可 。控 件 窗 口 将 在 单 击 位 置 的 中 心 地 方 出 现 。 图 5-3 标 识 了 Controls ( 控 件 ) 工 具 栏上 可 以 提 供 的 控 件 类 型 。
一 旦 已 经 把 自 己 想 要 的 控 件 从 Controls ( 控 件 ) 工 具 栏 拖 进 了 对 话 区 , 那 么 , 下面 就 是 在 自 己 喜 欢 的 位 置 安 排 控 件 了 。D ialo g( 对 话 )工 具 栏 可 以 为 你 提 供 帮 助 , 但 是 , 首 先 我 们 必 须 来 讨 论 一 下 在 对 话 中 选 中 控 件 窗 口 。
图 5-3 Controls 工 具 栏
选 择 和 安 排 控 件
将 控 件 窗 口 拖 入 对 话 框 的 时 候 ,在 该 控 件 周 围 包 围 着 一 个 有 阴 影 的 矩 形 , 这 就 表示 该 控 件 已 被 选 中 了 。阴 影 的 选 择 矩 形 有 八 个 尺 寸 控 制 柄 ,它 们 是 放 置 在 矩 形 四角 和 四 边 的 小 正 方 形 。 像 在 W indows 中 的 典 型 操 作 一 样 , 你 可 以 通 过 用 鼠 标 指针 来 拖 动 一 个 尺 寸 控 制 柄 , 来 调 整 选 中 的 控 件 ,或 者 如 果 想 更 加 精 确 地 进 行 调 整的 话 , 还 可 以 通 过 按 箭 头 键 的 同 时 按 下 Shift 键 来 完 成 。 每 按 一 次 , 控 件 的 尺 寸改 变 一 个 单 位 。 你 还 可 以 通 过 在 工 作 内 的 任 何 地 方 而 不 是 在 控 件 窗 口 上 单 击 ,来选 中 和 调 整 对 话 框 本 身 。
当 你 将 控 件 窗 口 拖 入 对 话 的 时 候 , 没 有 必 要 对 其 进 行 仔 细 定 位 , 因 为 移 动 已 经 就位 的 控 件 是 很 容 易 的 。单 击 对 话 工 作 区 中 的 控 件 来 选 中 控 件 窗 口 , 然 后 使 用 鼠 标拖 动 或 使 用 箭 头 键 移 动 它 。 为 了 更 好 地 对 齐 , 可 单 击 D ialo g( 对 话 ) 工 具 栏 上 的Toggle Grid ( 开 关 网 格 ) 按 钮 打 开 网 格 。
当 可 以 在 对 话 窗 口 中 看 到 网 格 的 时 候 , 控 件 仅 从 一 个 网 格 行 移 向 另 一 个 网 格 行 , 这 个 特 征 就 是 大 家 熟 知 的 “ 与 网 格 对 齐 ”。 在 默 认 状 态 下 , 水 平 和 垂 直 网 格 间 距是 5 个 对 话 单 位 , 但 你 可 以 在 图 5-4 所 示 的 Grid Settings( 网 格 设 置 ) 对 话 框 中改 变 这 个 对 话 框 。
图 5.4 Guide Setting 框
如 果 与 网 格 对 齐 特 征 阻 碍 你 按 照 自 己 的 方 式 来 安 排 控 件 , 那 么 只 需 将 其 关 闭 即可 。 如 果 你 后 来 又 打 开 了 , 编 辑 器 不 影 响 对 话 框 中 已 经 存 在 的 控 件 窗 口 的 放 置 。如 果 想 临 时 抑 制 一 下 此 特 征 , 请 在 拖 动 控 件 的 时 候 按 Alt 键 。
每 次 将 几 个 控 件 作 为 一 组 而 不 是 单 独 一 个 进 行 移 动 或 调 整 往 往 更 加 方 便 。对 话 编辑 器 为 同 时 选 中 几 个 控 件 提 供 了 两 种 方 法 。 第 一 种 方 法 是 在 按 住 Shift 键 的 同 时依 次 单 击 你 想 选 中 的 控 件 。第 二 种 方 法 最 适 于 成 组 安 排 的 控 件 。单 击 Control s( 控件 )工 具 栏 上 的 Selectio n( 选 择 )工 具 ,并 将 虚 线 矩 形 拖 到 控 件 上 面 来 选 中 它 们 。图 5-5 说 明 了 这 个 过 程 。
如 果 你 想 取 消 对 所 选 组 中 某 个 控 件 的 选 中 , 请 在 按 住 Shift 键 的 同 时 单 击 该 控件 。 还 可 以 用 同 样 的 方 法 向 组 中 添 加 控 件 。 选 中 了 多 个 控 件 之 后 , 在 选 中 组 中 , 除 了 一 个 控 件 之 外 ,除 有 控 件 的 尺 寸 控 制 柄 全 都 显 示 为 空 的 ,以 表 明 它 们 处 于 非激 活 状 态 。 剩 下 的 那 个 具 有 实 尺 寸 控 制 柄 的 控 件 被 认 为 是 选 中 组 中 的 支 配 控 件 , 编 辑 器 可 以 从 中 确 定 作 为 整 体 的 选 中 组 的 调 整 或 对 齐 方 式 。 例 如 , 图 5-5 中 的Check1 控 件 就 是 选 中 的 组 中 的 三 个 控 件 的 支 配 控 件 , 因 为 它 是 唯 一 具 有 实 尺 寸控 制 柄 的 控 件 。 在 按 下 Ctrl 键 的 同 时 , 单 击 选 中 组 中 的 另 一 个 控 件 , 可 以 使 其 成为 新 的 支 配 控 件 。
图 5-5 同时选中几个控件
仅 有 实 尺 寸 控 制 柄 处 于 活 动 状 态 ; 如 果 尺 寸 控 制 柄 是 空 的 ,那 么 该 控 件 就 不 能 在
这 个 方 向 上 进 行 调 整 。组 合 框 控 件 仅 仅 在 两 边 上 具 有 活 动 的 尺 寸 控 制 柄 。这 是 因为 通 常 看 不 到 的 控 件 下 拉 区 域 边 是 控 件 窗 口 的 一 部 分 , 在 建 立 窗 口 尺 寸 的 时 候 , 必 须 将 其 考 虑 进 来 。 图 5-6 说 明 了 如 何 改 变 组 合 框 控 件 下 拉 区 域 的 尺 寸 。
你 可 以 创 建 控 件 的 一 个 副 本 ,并 通 过 在 按 下 Ctrl 键 的 时 候 拖 动 控 件 窗 口 ,来 将 其放 在 工 作 区 中 , 如 图 5-7 所 示 。 该 操 作 将 创 建 一 个 新 窗 口 , 除 了 具 有 自 己 的 标 识符 值 外 , 它 就 是 原 始 窗 口 的 “ 克 隆 ” 体 。
图 5-6 改变组合框的尺寸
图 5-7 在 对 话 编 辑 器 中 复 制 控 件 窗 口
Dialog ( 对 话 ) 工 具 栏
既 然 你 已 经 知 道 了 如 何 选 中 一 组 控 件 , 那 么 , 图 5-8 所 示 的 D ialog( 对 话 ) 工 具栏 就 更 有 意 义 了 。 在 对 话 中 四 处 拖 动 控 件 是 找 到 合 适 位 置 的 好 办 法 , 但 是 , 如 果要 精 确 对 齐 控 件 窗 口 , 你 应 该 使 用 D ialog ( 对 话 ) 工 具 栏 上 的 工 具 。 利 用 它 们 , 你 可 以 在 对 话 框 内 部 对 齐 了 的 行 和 列 中 放 置 控 件 窗 口 ,为 对 话 提 供 整 齐 的 和 专 业的 外 观 。这 个 工 具 栏 上 还 有 一 个 测 试 模 式 开 关 ,它 允 许 你 将 新 的 对 话 用 于 测 试 驱动 程 序 , 来 看 看 它 在 实 际 中 的 外 观 和 行 为 。
图 5-8 Dialog ( 对 话 ) 工 具 栏
所 有 的 D ialo g( 对 话 ) 工 具 栏 按 钮 在 Layou t( 布 局 ) 菜 单 上 都 具 有 功 能 相 同 的 命令 , 因 此 , 如 果 你 不 想 看 见 工 具 栏 的 话 , 还 可 以 把 它 关 闭 。 如 果 想 显 示 或 隐 藏 工具 栏 , 请 从 Tools ( 工 具 ) 菜 单 中 选 择 Customize( 自 定 义 ), 单 击 Toolbars ( 工具 栏 ) 选 项 卡 , 然 后 单 击 列 表 中 的 Dialog( 对 话 ) 复 选 框 。
正 如 你 在 图 5-8 中 所 看 到 的 , 工 具 栏 将 按 钮 安 排 在 五 个 逻 辑 组 中 , 它 们 分 别 用 于对 齐 、 居 中 、 间 隔 、 调 整 控 件 的 尺 寸 , 以 及 打 开 和 关 闭 网 格 和 标 尺 指 南 。 在 图
- 中 呈 现 为 灰 色 的 对 齐 、 间 隔 和 尺 寸 调 整 工 具 , 仅 仅 当
对 话 中 选 中 了 两 个 或 多个 控 件 时 才 被 启 用 。
下 面 几 节 将 阐 述 D ialo g( 对 话 ) 工 具 的 几 个 效 果 。 通 常 , 为 了 将 一 组 控 件 放 到 所需 要 的 位 置 ,需 要 采 用 几 个 工 具 。因 此 ,你 必 须 考 虑 一 下 应 用 工 具 的 顺 序 。不 过 , 即 使 做 错 了 也 没 关 系 。 如 果 一 个 工 具 的 效 果 不 合 适 , 只 需 单 击 Edit( 编 辑 ) 菜 单上 的 Undo ( 撤 消 ) 即 可 。
对 齐 工 具
对 齐 工 具 的 作 用 是 将 所 选 组 的 控 件 与 支 配 控 件 对 齐 。 例 如 , 单 击 Align Left( 左对 齐 ) 按 钮 , 将 改 变 选 中 控 件 的 X 坐 标 , 以 便 与 支 配 控 件 的 X 坐 标 和 匹 配 , 而不 影 响 Y 坐 标 。
居 中 工 具
居 中 工 具 可 以 作 用 于 单 个 选 中 控 件 或 一 组 控 件 ,将 选 中 部 分 放 在 对 话 客 户 区 的 水平 或 垂 直 中 心 。
间 隔 工 具
间 隔 工 具 仅 仅 在 包 含 有 三 个 或 更 多 控 件 的 选 中 组 上 才 能 工 作 。 在 D ialog ( 对 话 ) 工 具 中 , 它 们 是 独 一 无 二 的 , 因 为 它 不 能 区 分 哪 一 个 选 中 控 件 是 支 配 控 件 。 水 平间 隔 将 改 变 选 中 组 中 除 了 最 左 边 和 最 右 边 控 件 之 外 的 X 坐 标 , 使 水 平 方 向 的 控件 均 匀 排 列 。 垂 直 间 隔 工 具 完 成 Y 坐 标 方 向 上 相 同 的 工 作 , 使 控 件 在 垂 直 方 向上 均 匀 分 布 。 在 下 列 中 , 垂 直 间 隔 工 具 ( 编 辑 器 为 它 取 了 个 容 易 引 起 混 淆 的 名 字 , Space Dow n( 向 下 间 隔 ) ) 调 整 的 仅 仅 是 Appl y( 应 用 ) 按 钮 , O K 和 Cancel 按 钮
依 旧 在 原 来 的 位 置 不 变 。
尺 寸 调 整 工 具
尺 寸 调 整 工 具 作 用 于 包 含 有 两 个 或 更 多 控 件 的 选 中 组 。尺 寸 调 整 并 不 移 动 控 件 窗口 , 而 仅 仅 改 变 选 中 的 控 件 的 高 度 和 宽 度 , 以 便 与 选 中 部 分 中 支 配 控 件 的 尺 寸 相配 。
控 件 属 性
对 话 工 作 区 中 的 每 个 控 件 都 有 一 个 Properties ( 属 性 ) 对 话 框 , 你 可 以 在 里 面 为控 件 指 定 标 识 符 和 值 , 键 入 标 签 , 设 置 适 合 于 控 件 窗 口 的 样 式 标 志 。 如 果 想 展 现控 件 的 Properties( 属 性 ) 框 , 请 右 击 工 作 区 中 的 控 件 窗 口 , 并 从 弹 出 的 上 下 文菜 单 上 选 择 Propertie s。 你 还 可 以 选 中 一 个 控 件 , 并 单 击 View ( 查 看 ) 菜 单 上 的Properties 命 令 。 每 个 控 件 类 型 的 Properties ( 属 性 ) 对 话 在 外 观 和 内 容 上 略 有 不同 。 图 5-9 显 示 了 一 个 复 选 框 控 件 的 Properties ( 属 性 ) 框 。
图 5-9 一个复选框控件的 Properties(属性)对话
在 第 4 章 中 ,你 可 能 已 经 习 惯 于 在 Visual C++ 图 形 编 辑 器 中 双 击 一 个 项 目 来 打 开合 适 的 Properties( 属 性 ) 框 了 , 但 该 项 技 术 在 对 话 编 辑 器 中 则 不 具 有 相 同 的 效果 。 双 击 对 话 工 作 区 中 的 一 个 控 件 窗 口 可 以 导 致 三 个 结 果 之 一 , 这 主 要 取 决 于 环境 和 控 件 类 型 。
- 如 果 控 件 接 受 用 户 输 入 ,双 击 控 件 窗 口 ,将 调 用 一 个
题 为 Add Function
( 添 加 函 数 ) 的 对 话 , 它 允 许 你 为 这 个 控 件 快 速 添 加 存 根 处 理 程 序 函数 。
-
双 击 静 态 控 件 或 对 话 窗 口 , 将 在 文 本 编 辑 器 中 打 开 对
话 类 的 源 文 件 , 并 在 构 造 器 中 放 置 插 入 符 。
-
如 果 项 目 没 有 ClassWizard 数 据 库 CLW 文 件( 将 在 下 章 介 绍
),那 么 双击 非 静 态 控 件 的 一 个 控 件 将 没 有 任 何 效 果 。 这 种 行 为 不 同 于 版 本 5 , 在 版 本 5 中 , 没 有 CLW 文 件 时 , 双 击 将 显 示 该 控 件 的 Properties ( 属性 ) 框 。
如 果 控 件 接 受 用 户 输 入 , 例 如 复 选 框 或 滑 块 控 件 , 那 么 , 当 你 键 入 控 件 标 题 的 时候 ,将 分 配 一 个 独 一 无 二 的 助 记 键 。利 用 助 记 键 ,用 户 通 过 按 下 键 盘 上 的 一 个 键 , 可 以 将 输 入 焦 点 移 到 控 件 上 。前 一 章 介 绍 了 用 于 菜 单 命 令 的 助 记 键 ,用 于 标 签 的助 记 键 也 没 有 什 么 差 别 。 只 需 要 在 任 何 字 符 前 加 上 “ 与 ” 符 号 (& ), 将 字 符 作 为控 件 的 助 记 键 标 识 即 可 。 例 如 图 5-9 中 的 复 选 框 就 具 有 标 题 “ &Red ”, 在 里 面 , 助 记 键 是 字 母 “ R ”。
对 于 滑 块 控 件 或 像 编 辑 框 这 样 的 文 字 条 目 控 件 ,应 在 静 态 控 件 标 签 中 为 其 分 配 助记 键 , 下 面 是 一 个 简 单 的 例 子 :
在 这 种 情 况 下 , 按 A lt+D 将 把 焦 点 放 在 Date 编 辑 框 中 , 按 下 A lt+A , 将 把 焦 点放 在 Amount 编 辑 框 中 ( 当 两 个 编 辑 框 都 没 有 焦 点 时 , A lt 键 是 可 选 的 )。为 了 使 助记 键 工 作 , 每 个 编 辑 框 必 须 按 照 按 Tab 键 的 移 动 顺 序 排 列 它 的 静 态 控 件 标 签 。
按 Tab 键 的 移 动 顺 序
助 记 键 并 不 是 为 某 个 控 件 分 配 输 入 焦 点 的 唯 一 办 法 。 用 户 可 以 用 鼠 标 单 击 控 件 , 或 通 过 反 复 按 Tab 键 跳 到 某 一 控 件 。每当系统检测到 Tab 键 的 时 候 , 它 就 把 输 入焦 点 移 动 到 Tab 键 移 动 顺 序 的 下 一 个 控 件 。
按 Tab 键 的 移 动 顺 序 可 以 由 RC 文 件 对 话 脚 本 的 控 件 语 句 顺 序 中 推 出 。 例 如 , 当在 下 面 脚 本 中 定 义 的 对 话 出 现 的 时 候 , IDC_COMBO1 组 合 框 控 件 就 具 有 了 输 入焦 点 。 按 下 Tab 键 , 将 输 入 焦 点 从 IDC_COMBO1 控 件 按 显 示 的 顺 序 移 到 另 一 个控件。当 ID_CANCEL 按 钮 具 有 了 焦 点 之 后 , 再 次 按 下 Tab 键 , 将 把 焦 点 循 环 回IDC_COMBO1 的 开 始 处 。
IDD_DEMO_DLG DIALOG 0, 0, 247, 65
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION " Demo Dialog " FONT 8, " MS Sans Serif" BEGIN
COMBOBOX IDC_COMB01,15,15,159,80,WS_VSCROLL |
WS_TABSTOP | CBS_DROPDOWN|CBS_AUTOHSCROLL CONTROL " and " ,IDC_RADI01, " Button " ,BS_AUTORADIOBUTTON |
WS_TABSTOP,14,39,25,10
CONTROL " or" ,IDC_RADI02 ," Button " ,BS_AUTORADIOBUTTON | WS_TABSTOP,44,39,20,10
COMBOBOX IDC_COMBO2,69,39,106,80,WS_VSCROLL | WS_GROUP | WS_TABSTOP | CBS_DROPDOWN | CBS_AUTOSCROLL
DEFPUSHBUTTON " OK " ,IDOK,196,12,44,17,WS_GROUP
PUSHBUTTON " Cancel" ,ID_CANCEL,196,34,44,17,WS_GROUP
END
对 话 编 辑 器 可 以 将 你 与 RC 文 件 中 的 详 细 信 息 隔 离 开 来 , 但 是 , 你 仍 然 需 要 留 心询 问 用 户 输 入 对 话 中 Tab 键 的 移 动 顺 序 。检 查 顺 序 通 常 是 你 在 单 击 D ialo g( 对 话 )工 具 栏 上 的 测 试 开 关 之 前 所 做 的 最 后 一 件 事 情 。 从 Layou t( 布 局 ) 菜 单 选 择 Tab Orde r( Tab 次 序 ), 可 以 显 示 当 前 对 话 的 Tab 键 移 动 顺 序 , 该 顺 序 是 作 为 序 号 码
在 对 话 控 件 附 近 出 现 的 。 下 面 是 在 前 面 的 脚 本 中 定 义 的 用 于 对 话 的 工 作 区 :
如 果 想 修 改 Tab 键 的 移 动 顺 序 , 请 单 击 以 第 一 个 控 件 开 头 的 序 列 中 的 每 个 控 件 , 也 就 是 当 对 话 首 次 出 现 时 , 你 想 让 其 具 有 输 入 焦 点 的 那 个 控 件 。如 果 现 有 的 顺 序仅 仅 对 于 某 一 点 来 说 是 正 确 的 ,那 么 ,你 可 能 会 发 现 ,只 改 变 错 误 的 是 很 容 易 的 。在 单 击 具 有 最 高 的 正 确 Tab 键 的 移 动 顺 序 号 的 控 件 窗 口 的 同 时 按 下 Ctrl 键 ,然 后释 放 Ctrl 键 , 并 继 续 单 击 所 要 求 顺 序 中 的 控 件 , 直 到 顺 序 正 确 为 止 。 例 如 , 如 果想 改 变 控 件 4 到 6 的 顺 序 , 请 在 按 下 Ctrl 键 的 时 候 单 击 控 件 3 , 然 后 依 次 单 击 你想 让 其 拥 有 制 表 号 4 , 5 和 6 的 控 件 。 按 Enter 键 设 置 顺 序 并 返 回 到 编 辑 模 式 。
对 于 成 组 出 现 的 控 件 , 例 如 单 选 按 钮 和 复 选 框 , 改 正 Tab 键 的 移 动 顺 序 特 别 重要 。 第 6 章 将 主 要 介 绍 Tab 键 的 移 动 顺 序 , 以 及 它 在 使 一 组 单 选 按 钮 互 斥 ( 在 一组 按 钮 中 设 置 一 个 将 自 动 清 除 其 他 按 钮 ) 中 所 起 的 作 用 。
例 1 : 修 改 Abou t对 话
这 里 是 演 示 对 话 编 辑 器 的 一 些 功 能 的 简 单 例 子 。假 定 你 想 修 正 一 下 前 一 章 中 为 虚
构 的 Demo 项 目 所 引 入 的 Abo u (t 关 于 )框 。图 5-10 显 示 了 一 种 可 能 的 修 改 结 果 ,
它 也 是 用 于 虚 构 程 序 SpifDemo 的 Abou t( 关 于 ) 框 , 它 制 作 得 更 加 精 心 。
图 5-10 修 改 后 的 Abou t(关于)框
位 图 标 志 事 先 在 Visual C++ 图 形 编 辑 器 中 创 建 , 并 保 存 在 名 为 XYZCorp.bmp 的
文 件 之 中 。 除 此 之 外 , 在 对 话 编 辑 器 中 所 做 的 改 动 只 用 几 个 步 骤 即 可 完 成 , 所 花的 时 间 也 就 5 分 钟 。 如 果 你 想 试 着 自 己 修 改 About ( 关 于 ) 框 , 那 么 , 可 以 以 一个 名 为 Demo 的 免 费 分 布 的 AppWizard 项 目 作 为 开 始 。 然 后 按 如 下 步 骤 进 行 操作 。
- **创 建 标 志 :**单 击 Inse r(t 插 入 )菜 单 上 的 Resourc e( 资
源 ),并 选 中 Bitmap
( 位 图 ),来启动 Visual C++ 图 形 编 辑 器 。设计标志位图,从 View( 查
看 ) 菜 单 选 择 Properties , 来 为 新 的 位 图 资 源 提 供 标 识 符 , 并 指 定 文 件名 。 完 成 之 后 单 击 File ( 文 件 ) 菜 单 上 的 Save ( 保 存 )。
-
启 动 对 话 编 辑 器 并 加 载 Abou t( 关 于 ) 框 : 在
Workspace( 工 作 空 间 ) 窗 口 的 ResourceView 窗 格 中 , 双 击 IDD_ABOUTBOX 来 启 动 对 话 编辑 器 。
-
调 整 对 话 的 尺 寸 : 通 过 单 击 没 有 被 控 件 占 据 的 灰
色 对 话 框 里 面 的 任 何地 方 , 来 选 中 对 话 窗 口 , 并 拖 动 底 部 尺 寸 调 整 控 制 柄 来 扩 大 窗 口 。
-
改 变 标 题 : 在 对 话 窗 口 处 于 选 中 状 态 的 时 候 , 单
击 View( 查 看 ) 菜 单上 的 Properties 命 令 , 并 在 D ialog Properties ( 对 话 属 性 ) 框 中 重 新 编写 标 题 。
-
添 加 标 志 : 在 对 话 工 作 区 中 选 中 MFC 图 标 , 通 过 按
Del 键 将 其 删 除 , 然 后 用 在 步 骤 1 中 创 建 的 代 表 公 司 标 志 的 新 位 图 来 代 替 它 。 如 果 想 向
对 话 添 加 一 个 位 图 , 请 单 击 Controls ( 控 件 ) 工 具 栏 上 的 Picture ( 图片 ) 按 钮 , 并 将 控 件 拖 到 对 话 中 的 任 何 地 方 ( 位 置 不 需 要 十 分 精 确 )。在 图 形 控 件 处 于 选 中 状 态 的 时 候 , 使 用 Propertie s( 属 性 ) 命 令 可 以 调用 代 表 新 图 形 控 件 的 Picture Propertie s( 图 片 属 性 ) 框 ( 如 果 想 选 中 像图 片 这 样 的 空 控 件 , 请 单 击 该 控 件 周 围 的 框 架 , 原 因 是 编 辑 器 不 能 将框 架 里 面 的 单 击 识 别 为 以 控 件 作 为 目 标 )。从 Typ e( 类 型 ) 框 的 列 表 中选 择 Bitmap ( 位 图 ), 并 在 Imag e( 图 像 ) 框 中 键 入 位 图 标 识 符 。 一 定要 键 入 与 在 步 骤 1 给 定 的 相 同 的 标 识 符 。 你 可 以 按 照 同 样 的 方 式 向 对话 中 添 加 图 标 , 只 是 应 选 择 Type ( 类 型 ) 框 中 的 Icon ( 图 标 ), 而 不是 Bitmap( 位 图 )。
- 编 辑 对 话 文 字 : 对 话 中 每 两 行 文 字 就 是 一 个 静 态
控 件 。 为 每 个 静 态 控件 调 用 Text Propertie s(属性)框,并修改 Captio n( 标 题 ) 框 中 的 文 字 。在 上 例 中 , 将 “ Dem o ” 改 为 “ SpitfyDem o”, 版 权 行 扩 展 为 包 括 XYZ Corporation 。 在 原 来 文 字 中 用 \251 代替 “ (C )” 版 权 符 号 , \251 是 AXSI
字 符 的 八 进 制 代 码 ( 如 果 想 获 得 你 想 用 相 同 方 式 添 加 到 文 字 控 件 的 其 他
ANSI 字 符 列 表 , 请 参 考 附 录 A )。
- **添 加 电 话 号 码 :**该 步 骤 需 要 用 Contro l (s 控 件 )工 具
栏 提 供 的 Group Box
( 组 框 ) 工 具 和 Static Tex t( 静 态 文 本 ) 工 具 。 首 先 , 单 击 Group Box
( 组 框 ) 按 钮 , 并 将 它 的 图 像 移 动 到 对 话 框 的 下 半 空 白 区 域 。 在 需 要的 时 候 将 其 扩 大 ,然 后 再 次 单 击 Propertie s( 属 性 )命 令 打 开 Group Box Properties ( 组 框 属 性 ) 对 话 , 并 将 标 题 改 为 “ Phone Numbers ”, 下 一步 , 单 击 Static tex t( 静 态 文 本 ) 按 钮 , 并 将 其 拖 到 对 话 中 的 组 合 框 里面 。 在 静 态 控 件 窗 口 仍 处 于 选 中 状 态 的 时 候 , 通 过 在 按 住 Ctrl 键 的 同时 短 距 离 地 拖 动 控 件 , 可 以 创 建 它 的 多 个 副 本 。 将 这 些 副 本 拖 到 独 立的 行 上 , 一 个 接 一 个 地 放 置 。 在 这 个 阶 段 , 对 齐 并 不 是 很 重 要 的 , 因为 以 后 可 以 更 加 仔 细 地 进 行 。
在 默 认 状 态 下 , 静 态 控 件 包 含 有 单 个 单 词 “ Static ”。 为 这 三 个 静 态 控件 中 的 每 一 个 打 开 Text Properties( 属 性 ) 对 话 , 并 在 Caption( 标 题 ) 框 中 用 新 文 字 和 电 话 号 码 代 替“ Static ”。 单 击 位 于 Properties 对 话 左 上角 的 按 钉 按 钮 , 可 以 阻 止 它 在 两 个 选 择 之 间 消 失 。
\t 制 表 符 在 三 个 静 态 控 件 中 为 电 话 号 码 留 空 , 并 将 它 们 对 齐 , 例 如“ Sales:\t\t\t(206)555-1212 ”。 不 过 , 在 Caption 栏 中 键 入 \t 字 符 将 只 为
静 态 控 件 扩 展 一 个 单 空 格 , 因 此 , \t 字 符 后 面 的 文 字 可 能 不 会 在 控 件窗 口 中 出 现 。 如 果 看 到 它 , 你 可 以 通 过 拖 动 控 件 的 右 尺 寸 调 整 控 制 柄来 手 工 加 长 每 个 静 态 控 件 。
- 对 齐 控 件 : 打 开 网 格 , 并 使 用 鼠 标 拖 动 控 件 就 位
。 三 个 带 有 电 话 号 码的 文 字 控 件 应 当 被 对 齐 , 而 且 被 均 匀 排 列 。 在 你 所 希 望 的 地 方 设 置 第一 行 , 然 后 选 中 全 部 三 行 , 并 且 单 击 D ialo g( 对 话 ) 工 具 栏 上 的 Align
Left( 左 对 齐 ) 和 Space Down ( 向 下 间 隔 ) 按 钮 。
如 果 想 使 对 话 的 外 观 均 衡 , 在 上 面 的 例 子 中 , 还 可 以 扩 大 O K 按 钮 。只 需 单 击 该 按 钮 便 可 选 中 它 , 然 后 根 据 需 要 拖 动 尺 寸 调 整 控 制 柄 即可 。
- 测 试 : 单 击 D ialog ( 对 话 ) 工 具 栏 上 的 测 试 驱 动 开
关 , 可 以 看 看 完 成以 后 的 作 品 是 什 么 样 子 。 如 果 想 返 回 编 辑 模 式 , 请 单 击 对 话 的 OK 按钮 , 或 按 ESC 。
保 存 自 己 的 工 作 之 后 , 对 话 编 辑 器 将 用 修 改 后 的 Abou t( 关 于 ) 框 所 对 应 的 新 脚本 覆 盖 文 件 中 原 来 的 脚 本 。
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 217,129
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION " About XYZ SpiffyDemo" FONT 8, " MS Sans Serif "
BEGIN
CONTROL IDB_XYZCORP,IDC_STATIC ," Static " , SS_BITMAP,17,16,85,10
LTEXT " SpiffyDemo Version 1.0 " , IDC_STATIC,21,33,119,8,SS_NOPREFIX
续 表
LTEXT " Copyright \251 1998,XYZ Corporation" ,
IDC_STATIC,21,45,119,8
DEFPUSHBUTTON " OK " ,IDOK,166,15,32,40,WS_GROUP
GROUPBOX " Phone Numbers" ,IDC_STATIC,17,65,181,56
LTEXT " Technical Support:\t(206) 555-1212 " , IDC_STATIC,33,82,140,8
LTEXT " Customer Service:\t(206) 555-1212 " , IDC_STATIC,33,94,142,8
LTEXT " Sales:\t\t\t(206) 555-1212 " , IDC_STATIC,33,106,141,8
END
该 脚 本 的 第 一 个 CONTROL 语 句 引 用 IDB_XYZCORP 位 图 , 该 位 图 包 含 步 骤 1 中 用 图 形 编 辑 器 创 建 的 公 司 标 志 。 资 源 编 辑 器 知 道 到 哪 里 去 找 IOB_XYZCORP 位 图 , 因 为 图 形 编 辑 器 已 在 RC 文 件 中 其 他 地 方 记 录 了 文 件 名 。
IDB_XYZCORP BIPMAP MOVEABLE PORE " yes\\xyzcorp.bmp"
例 2 : 简 单 的 非 模 态 对 话 框
About 是 模 态 对 话 框 , 直 到 单 击 OK 关 闭 对 话 之 后 , 它 才 允 许 用 户 继 续 在 程 序 中工 作 。 相 反 , 非 模 态 对 话 框 就 允 许 用 户 在 同 一 程 序 中 切 换 到 另 一 个 窗 口 , 并 且 继续 工 作 。 而 对 话 仍 在 屏 幕 上 保 留 , 直 到 被 退 出 。
对 话 是 模 态 的 , 还 是 非 模 态 的 , 仅 仅 取 决 于 程 序 在 运 行 时 间 创 建 该 对 话 的 方 式 。你 可 以 用 相 同 的 方 法 设 计 模 态 和 非 模 态 对 话 框 。只有一点例外 : 非 模 态 对 话 框 必须 具 有 样 式 标 志 WS_VISIBLE 。 该 标 志 可 以 这 样 设 定 , 在 对 话 工 作 区 中 右 击 , 并从 上 下 文 菜 单 中 选 择 Properties 来 调 用 D ialog Properties ( 对 话 属 性 ) 框 。 然 后 , 打 开 More Style ( 其 他 风 格 ) 选 项 卡 中 的 Visible ( 可 见 性 ) 复 选 框 :
该 操 作 将 把 WS_VISIBLE 标 志 添 加 到 RC 文 件 中 该 对 话 脚 本 的 STYLE 语 句 。
C 程 序 通 过 调 用 CreatDialog API 函 数 或 者 它 的 一 个 变 种 ( 例 如 ,CreatDialogIndirect
来 创 建 一 个 非 模 态 对 话 :
hDig=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DIALOG1),
hwnd,DlgProc) ;
在 本 例 中 , hInst 是 程 序 的 实 例 句 柄 , IDD_DIALOG1 是 RC 文 件 中 代 表 该 对 话 脚本 的 标 识 符 ,hwnd 是 对 话 拥 有 者 的 句 柄 ,D igProc 是 指 向 运 行 该 脚 本 及 接 收 它 的
消 息 的 过 程 的 指 针 。
使 用 MFC 的 C++ 程 序 用 CDialog::Create 函 数 来 创 建 非 模 态 对 话 。 下 面 几 行 假 定
CMyDlg 类 是 由 MFC 的 CDialog 派 生 出 来 的 :
CMyDly*pDlg=new Cmydlg;
Ddlg Create(IDD_DIALOG,this);
CDialog::Create 和 CDiglog::Domodel 之 间 有 一 个 重 要 的 差 异 。因 为 后 一 个 函 数 创建 的 是 模 态 对 话 。 直 到 对 话 关 闭 , 它 才 会 返 回 。 而 Create 可 以 立 即 返 回 , 在 非 模态 对 话 保 留 在 屏 幕 上 的 时 候 , 允 许 程 序 继 续 运 行 。 对 话 在 程 序 关 闭 它 之 前 , 将 一直 存 在 :
delete pDlg;
在 本 节 展 示 的 Color 程 序 中 , 显 示 了 带 有 三 个 滑 块 控 件 ( 也 叫 轨 迹 条 )的 非 模 态 对话 , 这 三 个 滑 块 可 以 调 整 主 窗 口 背 景 颜 色 的 红 、 绿 、 蓝 组 成 。 当 你 用 鼠 标 或 箭 头键 移 动 滑 块 的 时 候 , 主 窗 口 的 颜 色 将 根 据 新 的 颜 色 组 成 而 变 化 , 颜 色 值 可 能 在 0 到 255 之 间 变 化 。 如 果 视 频 硬 件 足 够 的 话 , 从 理 论 上 讲 , 你 可 以 通 过 移 动 滑 动 栏来 显 示 16777216(256 3 ) 种 不 同 颜 色 中 的 任 一 种 。图 5-11 显 示 了 带 有 非 模 态 的 Color 对 话 的 程 序 窗 口 。
Color 是 一 个 MFC 程 序 , 但 不 是 用 AppWizard 创 建 的 ( 下 节 将 显 示 如 何 在AppWizard 应 用 程 序 中 创 建 新 对 话 )。 Color 项 目 开 始 是 选 中 New 对 话 Properties 选 项 卡 中 的 Win32 Application 图 标 。 键 入 Color 作 为 项 目 名 , 单 击 O K 。 通 过 单击 Insert( 插 入 ) 菜 单 上 的 Resource, 并 双 击 资 源 类 型 列 表 中 的 D ialog 来 启 动 对话 编 辑 器 。 新 的 对 话 是 以 出 现 默 认 的 OK 和 Cancel 按 钮 作 为 开 始 的 ; 在 工 作 区中 选 中 这 些 按 钮 , 并 按 Delete 来 删 除 它 们 。
图 5-11 Color 程序
Color 对 话 仅 仅 包 含 三 个 不 同 的 类 型 , 它 们 是 由 来 自 编 辑 器 的 Controls ( 控 件 ) 工 具 栏 的 Static Tex t( 静 态 文 本 ) ,Button ( 按 钮 ) 和 Slide r( 滑 块 ) 工 具 创 建 的 。
滑 块 栏 在 对 话 中 形 成 了 三 条 分 界 线 , 在 图 5-11 中 分 别 标 为 Red, Green 和 Blue 。为 了 创 建 Red (上 ) 线 , 首 先 需 要 在 两 个 静 态 文 本 控 件 之 间 放 置 一 个 滑 块 控 件 , 然后 所 有 的 控 件 都 要 对 齐 , 并 留 出 间 隔 。 将 文 本 控 件 的 标 题 初 始 化 为 Red , 并 在Text Properties 对 话 中 键 入 X 。X 的 作 用 是 充 当 Color 在 运 行 期 间 用 滑 块 位 置 的 新值 进 行 覆 盖 的 占 位 符 。为 滑 块 控 件 分 配 一 个 静 态 边 缘 的 边 框 和 一 个 具 有 指 针 的 按钮 。 这 些 样 式 可 以 在 Slider Propertie s( 滑 块 属 性 ) 对 话 中 进 行 设 置 , 可 以 通 过 右击 对 话 中 的 滑 块 控 件 窗 口 , 并 选 择 Properties 来 设 置 :
- 在 Style ( 样 式 ) 选 项 卡 中 , 在 拇 指 样 式 的 Point( 指 向
) 框 中 选 中
Bottom/Righ t( 底 部 /右 边 )。
- 在 Extender Style( 扩 展 样 式 ) 选 项 卡 中 , 单 击 Static Edg
e( 静 态 边 缘 ) 复 选 框 。
Green 和 Blue 线 的 创 建 方 法 与 Red 线 完 全 相 同 , 通 过 将 Red 的 三 个 控 件 做 为 一组 选 中 来 复 制 , 然 后 按 照 前 一 章 中 介 绍 的 方 法 , 在 按 下 Ctrl 的 同 时 拖 动 该 组 控件 。 这 时 候 , 对 话 编 辑 器 工 作 区 看 上 去 与 下 图 类 似 , 完 成 该 对 话 仅 仅 需 要 将 第 二个 和 第 三 个 标 题 分 别 改 为 Green 和 Blue,将 控 件 对 齐 ,并 在 对 话 窗 口 的 底 部 添 加O K 按 钮 。 为 该 按 钮 分 配 一 个 标 识 符 IDOK , 并 设 置 该 按 钮 的 Propertie s( 属 性 ) 对 话 Styles 选 项 卡 中 的 Default Button ( 默 认 按 钮 ) 复 选 框 。
在 复 制 选 定 了 的 控 件 的 时 候 ,对 话 编 辑 器 将 自 动 为 新 的 控 件 分 配 不 同 的 标 识 符 符号 , 以 确 保 该 对 话 中 的 每 个 控 件 都 被 独 一 无 二 地 标 识 。新 的 符 号 与 原 来 的 符 号 具
有 相 同 的 名 字 , 只 是 后 面 添 加 了 数 字 。 例 如 , 第 一 行 的 Red 滑 块 控 件 将 分 配 一 个名 为 IDC_SLIDE_RED 的 标 识 符 。 当 你 通 过 复 制 Red 线 来 创 建 Green 和 Blue 线的 时 候 , 编 辑 器 将 为 新 控 件 分 配 名 为 IDC_SLIDE_RED1 和 IDC_SLIDE_RED2 的 标 识 符 ( 在 Color 程 序 中 , 以 后 将 在 Properties( 属 性 ) 框 中 把 每 个 控 件 的 标 识符 改 为 IDC_SLIDE_GREEN 的 IDC_SLIDE_BLUE )。在 保 存 这 个 对 话 的 时 候 ,编辑 器 将 在 Resource.h 文 件 中 为 新 的 标 识 符 写 下 #define 语 句 。 结 果 总 结 如 下 :
Color 对 话 中 的 控 件 标 识 符
上 行 |
中 行 |
下 行 |
||
---|---|---|---|---|
Color 控 件 |
静 态 |
IDC_STATIC |
IDC_STATIC |
IDC_STATIC |
滑 块 控 |
件 |
IDC_SLIDE_RE D |
IDC_SLIDE_GREEN |
IDC_SLIDE_BL UE |
X 静 态 |
控 件 |
IDC_STATIC_R ED |
IDC_STATIC_GREE N |
IDC_STATIC_BL UE |
Color 静 态 控 件 ( 最 左 面 的 控 件 ) 的 标 题 应 该 是 Red , Green 和 Blue。 最 右 边 的 控 件的 标 题 是 所 有 三 条 线 的 X 。
Color 的 源 代 码 仅 需 要 一 个 主 文 件 , 两 个 名 为 Resource.h 和 Color.h 的 头 文 件 ,以及 一 个 定 义 了 对 话 的 名 为 Color.re 的 资 源 脚 本 文 件 。 源 程 序 列 表 如 下 ( 见 列 表 5- 1):
列 表 5-1 : Color 程 序 的 源 代 码
// ********************************************************************
#include "resource.h"
#include "afxres.h"
AFX_IDI_STD_FRAME ICON "res\\Color.ico"
IDR_MAINFRAME MENU
BEGIN
POPUP "&Options"
BEGIN
MENUITEM "&Color", IDM_COLOR
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_APP_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About Color...", ID_APP_ABOUT
END
END
IDD_ABOUTBOX DIALOG 0, 0, 240, 65
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Color"
FONT 8, "MS Sans Serif"
BEGIN
BEGI N
LTEXT "Red",IDC_STATIC,16,15,14,8
LTEXT "Green",IDC_STATIC,16,49,20,8
LTEXT "Blue",IDC_STATIC,16,83,14,8
CONTROL "Slider1",IDC_SLIDE_RED,"msctls_trackbar32",
TBS_NOTICKS | WS_TABSTOP,42,10,106,21,
WS_EX_STATICEDGE
CONTROL "Slider1",IDC_SLIDE_GREEN,"msctls_trackbar32",
TBS_NOTICKS | WS_TABSTOP,42,44,106,21,
WS_EX_STATICEDGE
CONTROL "Slider1",IDC_SLIDE_BLUE,"msctls_trackbar32",
TBS_NOTICKS | WS_TABSTOP,42,78,106,21,
#include "Resource.h"
class CColorApp : public CWinApp
{
public:
virtual BOOLInitInstance();
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CColorDlg dialog
class CColorDlg : public CDialog
{
public:
int nColor[3];
BOOL bCreate;
CColorDlg ();
protected:
virtual BOOLOnInitDialog ();
virtual voidOnOK ();
afx_msg voidOnCancel ();
afx_msg voidOnHScroll( UINT nCode, UINT nPos, CScrollBar* pScroll );
DECLARE_MESSAGE_MAP()
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CMainFrame
class CMainFrame : public CFrameWnd
{
public:
CColorDlg* pColorDlg;
CMainFrame();
~CMainFrame();
protected:
afx_msg voidOnAbout();
afx_msg BOOLOnEraseBkgnd( CDC* pDC );
afx_msg voidOnColor();
DECLARE_MESSAGE_MAP()
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CAboutDlg dialog
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
};
CAboutDlg::CAboutDlg() : CDialog( IDD_ABOUTBOX )
{
}
Color.cpp
// ********************************************************************
//
// Color.cpp
//
// ********************************************************************
#define VC_EXTRALEAN
#include <afxwin.h>
#include <afxcmn.h>
#include "Color.h"
CColorApp theApp;
BOOL CColorApp::InitInstance()
{
m_pMainWnd = new CMainFrame;
m_pMainWnd->ShowWindow( m_nCmdShow );
m_pMainWnd->UpdateWindow ();
return TRUE;
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CMainFrame
BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)
ON_COMMAND (IDM_COLOR, OnColor)
ON_COMMAND (ID_APP_ABOUT, OnAbout)
ON_WM_ERASEBKGND ()
END_MESSAGE_MAP ()
CMainFrame::CMainFrame ()
{
pColorDlg = new CColorDlg;
Create(NULL, "Color", WS_OVERLAPPEDWINDOW, rectDefault, NULL,
MAKEINTRESOURCE (IDR_MAINFRAME) );
}
CMainFrame::~CMainFrame ()
{
delete pColorDlg;
}
void CMainFrame::OnColor()
{
if (pColorDlg->bCreate) // If the dialog already exists,
pColorDlg->SetFocus(); // give it focus
else // Otherwise, create it
{
if (pColorDlg->Create( IDD_COLOR_DIALOG, this ))
pColorDlg->bCreate = TRUE;
}
}
BOOL CMainFrame::OnEraseBkgnd( CDC* pDC )
{
Cbrush brush;
CRect rect;
COLORREF rgbBackGnd = RGB ((BYTE) pColorDlg->nColor[0],
(BYTE) pColorDlg->nColor[1],
(BYTE) pColorDlg->nColor[2]);
GetClientRect( &rect );
brush.CreateSolidBrush( rgbBackGnd );
pDC->FillRect( rect, &brush );
return TRUE;
}
void CMainFrame::OnAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // CColorDlg dialog BEGIN_MESSAGE_MAP (CColorDlg, CDialog) ON_WM_HSCROLL () END_MESSAGE_MAP () CColorDlg::CColorDlg () |
|||
---|---|---|---|
{ |
|||
nColor[0] = nColor[1] = |
0; 128; |
// Initial color is // medium-intensity green |
|
nColor[2] = bCreate = |
0; FALSE; |
// Haven't created the dialog yet |
|
} |
BOOL CColorDlg::OnInitDialog ()
{
CSliderCtrl* pSlide[3];
CString szColorValue;
int i;
for (i=0; i < 3; i++)
{
pSlide[i] = (CSliderCtrl*) GetDlgItem( IDC_SLIDE_RED + i );
pSlide[i]->SetRange( 0, 255 );
pSlide[i]->SetPos( nColor[i] );
szColorValue.Format( "%d", nColor[i] );
SetDlgItemText( i + IDC_STATIC_RED, szColorValue );
}
SetIcon( AfxGetApp()->LoadIcon( AFX_IDI_STD_FRAME ), FALSE );
return TRUE;
}
void CColorDlg::OnHScroll( UINT nCode, UINT nPos, CScrollBar* pScroll )
{
CSliderCtrl* pSlide = (CSliderCtrl*) pScroll;
CString szColorValue;
int i = pSlide->GetDlgCtrlID () - IDC_SLIDE_RED;
nColor[i] = pSlide->GetPos (); // Slider position is
szColorValue.Format( "%d", nColor[i] ); // component 0-255
// Write current component value in the "x" static control
SetDlgItemText( i + IDC_STATIC_RED, szColorValue );
AfxGetMainWnd()->Invalidate ();
}
void CColorDlg::OnOK ()
{
OnCancel (); // Close dialog when OK Clicked
}
// Close on (1) OK button; (2) Esc key; or (3) dialog's Close command
void CColorDlg::OnCancel ()
{
if (DestroyWindow ())
((CMainFrame*) AfxGetMainWnd())->pColorDlg->bCreate = FALSE;
}
程 序 的 所 有 主 要 工 作 是 由 两 个 类 来 实 现 的 , 它 们 分 别 是 用 于 主 窗 口 的CMainFrame , 以 及 一 个 名 为 Ccolordlg 的 Cdialog 派 生 类 , 它 的 作 用 是 用 来 驱 动非 模 态 对 话 框 。 CColorDlg 构 造 器 初 始 化 一 个 代 表 主 窗 口 的 背 景 颜 色 值 的 数 组 , 它 以 中 等 密 度 的 绿 色 开 始 。既 然 窗 口 背 景 颜 色 的 红 、绿 和 蓝 成 份 可 从 0 变 到 255 , 那 么 , OnInitDialog 函 数 可 以 把 每 个 滑 块 滚 动 范 围 设 为 从 0 到 255 。 这 就 意 味 着 , 该 范 围 内 的 一 个 整 数 可 代 表 任 何 一 个 时 刻 的 拇 指 按 钮 的 位 置 ,可 以 很 方 便 地 确 定颜 色 成 分 的 当 前 值 。
当 用 户 移 动 滑 块 拇 指 的 时 候 , CColorDlg::OnHScroll 函 数 就 获 得 控 制 权 , 并 指 出哪 个 滑 块 正 在 通 过 调 用 GetDlgCtrlID 被 移 动 。 该 函 数 然 后 调 用 GetPos 来 获 得 新的 拇 指 位 置 , 将 该 值 写 到 nColor 数 组 和 对 话 中 的 静 态 文 字 控 件 之 中 , 并 且 调 用Invalidate 函 数 。
对 Invalidate 的 调 用 将 导 致 操 作 系 统 向 主 窗 口 发 送 一 条 WH_ERASEBKGND 消息 , 告 诉 该 窗 口 为 自 己 重 新 上 色 。 该 消 息 为 像 Color 这 样 的 应 用 程 序 提 供 了 一 个为 自 己 填 上 背 景 颜 色 的 机 会 。 大 多 数 应 用 程 序 都 忽 略 W M _ERASEBKGND 消息 ,在 这 些 情 形 中 ,W indows 将 使 用 程 序 在 创 建 窗 口 时 所 指 定 的 默 认 背 景 颜 色 不为 窗 口 上 色 ( 通 常 是 白 的 )。 Color.cpp 在 它 的 CMainFrame::OnEraseBKGnd 函 数 中截 住 了 WM_ERASEBKGND 消 息 , 该 函 数 在 存 储 在 nColor 数 组 中 的 红 、 绿 和 蓝颜 色 组 成 的 当 前 值 的 基 础 之 上 , 声 明 了 COLORREF 对 象 :
COLORREF rgbBackGnd = RGB ((BYTE) pColorDog->nColor[0],
(BYTE) pColorDog->nColor[1], (BYTE) pColorDog->nColor[2],
OnEraseBkGnd 然 后 从 rgbBackGnd 中 创 建 画 刷 , 并 使 用 它 为 窗 口 上 色 , 并 且 返回 一 个 值 TURE 。 TRUE 返 回 值 用 来 告 诉 操 作 系 统 , 它 不 应 该 用 默 认 的 颜 色 清 除窗 口 , 因 为 应 用 程 序 已 经 重 新 上 了 背 景 颜 色 。
所 有 这 些 都 是 为 了 解 释 为 什 么 程 序 要 在 创 建 主 窗 口 之 前 采 取 特 殊 的 步 骤 来 创 建非 模 态 对 话 控 件 :
CMainFrame::CMainFrame ()
{
pColorDlg = new CColorDlg;
Create( NULL, " Color" , WS_OVERLAPPEDWINDOW, rectDefault, NULL, MAKEINTRESOURCE (IDR_MAINFRAME) );
}
在 主 窗 口 出 现 之 后 , 操 作 系 统 立 即 发 送 WM_ERASEBKGND 消 息 , 因 此 , 首 先创 建 CColorDlg 对 象 , 可 以 确 保 OnEraseDKGnd 函 数 读 到 nColor 数 组 中 有 效 的颜 色 值 。
例 3 : 向 AppWizard 程 序 添 加 对 话
如 果 你 愿 意 在 AppWizard 的 帮 助 下 开 始 项 目 , 那 么 , 前 一 节 中 的 Color 程 序 看 上去 就 与 此 没 有 关 系 了 。 实 际 上 , 它 是 有 关 的 。 向 程 序 添 加 新 对 话 将 调 用 相 同 的 步骤 , 不 管 是 否 由 AppWizard 创 建 这 个 程 序 。 但 AppWizard 将 生 成 精 确 表 单 的 代码 ,它与 Color.cpp 的 紧 凑 样 式 相 匹 配 可 能 会 有 点 儿 困 难 。为 显 示 在 向 AppWizard 程 序 中 添 加 新 对 话 中 引 用 了 什 么 ,本 节 将 演 示 使 用 AppWizard 范 例 程 序 MFcTree 的 必 要 步 骤 。
图 5-12 所 显 示 的 M fcTree 对 话 并 不 稀 奇 ,仅 仅 是 一 些 MFC 类 和 一 个 O K 按 钮 的树 状 视 图 。 但 它 却 可 以 很 好 地 用 来 演 示 要 说 明 的 问 题 , 在 本 章 稍 后 和 第 13 章 , 我 们 还 要 对 其 进 行 改 进 。
图 5-12 MfcTree 程序
该 程 序 的 创 建 过 程 可 分 为 五 步 :
-
运 行 AppWizard 创 建 M fcTree 项 目 。
-
在 对 话 编 辑 器 中 创 建 对 话 资 源 。
-
向 项 目 添 加 新 的 对 话 类 的 资 源 文 件 。
-
修 改 菜 单 。
-
向 项 目 资 源 文 件 添 加 必 要 的 源 代 码 。下 面 , 我 们 来 一
步 一 步 地 进 行 。
步 骤 1 : 运 行 AppWizard 来 创 建 M fcTree项 目
在 File ( 文 件 ) 菜 单 上 单 击 New , 并 在 New 对 话 中 选 中 Projects 选 项 卡 。 选 择MFC AppWizard (exe) 图 标 , 并 将 新 项 目 命 名 为 MfcTree, 然 后 单 击 OK 按 钮 运 行AppWizard 。 除 了 如 下 说 明 的 例 外 选 项 外 , 其 他 均 接 受 AppWizard 的 默 认 设 置 。这 些 例 外 是 ,在 步 骤 1 中 选 中 Single Document Interfac e( 单 文 档 界 面 ),在 步 骤 4中 清 除 掉 用 于 停 靠 工 具 栏 和 打 印 支 持 的 复 选 框 。如 果 想 在 配 套 CD 上 保 持 短 文 件名 , 那 么 默 认 的 M fcTreeDoc 和 MfcTreeView 文 件 名 应 改 为 M fcDoc 和 M fcView , 但 这 个 步 骤 完 全 是 可 选 的 。
步 骤 2 : 创 建 M fcTree 对 话
既 然 M fcTree 是 一 个 打 开 的 项 目 , 那 么 , 我 们 就 可 以 设 计 它 的 对 话 资 源 。 通 过 单
击 Insert( 插 入 ) 菜 单 上 的 Resource, 并 双 击 资 源 类 型 列 表 中 的 D ialog 来 启 动 资源 对 话 框 。 在 工 作 区 中 选 中 默 认 的 Cancel 按 钮 , 并 按 Del 键 来 删 除 该 按 钮 。 在对 话 工 作 区 内 任 何 地 方 右 击 , 并 从 上 下 文 菜 单 中 选 择 Properties 来 引 用 D ialog Properties ( 属 性 ) 框 。 将 对 话 标 题 改 为 M fcTree , 将 对 话 标 识 符 改 为IDC_MFC_DIALOG 。
下 一 步 是 添 加 树 状 视 图 控 件 , 从 Controls (控件)工具栏中,将 Tree Contro l( 树状 控 件 ) 工 具 拖 入 对 话 工 作 区 , 并 根 据 需 要 调 整 对 话 工 作 区 和 控 件 的 大 小 。 单 击View ( 查 看 ) 菜 单 上 的 Properties 来 调 用 Tree Control Propertie s( 树 状 控 件 属 性 ) 框 ,并 将 标 识 符 符 号 改 为 IDC_MFC_TREE 。在 Style 选 项 卡 中 ,单 击 Has Buttons
( 有 按 钮 ), Has Lines ( 有 线 ) 和 Lines At Roo t( 根 位 置 的 线 ) 复 选 框 , 如 下 图所 示 :
这 些 样 式 改 变 将 向 列 表 视 图 添 加 小 的 加 号 或 减 号 图 标 , 当 单 击 这 些 图 标 的 时 候 , 将 折 叠 或 展 开 列 表 层 次 中 的 各 级 。使 用 本 章 前 面 介 绍 的 水 平 间 隔 工 具 将 O K 按 钮移 到 对 话 和 中 心 两 个 控 件 的 底 部 。 现 在 , 对 话 在 编 辑 工 作 区 中 的 样 子 如 图 所 示 :
从 Fil e( 文 件 )菜 单 选 择 Save ,将 新 对 话 脚 本 保 存 到 M fcTree.rc 文 件 。Visual C++ 自 动 向 Resource 文 件 添 加 代 表 新 标 识 符 的 #define 语 句 。 通 过 单 击 File ( 文 件 ) 菜 单 上 的 Close 命 令 关 闭 对 话 编 辑 器 。
步 骤 3 : 为 C M fcDlg 对 话 类 添 加 源 文 件
我 们 现 在 已 经 拥 有 了 一 个 新 的 对 话 资 源 , 但 是 , 需 要 从 CDialog 派 生 的 一 个 类 才能 运 行 它 。 在 下 一 章 中 , 我 们 将 会 看 到 如 何 使 用 ClassWizard 来 生 成 主 体 的 对 话类 , 并 自 动 将 它 的 文 件 添 加 到 项 目 中 , 但 目 前 , 我 们 只 能 使 用 文 本 编 辑 器 来 完 成相 同 的 工 作 。 为 包 含 新 的 CMfcDlg 对 话 类 ( 列 表 5-2) 而 创 建 源 文 件 C M fD lg.h 和M fcDlg.cpp 。 现 在 我 们 只 需 要 这 些 很 少 的 文 件 , 就 能 将 CMfcDlg 类 添 加 到 项 目 。我 们 将 在 步 骤 5 中 将 源 代 码 添 加 到 文 件 。
如 果 想 从 头 开 始 为 一 个 像 M fcTree 这 样 的 开 放 项 目 创 建 新 的 源 文 件 ,请 将 箭 头 停在 Project( 项 目 ) 菜 单 的 Add To Project( 添 加 到 项 目 ) 命 令 上 , 然 后 , 单 击 随后 出 现 的 次 级 菜 单 上 的 New 。 选 择 你 想 创 建 的 文 件 , 并 输 入 文 件 名 。单 击 O K 启动 文 本 编 辑 器 , 编 辑 器 中 将 出 现 一 个 空 的 文 档 窗 口 。
列 表 5-2 : CMfcDlg 类 的 主 体 源 文 件
MfcDlg. h
// ********************************************************************
//
// MfcDlg.h
//
// ********************************************************************
class CMfcDlg : public CDialog
{
public:
CMfcDlg( CWnd* pParent = NULL );
protected:
virtual BOOL OnInitDialog();
};
MfcDlg.cpp
// ********************************************************************
//
// MfcDlg.cpp
//
// ********************************************************************
#include "stdafx.h"
#include "MfcTree.h"
#include "MfcDlg.h"
CMfcDlg::CMfcDlg( CWnd* pParent ) :
如 果 你 在 文 本 编 辑 器 中 键 入 了 两 个 源 文 件 , 完 成 之 后 , 一 定 要 把 它 们 保 存 到 项 目文 件 夹 。 另 一 种 方 法 是 , 你 可 以 从 配 套 CD 上 的 Chapter.os\MfcTree 文 件 夹 中 复制 这 两 个 文 件 的 完 整 形 式 。 复 制 文 件 需 要 你 将 它 们 手 工 添 加 到 项 目 。在 弹 出 的 次级 菜 单 上 选 择 Add To Project, 并 单 击 Files , 然 后 双 击 文 件 列 表 中 的 MfcDlg.cpp 文 件 , 将 它 添 加 到 项 目 之 中 。
不 必 用 相 同 的 方 法 来 添 加 M fcDlg.h 文 件 , 因 为 Visual C++ 将 头 文 件 识 别 为
M fcDlg.cpp 的 相 关 文 件 。
步 骤 4 : 修 改 菜 单
M fcTree 需 要 一 个 菜 单 命 令 来 调 用 对 话 , 但 是 , 不 需 要 AppWizard 放 在 菜 单 上 的其 他 命 令 。 使 用 第 4 章 中 介 绍 的 Visual C++ 菜 单 编 辑 器 将 M fcTree 的 菜 单 修 改 成如 下 的 样 子 。
在 菜 单 编 辑 器 中 , 双 击 Workspace ( 工 作 空 间 ) 窗 口 的 ResourceView 窗 格 中 的IDR_MAINFRAME 菜 单 标 识 符 可 以 打 开 资 源 。 在 菜 单 编 辑 器 中 , 双 击 MFcTree 菜 单 来 显 示 Menu Item Properties ( 菜 单 项 属 性 ) 框 。 键 入 IDM_OPTION_MFC 作 为 项 目 的 标 识 符 , 然 后 按 ENTER 键 。
步 骤 5 : 添 加 需 要 的 源 代 码
如 果 按 照 步 骤 3 中 所 列 出 的 代 码 键 入 了 MfcDlg.cpp 文 件 , 该 文 件 仅 仅 包 含 一 个类 构 造 器 和 一 个 叫 做 OnInitDialog 的 存 根 函 数 。 OnInitDialog 函 数 需 要 用 下 面 显示 的 带 阴 影 的 代 码 , 来 初 始 化 树 形 视 图 控 件 。 正 如 你 所 看 到 的 , 它 可 以 用 许 多 指令 来 初 始 化 树 形 视 图 。 如 果 你 通 过 自 己 创 建 M fcTree 来 顺 着 这 些 步 骤 进 行 操 作 , 那 么 没 有 必 要 键 入 所 有 的 行 。 只 需 键 入 头 一 组 , 或 者 从 配 套 CD 的Chapter.os\MfcTree 文 件 夹 中 的 MfcDlg.cpp 源 文 件 中 进 行 剪 切 和 粘 贴 即 可 。
OnInitDialog 函 数 用 来 初 始 化 一 个 名 为 PTree 的 指 针 , 该 指 针 指 向 的 是 作 为IDC_MFe_TRUE 标 识 的 对 话 的 树 形 窗 口 控 件 。 该 函 数 然 后 重 复 调 用 Ctree Ctrl::nsertItem 函 数 来 向 控 制 添 加 一 个 包 含 有 从 CWnd 派 生 的 MFe 类 的 层 次 列表 。 项 目 被 插 入 到 层 次 中 比 它 的 父 层 低 一 级 的 列 表 之 中 , 第 二 个 参 数 或 者 是 以 前为 父 层 级 调 用 InsertItem 所 返 回 的 MTREEITEM 值 , 或 者 是 值 TVI_ROOT ( 如 果没 有 父 层 的 话 )。 TV1_SORT 标 志 指 示 树 形 视 窗 控 件 将 该 项 目 按 字 母 顺 序 排 序 :
BOOL CMfcDlg::OnInitDialog()
{
hRoot = pTree->InsertItem( "Control bars", TVI_ROOT, TVI_SORT );
hLevel1 = pTree->InsertItem( "CControlBar", hRoot );
hLevel2 = pTree->InsertItem( "CDialogBar", hLevel1 );
hLevel2 = pTree->InsertItem( "COleResizeBar", hLevel1 );
hLevel2 = pTree->InsertItem( "CStatusBar", hLevel1 );
hLevel2 = pTree->InsertItem( "CToolBar", hLevel1 );
hRoot = pTree->InsertItem( "Other windows", TVI_ROOT, TVI_SORT );
hLevel1 = pTree->InsertItem( "CPropertySheet", hRoot );
hLevel1 = pTree->InsertItem( "CSplitterWnd", hRoot );
hRoot = pTree->InsertItem( "Dialog boxes", TVI_ROOT, TVI_SORT );
hLevel1 = pTree->InsertItem( "CDialog", hRoot );
hLevel2 = pTree->InsertItem( "CCommonDialog", hLevel1 );
hLevel3 = pTree->InsertItem( "CColorDialog", hLevel2 );
hLevel3 = pTree->InsertItem( "CFileDialog", hLevel2 );
hLevel3 = pTree->InsertItem( "CFindReplaceDialog", hLevel2 );
hLevel3 = pTree->InsertItem( "CFontDialog", hLevel2 );
hLevel3 = pTree->InsertItem( "COleDialog", hLevel2 );
hLevel4 = pTree->InsertItem( "COleBusyDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COleChangeIconDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COleChangeSourceDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COleConvertDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COleInsertDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COleLinksDialog", hLevel3 );
hLevel5 = pTree->InsertItem( "COleUpdateDialog", hLevel4 );
hLevel4 = pTree->InsertItem( "COlepasteSpecialDialog", hLevel3 );
hLevel4 = pTree->InsertItem( "COlePropertiesDialog", hLevel3 );
hLevel3 = pTree->InsertItem( "CPageSetupDialog", hLevel2 );
hLevel3 = pTree->InsertItem( "CPrintDialog", hLevel2 );
hLevel2 = pTree->InsertItem( "COlePropertyPage", hLevel1 );
hLevel2 = pTree->InsertItem( "CPropertyPage", hLevel1 );
hRoot = pTree->InsertItem( "Views", TVI_ROOT, TVI_SORT );
hLevel1 = pTree->InsertItem( "CView", hRoot );
hLevel2 = pTree->InsertItem( "CCtrlView", hLevel1 );
hLevel3 = pTree->InsertItem( "CEditView", hLevel2 );
hLevel3 = pTree->InsertItem( "CListView", hLevel2 );
hLevel3 = pTree->InsertItem( "CRichEditView", hLevel2 );
hLevel3 = pTree->InsertItem( "CTreeView", hLevel2 );
hLevel2 = pTree->InsertItem( "CScrollView", hLevel1 );
hLevel3 = pTree->InsertItem( "CFormView", hLevel2 );
hLevel4 = pTree->InsertItem( "CDaoRecordView", hLevel3 );
hLevel4 = pTree->InsertItem( "CRecordView", hLevel3 );
hRoot = pTree->InsertItem( "Controls", TVI_ROOT, TVI_SORT );
hLevel1 = pTree->InsertItem( "CAnimateCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CButton", hRoot );
hLevel2 = pTree->InsertItem( "CBitmapButton", hLevel1 );
hLevel1 = pTree->InsertItem( "CComboBox", hRoot );
hLevel1 = pTree->InsertItem( "CEdit", hRoot );
hLevel1 = pTree->InsertItem( "CHeaderCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CHotKeyCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CListBox", hRoot );
hLevel2 = pTree->InsertItem( "CCheckListBox", hLevel1 );
hLevel2 = pTree->InsertItem( "CDragListBox", hLevel1 );
hLevel1 = pTree->InsertItem( "CListCtrl", hRoot );
hLevel1 = pTree->InsertItem( "COleCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CProgressCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CRichEditCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CScrollBar", hRoot );
hLevel1 = pTree->InsertItem( "CSliderCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CSpinButtonCtrl", hRoot );
hLevel1 = pTree->InsertItem( "CStatic", hRoot );
return TRUE;
}
尽 管 上 面 的 代 码 目 前 可 以 工 作 , 但 是 , 这 是 十 分 不 够 的 。 第 13 章 中 所 引 入 的
M fcTree3 程 序 显 示 了 一 个 更 加 清 楚 的 方 法 , 来 实 现 对 InsertItem 的 一 系 列 调 用 。
下 一 步 , 在 文 本 编 辑 器 中 编 辑 文 件 MfcTree.cpp 和 MfcTree.h , 并 添 加 一 个 叫 做OnMfcTree 的 函 数 。当 用 户 单 击 了 程 序 的 Options 菜 单 上 的 MFC TREE 命 令 的 时候 , OnMfcTree 处 理 函 数 就 获 得 了 控 制 。 如 果 想 添 加 OnMfcTree , 请 通 过 在
Workspa c (e 工 作 空 间 )窗 口 的 FileViews 窗 格 中 双 击 其 文 件 名 ,来 打 开 M fcTree.cpp
文 档 。 在 靠 近 源 代 码 开 始 处 插 入 如 下 代 码 :
#includ e "MfcDlg.h "
另 外 , 编 辑 MfcTree.cpp 中 的 消 息 映 射 , 使 它 成 为 下 面 的 样 子 :
BEGIN_MESSAGE_MAP(CMfcTreeApp, CWinApp)
//{{AFX_MSG_MAP(CMfcTreeApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(IDM_OPTIONS_MFC , OnMfcTree )
//}}AFX_MSG_MAP END_MESSAGE_MAP()
将 OnMfcTree 函 数 添 加 到 MfcTree.cpp :
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CMfcTreeApp message handlers
voi d CMfcTreeApp::OnMfcTree( )
并 在 M fcTree.h 文 件 中 声 明 它 :
// Implementation
//{{AFX_MSG(CMfcTreeApp) afx_msg void OnAppAbout();
afx_ms g voi d OnMfcTree() ;
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};
现 在 就 准 备 创 建 M fcTree 了 。单 击 Build 菜 单 上 的 Set Active Configuratio n( 设 置有 效 配 置 ) 命 令 , 来 选 中 W in32 Release 目 标 , 然 后 就 可 以 创 建 和 测 试 这 个 应 用程 序 。
基 于 对 话 的 应 用 程 序
M fcTree 的 所 有 操 作 都 在 对 话 中 而 不 是 在 主 窗 口 中 进 行 。 如 果 程 序 将 主 窗 口 完 全隐 藏 起 来 , 仅 仅 显 示 对 话 , 那 么 将 更 加 方 便 , 这 可 以 省 掉 用 户 单 击 菜 单 命 令 来 调用 窗 口 的 麻 烦 。 以 前 , 你 曾 经 看 到 过 这 样 的 基 于 对 话 的 应 用 程 序 , 即 W indows 提 供 的 Character Map ( 字 符 映 射 表 ), Calculator( 计 算 器 ) 和 Phone Dialer( 电话 拨 号 程 序 ) 实 用 程 序 , 都 是 用 来 显 示 一 个 程 序 如 何 有 效 地 通 过 代 替 主 窗 口 的 单个 对 话 来 与 用 户 进 行 有 效 联 系 的 例 子 。 在 本 节 中 , 我 们 将 看 到 如 何 用 Visual C++ 编 写 基 于 对 话 的 应 用 程 序 , 并 创 建 一 个 范 例 程 序 来 演 示 这 项 技 术 。
用 C 编 写 的 基 于 对 话 的 应 用 程 序 不 初 始 化 WNDCLASS 或 WNDCLASSEX 结构 , 不 调 用 RegisterClass 来 注 册 窗 口 类 。 不 调 用 CreateWindow 来 创 建 主 窗 口 。它 不 调 用 ShowWindow 和 UpdateWindow , 甚 至 没 有 调 用 GetMessage 和D ispatch M essage 的 消 息 循 环 。 它 不 需 要 这 些 东 西 , 与 用 户 的 所 有 交 互 都 在 对 话中 发 生 , W indows 可 以 处 理 它 , 程 序 仅 仅 需 要 创 建 类 似 于 下 面 的 对 话 即 可 :
int WINAPI WinMain( HINTANCE hInst, HINSTANCE hInstPrev,
LPSTR szCmdline, int nCmdShow)
{
DialogBox(hInst, MAKEINTRESOURCE (IDD_DIALOG),
NULL,DlgProc);
return( 0 );
}
在 这 个 代 码 段 中 , IDD_DIALOG 值 用 来 标 识 该 程 序 的 RC 文 件 中 的 对 话 脚 本 。D lgProc 是 一 个 指 针 ,它 指 向 的 是 接 收 像 WM_INITDIALOG 和 W M _ C O M M A N D 这 样 的 系 统 消 息 的 过 程 。
MFC 程 序 没 有 可 见 的 W inMain 函 数 或 消 息 , 因 此 , 有 关 对 话 界 面 的 代 码 数 量 减少 了 许 多 。 但 MFC 提 供 了 AppWizard 的 优 点 , 它 可 以 为 基 于 对 话 的 应 用 程 序 生成 模 板 形 式 的 代 码 。
例 4 : M fcTree 的 基 于 对 话 的 版 本
AppWizard 为 基 于 对 话 的 应 用 程 序 所 编 写 的 代 码 比 它 为 一 般 的 应 用 程 序 所 生 成
的 代 码 更 加 清 晰 , 更 加 易 于 理 解 。 在 AppWizard 的 Step1( 如 图 5-13 所示 ) 中 单 击D ialog Based 单 选 按 钮 , 将 导 致 AppWizard 为 两 个 类 创 建 源 文 件 , 一 个 为 应 用 程序 , 另 一 个 为 对 话 对 象 。
AppWizard 为 仅 包 含 一 个 O K 按 钮 、 一 个 Cancel 按 钮 以 及 一 个 带 有 警 告 “ Place dialog controls here ( 将 对 话 控 件 放 在 这 里 )” 的 静 态 控 件 的 对 话 窗 口 生 成 资 源 脚本 。 如 果 你 在 AppWizard 的 步 骤 2 中 单 击 了 Content-Sensitive Help ( 与 内 容 相 关的 帮 助 ) 复 选 框 的 话 。 该 对 话 还 包 括 一 个 Help 按 钮 ( 如 果 想 了 解 有 关 的 详 细 信息 , 请 参 阅 第 2 章 )。 这 种 方 法 的 思 路 是 在 创 建 项 目 之 后 , 为 你 运 行 对 话 编 辑 器 , 并 将 应 用 程 序 需 要 的 控 件 添 加 到 对 话 中 。
在 Visual C++ 版本 6.0 中 , 当 AppWizard 完 成 之 后 , 对 话 编 辑 器 将 自 动 启 动 。 在以 前 的 版 本 中 , 你 必 须 自 己 通 过 双 击 ResourceView 窗 口 中 的 对 话 标 识 符 才 能 启动 。
图 5-13 在 AppWizard 中创建基于对话的应用程序
用 AppWizard 创 建 M fcTree 的 基 于 对 话 的 版 本 只 需 三 个 步 骤 ,与 前 一 节 中 的 五 个步 骤 对 比 如 下 :
步 骤 主 窗 口 版 本 基 于 对 话 的 版 本
-
运 行 AppWizard 创 建 项 目 √ √
-
创 建 或 修 改 对 话 √ √
-
插 入 新 对 话 类 的 源 文 件 √
-
修 改 菜 单 √
-
添 加 所 必 需 的 源 代 码 √ √
为 对 话 创 建 新 类 的 步 骤 3 和 修 改 主 菜 单 的 步 骤 4 ,在 MfcTree 基 于 对 话 的 版 本 中是 不 需 要 的 。 AppWizard 为 对 话 类 自 动 生 成 主 体 源 文 件 , 清 除 主 窗 口 也 取 消 了 对菜 单 的 需 要 。甚 至 AppWizard 所 生 成 的 源 代 码 也 比 较 易 于 修 改 ,因 为 你 仅 仅 需 要编 辑 CMfDlg::OnInitDialog 函 数 , 在 该 函 数 的 TODO 行 后 添 加 InsertItem 调 用 和以 前 一 样 , 下 面 代 码 段 中 的 灰 色 阴 影 表 示 是 新 的 源 程 序 行 ,它 们 与 以 前 介 绍 的 添加 到 M fcTree 的 原 始 版 本 中 的 代 码 是 一 样 的 :
BOOL CMfcDlg::OnInitDialog()
{
Cdialog::OnInitDialog();
.
.
.
// TODO: Add extra initiallization here
//Ad d th e res t o f th e sourc e cod e her e
}
图 5-14 显 示 了 M fcTree , 这 是 它 基 于 对 话 的 版 本 。 从 本 质 上 讲 , 除 了 主 窗 口 已 被清 除 ,对 话 标 题 栏 现 在 包 含 应 用 程 序 图 标 和 系 统 菜 单 , 并 且 程 序 更 加 易 于 创 建 和使 用 之 外 , 它 与 图 5-12 中 所 显 示 的 原 始 版 本 是 同 一 个 程 序 。 如 果 你 想 自 己 试 试这 个 新 版 本 , 可 以 在 配 套 CD 上 Chapteros\MfcTree2 文 件 类 中 找 到 它 。
图 5-14 MfcTree 程序基于对话的版本
例 5 : 不 用 AppWizard 实 现 的 基 于 对 话 的 应 用 程 序
在 创 建 基 于 对 话 的 应 用 程 序 的 时 候 , AppWizard 起 了 很 大 的 作 用 , 因 为 这 样 的 应用 程 序 在 方 法 上 很 一 致 , 因 此 AppWizard 添 加 你 不 想 要 的 代 码 的 可 能 性 就 很 小 。但 AppWizard 可 能 仍 然 满 足 不 了 你 的 特 殊 需 要 , 如 果 你 对 不 用 AppWizard 编 写基 于 对 话 的 应 用 程 序 感 兴 趣 , 那 么 本 节 将 告 诉 你 如 何 去 做 。 它 用 名 为 D irList1 的范 例 程 序 来 进 行 说 明 , 该 程 序 的 作 用 是 在 对 话 中 显 示 一 个 目 录 列 表 。但 是 为 了 更加 有 趣 ,D irList1 展 现 给 用 户 的 对 话 是 一 个 属 性 表 ,通 常 叫 做 多 选 项 卡 的 对 话 框 。
属 性 表 可 以 向 用 户 展 示 大 量 的 信 息 , 这 就 很 好 地 解 决 了 对 话 框 过 分 拥 挤 的 问 题 , 但 从 本 质 上 讲 , 属 性 表 也 仅 仅 是 一 个 对 话 , 或 者 可 以 说 是 一 系 列 叫 做 页 面 的 对话 , 这 些 页 面 一 个 盖 着 另 一 个 , 你 可 以 像 设 计 其 他 对 话 一 样 用 对 话 编 辑 器 设 计 属性 表 的 每 页 。 RC 文 件 中 一 个 页 面 的 属 性 脚 本 看 上 去 与 普 通 的 对 话 是 一 样 的 , 只是 属 性 表 的 所 有 页 面 都 具 有 相 同 的 大 小 。当 程 序 调 用 PropertySheet API 函 数 创 建MFC CPropertySheet 对 象 的 时 候 , Windows 将 属 性 表 页 面 做 为 对 话 来 显 示 。
偶 然 情 况 下 ,你 可 能 会 遇 到 对 话 编 辑 器 的 Control s( 控 件 )工 具 栏 中 的 Tab Control
( 选 项 卡 控 件 ) 的 工 具 。 这 个 控 件 显 示 一 组 可 以 在 对 话 中 充 当 属 性 表 的 分 选 项 卡的 页 面 , 但 并 不 将 你 的 对 话 转 化 为 属 性 表 。
图 5-15 显 示 了 DirList1 属 性 对 话 的 第 一 个 和 第 二 个 页 面 , 标 签 分 别 为 Location
和 Date 。
Date 选 项 卡 利 用 新 的 Date-Time Picke r( 日 期 - 时 间 选 取 器 ) 控 件 , 允 许 用 户 通 过弹 出 的 日 历 选 择 日 期 , 尽 管 Date 和 Size 页 面 可 以 正 常 工 作 , 但 是 , 该 页 面 的 存在 仅 仅 是 为 了 说 明 的 目 的 , 对 程 序 的 这 个 版 本 并 没 有 影 响 ( 第 7 章 中 将 要 介 绍 的 D irList2 项 目 ,利 用 了 Date 和 Size 页 ) 。D irList1 中 的 重 要 活 动 在 Locatio n( 位 置 ) 页 中 发 生 , 它 在 一 个 列 表 框 控 件 中 显 示 一 个 目 录 列 表 。 DirList1 通 过 调 用CWnd::DlgDirList 函 数 来 用 目 录 列 表 填 充 这 个 列 表 框 。
DlgDirListDir,IDC_LIST,IDC_DIRPATH,DOL_ALL);
参 数 pDir 指 向 以 null( 空 ) 结 束 的 字 符 串 , 该 字 符 串 包 含 了 目 录 路 径 。 常 数IDC_LIST 用 来 标 识 显 示 目 录 列 表 框 控 件 , IDC_DIRPATH 用 来 标 识 一 个 静 态 控件 , DLgDirList 把 路 径 字 符 串 写 到 这 个 控 件 里 面 。 DLL_ALL 是 一 个 在 源 代 码 中定 义 的 常 数 , 它 将 标 志 DDL_DRIV E , DDL_DIRECTORT 和 DDL_HIDDEN 组合 了 起 来 。 这 些 标 志 告 诉 D lgDirList, 在 目 录 列 表 中 包 括 驱 动 器 、 子 目 录 和 隐 藏的 文 件 。单 击 列 表 中 的 驱 动 器 或 子 目 录 ,将 改 变 路 径 ,并 刷 新 列 表 。利 用 Location 选 项 卡 中 标 签 为 Up 1 Directory Leve l( 向 上 一 级 目 录 ) 的 大 按 钮 , 用 户 可 以 回 到上 一 级 目 录 。
图 5-15 DirList1 程 序 的 Location 和 Date 选项卡
D irList1 中 的 属 性 表 对 话 仅 用 到 了 五 种 控 件 类 型 : 推 压 按 钮 、单 选 按 钮 、列 表 框 、编 辑 控 件 和 微 调 框 。 如 果 你 对 这 些 控 件 的 安 装 方 式 感 兴 趣 , 请 打 开 D irList.rc 文件 , 并 且 通 过 双 击 下 图 所 示 的 一 个 对 话 标 识 符 来 启 动 对 话 编 辑 器 。
IDD_PAGE 1,IDD_PAGE2 和 IDD_PAGE3 分 别 用 来 标 识 对 话 的 Location 页 ,Date
页 和 Size 页 。 列 表 5-3 显 示 了 D irList1 项 目 的 源 代 码 。
列 表 5-3 DirList1 的 源 程 序 文 件
#define IDI_APPICON 105
#define IDC_DIRPATH 110
#define IDC_LIST 111
#define IDC_BUTTON1 120
#define IDC_EDIT1 121
#define IDC_EDIT2 122
#define IDC_RADIO1 123
#define IDC_RADIO2 124
#define IDC_RADIO3 125
#define IDC_RADIO4 126
#define IDC_SPIN1 127
#define IDC_SPIN2 128
#include "afxres.h"
IDI_APPICON ICON "res\\dirlist.ico"
STRINGTABLE
BEGIN
IDD_ABOUTBOX "&About DirList..."
END
IDD_ABOUTBOX DIALOG 0, 0, 240, 65
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Directory List"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT LTEXT |
"Directory List Version 1.0",IDC_STATIC,45,10,115,8 """Microsoft Visual C++ Programmer's Guide""", IDC_STATIC,45,26,140,8 |
||
---|---|---|---|
LTEXT |
"Copyright \251 1998, Beck Zaratian", IDC_STATIC,45,42,115,8 |
||
DEFPUSHBUTTON |
"OK",IDOK,195,10,35,40,WS_GROUP |
||
END |
|||
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / |
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / |
||
// // Property page 1 - "Location" // IDD_PAGE1 DIALOG 0, 0, 282, 135 |
EN D
CONTROL "&between",IDC_RADIO2,"Button",
BS_AUTORADIOBUTTON | WS_TABSTOP,100,23,43,10
CONTROL "&within previous",IDC_RADIO3,"Button",
BS_AUTORADIOBUTTON | WS_TABSTOP,100,80,63,10
CONTROL "within &previous",IDC_RADIO4,"Button",
BS_AUTORADIOBUTTON | WS_TABSTOP,100,105,63,10
GROUPBOX "Only files dated:",IDC_STATIC,70,10,200,115,WS_GROUP
CONTROL "DateTimePicker1",IDC_DATETIME1,"SysDateTimePick32",DTS_RI GHTALIGN | WS_TABSTOP,170,20,50,15
LTEXT "and",IDC_STATIC,128,50,13,8,NOT WS_GROUP
CONTROL "DateTimePicker1",IDC_DATETIME2,"SysDateTimePick32",DTS_RI GHTALIGN | WS_TABSTOP,170,45,50,15
EDITTEXT IDC_EDIT1,170,76,35,16,ES_NUMBER
//
// ********************************************************************
class CDirListApp : public CWinApp
{
public:
BOOL InitInstance ();
};
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage1 property page
class CPage1 : public CPropertyPage
{
private:
BOOL bEditFocus;
CString strDirectory, strFilter;
void GetCurrentDirectory ();
void ShowList ();
public:
CPage1 () : CPropertyPage( IDD_PAGE1 ) {}
protected:
virtual void DoDataExchange( CDataExchange* pDX );
virtual BOOL OnInitDialog ();
afx_msg void OnEditGainFocus ();
afx_msg void OnEditLoseFocus ();
afx_msg void OnUp1Level ();
afx_msg void OnSelChange ();
DECLARE_MESSAGE_MAP ()
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage2 property page
class CPage2 : public CPropertyPage
{
public:
int nAnyDate;
Ctime timeMin, timeMax;
int PrevDays;
int PrevMonths;
CPage2 () : CPropertyPage( IDD_PAGE2 ) {}
protected:
virtual void Do DataExchange( CDataExchange* pDX );
virtual BOOL OnInitDialog ();
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage3 property page
class CPage3 : public CPropertyPage
{
public:
int nAnySize;
DWORD MinSize;
DWORD MaxSize;
CPage3 () : CPropertyPage( IDD_PAGE3 ) {}
protected:
virtual void DoDataExchange( CDataExchange* pDX );
virtual BOOL OnInitDialog ();
};
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CListSheet
class CListSheet : public CPropertySheet
{
public:
CPage1 page1;
CPage2 page2;
CPage3 page3;
CListSheet( LPCTSTR szCaption );
protected:
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand( UINT nID, LPARAM lParam );
DECLARE_MESSAGE_MAP()
};
DirList1.cpp
// ********************************************************************
//
// DirList1.cpp
//
// ********************************************************************
#include "afxwin.h"
#include "afxdlgs.h"
#include "afxcmn.h"
#include "resource.h"
#include "dirlist1.h"
#define DDL_ALL DDL_DIRECT ORY | DDL_DRIVES | DDL_HIDDEN
CDirListApp DirListApp;
BOOL CDirListApp::InitInstance ()
{
CListSheet sh( "Directory List" ); // Create property sheet object
sh.DoModal (); // and display dialog
return FALSE; // Return FALSE to exit DirList
}
CAboutDlg::CAboutDlg() : CDialog( IDD_ABOUTBOX )
{
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CListSheet property sheet
CListSheet::CListSheet( LPCTSTR szCaption ) : CPropertySheet( szCaption )
{
AddPage( &page1 );
AddPage( &page2 );
AddPage( &page3 );
}
BEGIN_MESSAGE_MAP (CListSheet, CPropertySheet)
ON_WM_SYSCOMMAND()
END_MESSAGE_MAP()
BOOL CListSheet::OnInitDialog()
{
CPropertySheet::OnInitDialog();
// Add "About..." command to system menu
CMenu* pSysMenu = GetSystemMenu( FALSE );
CString str;
str.LoadString( IDD_ABOUTBOX );
pSysMenu->AppendMenu( MF_SEPARATOR );
pSysMenu->AppendMenu( MF_STRING, IDD_ABOUTBOX, str );
// Remove Apply button, since it's not needed
CButton* button = (CButton *) GetDlgItem( ID_APPLY_NOW );
button->DestroyWindow();
// Set the 16-by-16 image (see closing remarks in Chapter 5)
HICON hIcon = (HICON) ::LoadImage( DirListApp.m_hInstance,
MAKEINTRESOURCE( IDI_APPICON ),
IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );
SetIcon( hIcon, FALSE );
return TRUE;
}
void CListSheet::OnSysCommand( UINT nID, LPARAM lParam )
{
if (nID == IDD_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CPropertySheet::OnSysCommand( nID, lParam );
}
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage1 property page
BOOL CPage1::OnInitDialog ()
{
bEditFocus = FALSE;
strFilter = "*.*";
GetCurrentDirectory ();
ShowList ();
return CDialog::OnInitDialog ();
}
void CPage1::GetCurrentDirectory ()
{
PTSTR pDir = new char[MAX_PATH];
::GetCurrentDirectory( MAX_PATH, pDir );
strDirectory = pDir;
if(strDirectory.Right( 1 ) != "\\")
strDirectory += "\\"; // Append backslash
delete [] pDir;
}
void CPage1::ShowList ()
{
PTSTR pDir = new char[MAX_PATH];
lstrcpy( pDir, strDirectory );
lstrcat( pDir, strFilter );
DlgDirList( pDir, IDC_LIST, IDC_DIRPATH, DDL_ALL );
delete [] pDir;
}
BEGIN_MESSAGE_MAP (CPage1, CPropertyPage)
ON_EN_SETFOCUS (IDC_EDIT1, OnEditGainFocus)
ON_EN_KILLFOCUS (IDC_EDIT1, OnEditLoseFocus)
ON_BN_CLICKED(IDC_BUTTON1, OnUp1Level)
ON_LBN_SELCHANGE (IDC_LIST, OnSelChange)
END_MESSAGE_MAP ()
void CPage1::OnEditGainFocus ()
{
bEditFocus = TRUE;
}
void CPage1::OnEditLoseFocus ()
{
bEditFocus = FALSE;
GetDlgItemText( IDC_EDIT1, strFilter );
ShowList ();
}
void CPage1::OnUp1Level ()
{
// If Enter pressed in edit control, refresh list
if (bEditFocus)
{
GetDlgItemText( IDC_EDIT1, strFilter );
ShowList ();
}
// Else go up one directory level
else
{
// When strDirectory == "d:\", we're already at root
if (strDirectory.Right( 2 ) != ":\\")
{
// Remove '\' at end of string
strDirectory.GetBufferSetLength( strDirectory.GetLength() - 1 );
strDirectory.ReleaseBuffer ();
// Find last '\' and truncate strDirectory string
int cLastSlash = strDirectory.ReverseFind( '\\' );
if (cLastSlash != -1)
{
strDirectory.GetBufferSetLength( cLastSlash + 1 );
strDirectory.ReleaseBuffer ();
ShowList ();
}
}
}
}
void CPage1::OnSelChange ()
{
char szItem[MAX_PATH];
char *pItem = szItem;
int i;
i = SendDlgItemMessage( IDC_LIST, LB_GETCURSEL, 0, 0 ); SendDlgItemMessage( IDC_LIST, LB_GETTEXT, i, (LPARAM) szItem ); // We're interested only in drives [-d-] or subdirectories [subdir] if (szItem[0] == '[') { if (lstrcmp( szItem, "[..]" )) // Ignore parent directory "[..]" { pItem++; // Skip past first bracket '[' // If drive, change "[-d-]" to "d:" |
||
---|---|---|
if (pItem[0] == '-' { |
&& |
pItem[2] == '-') |
pItem++; |
// Skip past first hyphen '-' |
pItem[1] = ':'; // Overwrite second '-' with ':'
pItem[2] = '\0'; // Truncate string
strDirectory = pItem; // New directory
}
// If subdir, change "[subdir]" to "subdir"
else
{
i = lstrlen( szItem );
pItem[i-2] = '\0'; // Overwrite ']' to truncate
strDirectory += pItem; // Append new subdirectory
}
strDirectory += "\\"; // Append backslash
ShowList (); // Refresh list
}
}
}
void CPage1::DoDataExchange( CDataExchange* pDX )
{
CPropertyPage::DoDataExchange( pDX );
DDX_Text( pDX, IDC_EDIT1, strFilter );
DDV_MaxChars( pDX, strFilter, 128 );
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage2 property page
BOOL CPage2::OnInitDialog ()
{
CSpinButtonCtrl* spin;
// Initialize variables
nAnyDate = 0;
PrevDays = 1;
PrevMonths = 1;
timeMin = 0;
timeMax = CTime::GetCurrentTime();
// Set limits of spin buttons
spin = (CSpinButtonCtrl *) GetDlgItem( IDC_SPIN1 );
spin->SetRange( 1, 100 ); // Within x months
spin = (CSpinButtonCtrl *) GetDlgItem( IDC_SPIN2 );
spin->SetRange( 1, 365 ); // Within x days
return CDialog::OnInitDialog ();
}
void CPage2::DoDataExchange( CDataExchange* pDX )
{
CPropertyPage::DoDataExchange( pDX );
DDX_DateTimeCtrl( pDX, IDC_DATETIME1, timeMin);
DDX_DateTimeCtrl( pDX, IDC_DATETIME2, timeMax);
DDX_Radio( pDX, IDC_RADIO1, nAnyDate );
DDX_Text( pDX, IDC_EDIT1, PrevMonths );
DDX_Text( pDX, IDC_EDIT2, PrevDays );
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
// CPage3 property page
BOOL CPage3::OnInitDialog ()
{
CSpinButtonCtrl* spin;
// Initialize variables
nAnySize = 0;
MinSize = 0;
MaxSize = 100;
// Set limits of spin buttons
spin = (CSpinButtonCtrl *) GetDlgItem( IDC_SPIN1 );
spin->SetRange( 0, 9999 ); // Min size
spin = (CSpinButtonCtrl *) GetDlgItem( IDC_SPIN2 );
spin->SetRange( 1, 9999 ); // Max size
return CDialog::OnInitDialog ();
}
void CPage3::DoDataExchange( CDataExchange* pDX )
{
CPropertyPage::DoDataExchange( pDX );
DDX_Radio( pDX, IDC_RADIO1, nAnySize );
DDX_Text( pDX, IDC_EDIT1, MinSize );
DDX_Text( pDX, IDC_EDIT2, MaxSize );
}
该 程 序 的 InitInstance 函 数 首 先 创 建 一 个 ClistSheet 对 象 , 该 对 象 是 从 MFC 的
CPropertySheet 类 中 派 生 出 来 的 。 DoModel 成 员 函 数 用 来 显 示 属 性 表 :
CListSheet sh( “ Directory List” ); // Make propsheet object sh.DoModal (); // and display dialog
当 该 对 象 的 OnInitDialog 函 数 获 得 控 制 的 时 候 ,它 向 系 统 菜 单 添 加 一 个 调 用 该 程序 的 About 框 的 命 令 。然 后 删 除 不 需 要 的 Apply 按 钮 , 这 个 按 钮 是 框 架 把 它 放 在对 话 中 的 。 OnInitDialog 函 数 还 演 示 了 基 于 对 话 的 应 用 程 序 是 如 何 设 置 两 个 图 标图 像 的 , 一 个 16 × 16 像 素 的 小 图 像 作 为 对 话 标 题 栏 上 的 应 用 程 序 图 标 , 32 × 32 像 素 的 大 图 像 将 出 现 在 About ( 关 于 ) 框 中 。 两 个 图 像 都 在 项 目 的 D irList.ico 文件 之 中 。MFC 框 架 在 创 建 应 用 程 序 窗 口 时 将 自 动 抽 取 大 图 像 , 因 此 , D irList1 必须 通 过 调 用 第 4 章 中 介 绍 的 Load Image API 函 数 来 自 己 调 用 小 图 像 :
// Set the 16-by-16 icon image
HICON hIcon = (HICON) ::LoadImage( DirLsitApp.m_hInstance,
MAKEINTRESOURCE( IDI_APPICON ),
IMAGE_ICON,16,16,LR_DEFAULTCOLOR );
SetIcon( hIcon, FALSE );
在 这 种 情 况 下 , 调 用 LoadImage 是 必 要 的 , 因 为 LoadIcon 函 数 只 能 正 确 识 别 32
× 32( 或 更 多 ) 像 素 的 图 像 , 一 个 尺 寸 与 SM_CXICON 和 SM_CYICON 系 统 计 量值 相 匹 配 的 图 像 。 向 SetIcon 函 数 传 递 一 个 参 数 值 FALSE 可 能 把 小 的 16 × 16 图像 设 置 为 应 用 程 序 图 标 。
就 其 本 身 而 言 , ClistSheet 对 象 是 一 个 空 的 对 话 窗 口 。 ClistSheet 构 造 器 通 过 调 用AddPage 成 员 函 数 来 添 加 三 个 属 性 页 。AddPage 将 指 针 指 向 CPropertyPage 对 象 , 该 对 象 是 通 过 向 CPropertyPage 基 本 初 始 化 程 序 传 递 对 话 标 识 符 而 创 建 的 。 例如 , 下 面 是 DirList1 为 属 性 表 的 第 一 页 声 明 CPropertyPage 对 象 的 代 码 :
public:
CPage1 ():CPropertyPage(IDD_PAGE1) {}
AddPage 函 数 负 责 将 对 话 资 源 转 换 成 带 有 选 项 卡 的 属 性 页 ,该 选 项 卡 上 包 含 有 对话 标 题 , 例 如 Location 和 Size。
当 准 备 显 示 第 一 页 的 时 候 , 它 的 CPage1::OnInitDialog 函 数 调 用
GetCurrentDirectory API 函 数 , 向 当 前 路 径 添 加 *.* 过 滤 器 , 并 且 调 用 D lgDirList ,
将 当 前 的 目 录 列 表 写 到 列 表 框 之 中 。 StrFilter 字 符 串 包 含 有 用 户 可 以 通 过 编 辑 控件 改 变 的 过 滤 器 。 程 序 最 有 趣 的 部 分 在 CPage1::OnSelChange 函 数 中 , 当 用 户 选中 了 列 表 框 中 一 个 项 目 的 时 候 , 该 函 数 便 得 到 控 制 权 。
如 果 用 户 选 中 了 一 个 文 件 名 ,函 数 将 忽 略 这 个 选 择 。如 果 选 中 的 项 目 是 磁 盘 驱 动器 , 那 么 驱 动 器 目 标 将 代 替 StrDirectory 中 的 路 径 , 然 后 成 为 字 符 串 d:\, 其 中 d 是 所 选 中 的 驱 动 器 符 号 。 在 列 表 框 中 选 定 了 一 个 子 目 录 , 将 把 子 目 录 名 添 加 到StrDirectory 中 的 路 径 。 当 路 径 改 变 的 时 候 , OnSelChange 将 调 用 ShowList 来 显示 新 路 径 的 目 录 列 表 。OnSelChange 将 按 照 CWnd::DlgDirList 在 列 表 框 中 写 该 文件 名 、驱 动 器 和 子 目 录 的 方 式 来 在 它 们 之 间 进 行 区 分 。驱 动 器 符 号 包 含 在 方 括 号和 边 字 符 之 中 , 例 如 [-a-] 或 [-c-]。 子 目 录 包 括 在 没 有 连 字 符 的 方 括 号 之 中 。 文 件名 没 有 括 号 或 连 字 符 。
虽 然 调 用 DlgDirList 添 加 目 录 列 表 具 有 一 定 的 方 便 性 ,但 该 技 术 还 存 在 着 两 个 严重 的 缺 陷 。 首 先 , 目 录 列 表 不 吸 引 人 , 并 没 有 达 到 当 前 的 W indows 标 准 。 其 次 , D lgDirList 只 有 在 W indows NT 下 才 能 识 别 长 文 件 名 。 出 于 这 两 方 面 的 考 虑 , 我们 不 得 不 完 全 放 弃 列 表 框 , 而 来 试 一 试 其 他 东 西 。 当 我 们 创 建 了 一 个 从 MFC 的CListView 中 派 生 出 来 的 新 类 ,并 将 其 添 加 到 Visual C++ 中 叫 做 Gallery 的 组 件 集时 , 我 们 再 来 做 这 件 事 。
但 是 , 目 前 有 另 一 个 问 题 比 Gallery 更 加 迫 切 。 本 章 中 已 完 成 的 一 些 工 作 可 能 就变 得 不 必 要 了 , 或 者 至 少 是 这 样 , 它 可 以 得 到 简 化 。 你 可 能 会 记 起 , 在 创 建
MFcTree 项 目 时 , 我 们 为 Mfclagh 和 M fcDlg.cpp 源 文 件 编 写 了 存 根 函 数 , 并 且将 项 目 手 工 插 入 到 一 个 消 息 映 射 之 中 。 这 些 任 务 可 以 在 ClassWizard 中 很 容 易 地进 行 处 理 。 ClassWizard 是 对 话 编 辑 器 的 天 然 伙 伴 ; 使 用 编 辑 器 来 设 计 对 话 , 使ClassWizard 可 以 生 成 运 行 该 对 话 的 源 代 码 。 下 一 章 将 显 示 如 何 去 做 。