致 谢 - 图1

美 国 微 软 出 版 社 授 权 的 标 准 、 权 威 、 完 整 的 中 文 图 书

M icrosoft Visual C++ 6.0

程 序 员 指 南

〔 美 〕 Beck Zaratian 著希 望 图 书 创 作 室 译

希 望 图 书 创 作 室 审 校

本 书 配 套 光 盘 包 括 两 部 分 内 容 :

  1. . 本 书 英 文 原 版 附 带 光 盘 中 的 例 子 代 码 及 可 执 行 程 序

  2. . 与 本 书 配 套 的 中 文 版 电 子 书

北 京 希 望 电 脑 公 司 出 品

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 程 序 :

  1. 在 W indows 任 务 栏 上 单 击 Start 按 钮 并 选 择 Run 命 令 。

  2. 在 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 。 该 程 序外 观 如 下 图 所 示 。

致 谢 - 图2

Index 窗 口 中 的 四 个 组 合 框 每 一 个 接 受 一 个 单 词 。 这 些 单 词 可 以 组 成 一 个 短 语 ,

如 “ Active Template Library ”, 或 仅 仅 是 指 定 一 些 一 同 出 现 在 同 一 段 或 同 一 页 的毫 无 关 联 的 几 个 词 。 程 序 也 能 搜 索 单 词 的 复 数 和 由 -ed-ing 形 成 的 派 生 词 , 并能 考 虑 到 单 词 拼 写 上 细 微 的 变 化 。 例 如 , 搜 索 单 词 edithandledebug , 程 序同 时 会 找 出 editshandlingdebugged 的 出 现 位 置 来 。 搜 索 单 词 的 大 小 写 无 关紧 要 , 不 常 见 的 简 写 可 能 会 导 致 意 外 的 匹 配 。 例 如 , 当 搜 索 只 取 首 字 母 的 缩 写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++ 的 每 件 事 情 时 , 才 会 峰 回 路 转 , 出 现 一 番 新 的 景 色 。 但 是 , 它 的 界 面 是 智 能 化 的 , 而 且 , 而 且 非 常 宽 容 , 它 鼓 励你 去 实 践 , 实 践 总 是 最 好 的 教 师 。

致 谢 - 图3

图 1-1 Visual C++ 主窗口的典型视图

本 章 是 一 个 起 点 , 它 介 绍 Visual C++ 的 环 境 外 壳 , 并 描 述 开 发 项 目 时 遇 到 的 界 面和 窗 口 。 我 们 不 急 于 在 本 章 中 讨 论 单 独 的 工 具 和 菜 单 命 令 , 因 为 在 后 面 的 几 章中 ,都 介 绍 了 菜 单 和 工 具 栏 及 它 们 包 含 的 各 种 各 样 的 命 令 。同 时 ,Developer Studio 还 充 当 Visual J++ 和 Visual InterDev 的 主 环 境 , 但 这 里 , 我 们 只 集 中 讨 论 这 个 环境 是 如 何 应 用 到 Visual C++ 和 C/C++ 项 目 上 的 。

工 具 栏 和 菜 单

Visual C++ 带 有 一 个 预 先 定 义 好 的 工 具 栏 集 , 单 击 它 们 便 可 以 访 问 它 们 。 如 果 找不 到 需 要 的 工 具 ,可 以 用 自 己 设 计 的 定 制 工 具 栏 来 增 大 工 具 栏 集 。 每 个 工 具 栏 都由 工 具 栏 的 标 题 栏 上 的 名 字 标 识 :

致 谢 - 图4

正 如 下 面 部 分 所 描 述 的 那 样 , 工 具 栏 经 常 被 定 位 在 某 个 位 置 上 , 这 时 标 题 栏 消失 。例 如 ,图 1-1 显 示 了 Standard 、Build 和 Edit 工 具 栏 定 位 在 Visual C++ 主 窗 口的 顶 端 时 的 样 子 。 工 具 栏 的 安 排 由 你 决 定 。 你 可 以 在 屏 幕 四 周 移 动 工 具 栏 , 通 过拖 曳 边 框 来 调 整 它 们 的 矩 形 形 状 , 并 使 任 何 一 套 工 具 可 见 或 隐 藏 。 你 可 能 愿 意 让某 些 工 具 栏 ( 如 Standard 和 Build ) 一 直 都 是 可 见 的 , 至 于 其 他 工 具 栏 , 通 常 只在 你 工 作 在 需 要 它 们 的 窗 口 中 时 , 才 变 得 可 见 。 例 如 , 在 默 认 设 置 中 , Debug 工具 栏 只 在 调 试 过 程 中 才 是 可 见 的 。Colors 和 Graphics 工 具 栏( 将 在 第 4 章 中 讨 论 ) 仅 在 图 形 编 辑 器 中 才 是 可 见 的 , 因 为 这 是 你 需 要 它 们 的 唯 一 地 方 。

致 谢 - 图5

图 1-2 在 Customize ( 自 定 义 ) 对 话 框 中 打 开 和 关 闭 工 具 栏

图 1-2 显 示 了 Customize ( 自 定 义 ) 对 话 框 中 包 含 的 工 具 栏 名 称 列 表 , 这 里 你 通过 单 击 复 选 框 来 调 整 工 具 栏 的 可 见 性 是 打 开 或 是 关 闭 。 在 Tools ( 工 具 ) 菜 单 中单 击 Customize ( 自 定 义 ) 命 令 即 可 打 开 这 个 对 话 框 ( 第 13 章 对 Customize ( 自定 义 ) 对 话 框 有 更 多 的 叙 述 )。

当 鼠 标 停 留 在 工 具 栏 按 钮 的 上 面 时 ,按钮凸起 。主 窗 口 的 底 端 的 状 态 栏 显 示 了 对按 钮 的 简 短 描 述 , 并 且 , 如 果 光 标 停 留 时 间 长 一 些 , 就 会 出 现 一 个 小 的 弹 出 式 的“ 工 具 提 示 ” 窗 口 , 它 包 含 了 按 钮 的 名 字 。 如 果 需 要 的 话 , Visual C++ 甚 至 可 以显 示 放 大 的 工 具 栏 :

致 谢 - 图6

工 具 提 示 和 放 大 的 选 项 都 是 在 图 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 所 示 。

致 谢 - 图7

图 1-3 使用 Docking View ( 停 靠 视 图 ) 命 令 切 换 窗 口 的 停 靠 模 式

若 关 掉 窗 口 的 停 靠 特 征 , 在 下 面 几 个 方 面 影 响 窗 口 :

  • 窗 口 就 像 一 个 普 通 的 文 档 窗 口 , 标 题 栏 上 有 最 小 化 、

    最 大 化 和 关 闭 窗口 的 按 钮 。

  • 从 Window ( 窗 口 ) 菜 单 中 选 择 Cascade( 层 叠 ) 或 Tile( 平

    铺 ) 命 令时 , 窗 口 同 其 他 打 开 的 文 档 窗 口 一 起 排 列 位 置 。

  • 窗 口 不 能 移 到 Visual C++ 主 窗 口 用 户 区 的 外 面 , 当 它 处

    在 停 靠 模 式 下时 是 可 以 的 。

  • 输 入 焦 点 移 到 该 窗 口 上 时 , 它 可 以 由 W indow ( 窗 口 )

    菜 单 上 的 Close

( 关 闭 ) 命 令 关 闭 。 否 则 , Close ( 关 闭 ) 命 令 不 能 影 响 停 靠 模 式 下 的窗 口 , 即 使 它 拥 有 焦 点 。

窗 口 或 工 具 栏 被 定 位 后 , 凸 起 的 硬 节( 有 时 称 为 把 手 ) 出 现 在 窗 口 的 顶 端 或 左 边界 , 如 图 1-4 所 示 。 双 击 把 手 使 窗 口 变 成 浮 动 的 ; 双 击 浮 动 窗 口 或 工 具 栏 的 标 题栏 , 使 它 回 到 原 来 的 位 置 。也 可 以 通 过 把 手 来 把 窗 口 拖 动 到 另 一 个 固 定 的 或 浮 动的 位 置 。

在 Visual C++ 中 创 建 的 窗 口 排 列 , 将 在 项 目 的 整 个 过 程 中 维 持 , 或 直 到 你 改 变 窗口 排 列 方 式 。 下 一 次 打 开 项 目 时 , 窗 口 像 上 次 离 开 时 的 样 子 排 列 。 然 而 , 在 环 境中 运 行 的 实 用 程 序 的 窗 口 并 不 遵 守 这 些 规 则 。这 些 窗 口 既 不 是 文 档 窗 口 , 也 不 是停 靠 窗 口 , 它 们 的 特 征 是 由 实 用 程 序 决 定 的 , 而 不 是 由 Visual C++ 决 定 。

致 谢 - 图8

图 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 ( 标 准 ) 工 具 栏 上 的 按 钮 来 激 活 , 这 些 按 钮 按 下 后 会 使 窗 口 可 见 或 消 失 。

致 谢 - 图9

图 1-5 显示 Workspace ( 工 作 空 间 ) 和 Outpu t( 输 出 ) 窗 口 , 工具按钮在 Standard (标准)工

具 栏 上

除 使 用 工 具 栏 按 钮 外 ,还 可 以 用 下 列 方 法 来 隐 藏 Workspac e( 工 作 空 间 )和 Output

( 输 出 ) 窗 口 :

  • 如 果 窗 口 是 浮 动 的 , 单 击 窗 口 的 标 题 栏 上 的 Close ( 关

    闭 ) 按 钮 。

  • 如 果 窗 口 是 固 定 的 , 单 击 窗 口 把 手 上 面 或 右 面 的 X 形

    按 钮 ( 图 1-4 )。

  • 在 窗 口 内 任 何 地 方 右 击 , 打 开 上 下 文 相 关 菜 单 , 选 择

    H ide( 隐 藏 ) 或Close( 关 闭 ) 命 令 。 菜 单 上 出 现 哪 个 命 令 取 决 于 窗 口 的 停 靠 模 式 是 打开 的 还 是 关 闭 的 , 但 两 个 命 令 有 同 样 的 效 果 。

  • 如 果 窗 口 的 停 靠 特 征 被 禁 止 , 单 击 窗 口 把 焦 点 移 到 它

    上 面 , 然 后 从

W indow ( 窗 口 ) 菜 单 中 选 择 Close ( 关 闭 ) 命 令 。

Workspace ( 工 作 空 间 ) 窗 口 显 示 了 项 目 各 个 方 面 的 信 息 。 在 窗 口 底 端 选 择 相 应的 选 项 卡 来 显 示 项 目 的 类 、 资 源 、 数 据 源 和 文 件 的 列 表 。 在 窗 口 中 单 击 小 的 加 号

( + ) 或 减 号( -) 来 展 开 或 折 叠 列 表 。 例 如 , 展 开 类 的 列 表 会 显 示 出 成 员 函 数 的名 字 ,如 图 1-6 中 的 第 一 屏 所 示 。双 击 列 表 开 头 靠 近 文 件 夹 或 书 本 形 图 标 的 文 字 , 与 单 击 表 头 的 加 号 或 减 号 有 同 样 的 效 果 。

致 谢 - 图10

图 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 ( 调 试 ) 选 项 卡 中 。

致 谢 - 图11

图 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 查 看 器 中 :

致 谢 - 图12

在 线 帮 助 的 第 二 个 来 源 是 弹 出 式 消 息 , 在 这 个 环 境 中 的 许 多 对 话 框 中 都 可 以 使用 。 选 项 卡 和 偶 尔 的 提 示 会 尽 量 解 释 对 话 框 中 的 编 辑 框 和 按 钮 的 用 途 ,但 当 标 签说 明 不 充 分 时 , 总 可 以 通 过 下 列 几 种 方 法 之 一 来 寻 求 特 殊 控 件 的 更 多 解 释 :

  • 把 焦 点 移 到 该 控 件 上 , 并 按 F1 键 。 对 于 复 选 框 或 单 选

    按 钮 , 通 过 单 击来 给 它 焦 点 , 可 能 会 打 开 或 关 闭 一 个 开 关 选 项 。 如 果 你 不 希 望 这 种 结果 , 当 你 阅 读 完 帮 助 信 息 后 , 要 记 得 把 开 关 恢 复 到 原 来 的 设 置 。

  • 在 该 控 件 上 右 击 , 来 打 开 What ’ s This ?( 这 是 什 么 ) 弹

    出 式 按 钮 。 如 果

该 控 件 是 一 个 编 辑 框 , 右 击 该 控 件 的 标 签 文 本 , 比 右 击 编 辑 框 本 身 要更 好 一 些 。 单 击 What ’ s This ?( 这 是 什 么 ) 按 钮 , 将 显 示 该 控 件 的 帮 助文 本 。

  • 单 击 对 话 框 右 上 角 的 问 号 按 钮 , 然 后 单 击 要 了 解 的 控

    件 。

这 三 种 方 法 效 果 完 全 一 样 : 运 行 W inHlp32 , 来 显 示 一 个 如 图 1-8 所 示 的 简 明 的弹 出 式 消 息 。 单 击 鼠 标 或 按 任 意 键 时 , 这 些 消 息 就 消 失 了 。

致 谢 - 图13

图 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 的 关 键字 文 件 ,该 文 件 中 包 含 了 所 有 文 章 中 使 用 的 关 键 字 列 表 , 及 指 向 它 们 在 文 本 中 的位 置 的 指 针 。 以 这 种 方 法 编 辑 关 键 字 , 会 加 速 特 定 的 词 和 短 语 的 搜 索 过 程 , 一 会儿 , 我 们 就 可 以 看 到 这 一 点 。 创 建 关 键 字 文 件 是 一 次 性 , 只 需 要 几 分 钟 , 在 此 过程 中 出 现 动 画 消 息 , 会 告 诉 你 正 在 做 什 么 :

致 谢 - 图14

该 过 程 要 求 系 统 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 文 章 , 以 两 窗 格 显 示 。 这 两 个 窗 格 被 设 计 成 可 以 共同 工 作 , 左 边 的 允 许 为 你 希 望 阅 读 的 文 章 输 入 标 准 , 而 右 边 的 则 显 示 找 到 的 文章 。

致 谢 - 图15

图 1-9 通过 MSDN Library 应用程序来访问在线帮助

在 右 窗 格 中 , 每 次 都 出 现 主 题 , 它 通 过 超 文 本 链 接 web 连 接 到 其 他 的 相 关 主 题 。

超 文 本 链 接 也 称 超 级 链 接 , 它 是 文 本 中 一 些 特 殊 的 词 和 短 语 。 链 接 带 有 下 划 线 , 并 以 突 出 的 颜 色 显 示 , 这 使 得 它 们 能 很 快 被 识 别 。 当 光 标 移 动 到 MSDN 库 窗 口中 的 超 文 本 链 接 上 时 ,光 标 变 成 手 的 形 状( 图 1-10 )。在 链 接 上 单 击 ,会 从 M S D N 窗 口 中 清 除 掉 当 前 主 题 , 而 代 之 以 超 文 本 链 接 所 指 向 的 新 主 题 。这 个 效 果 很 像 在Internet 上 浏 览 Web 网 页 。

致 谢 - 图16

图 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 参 考 的 文 章 子 集 :

  1. 从 MSDN 的 Vie w( 查 看 )菜 单 中 选 择 Define Subse t( 定 义 子

    集 )命 令 。

  2. 在 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 ( 添 加 ) 按 钮 来 创 建 子 集 。

  3. 在 Define Subset( 定 义 子 集 ) 对 话 框 的 底 部 的 编 辑 框 中

    键 入 新 子 集 的名 字 , 然 后 单 击 Save ( 保 存 ) 和 Close ( 关 闭 ) 按 钮 。

使 用 在 线 帮 助 时 , 要 在 各 个 子 集 间 切 换 , 只 需 从 名 为 Active Subset ( 有 效 子 集 ) 的 下 拉 列 表 中 选 择 一 个 子 集 即 可 :

致 谢 - 图17

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( 显 示 ) 按 钮 , 均 可 在 对 话 框 中 打 开 一 篇 文 章 。

致 谢 - 图18

图 1-11 提供 MSDN 文章全面索引的 Index ( 索 引 ) 选 项 卡

Search ( 搜 索 ) 选 项 卡

M S D N 帮 助 文 件 集 不 仅 仅 是 被 动 的 , 它 还 包 含 一 个 搜 索 引 擎 , 该 引 擎 扫 描MSDNVS98.chw 关 键 字 文 件 , 来 确 定 哪 些 主 题 文 件 包 含 了 指 定 的 词 或 短 语 , 这个 过 程 称 为 全 文 本 搜 索 。 全 文 本 搜 索 从 M S D N 的 Search ( 搜 索 ) 选 项 卡 中 启 动

( 图 1-12 ), 它 允 许 你 寻 找 包 含 指 定 词 或 短 语 的 主 题 。 M S D N 搜 索 引 擎 是 非 常 优秀 的 , 它 能 理 解 词 的 派 生 、 通 配 符 、 布 尔 逻 辑 组 合 及 NEAR 运 算 符 。 尽 管 要 有效 地 使 用 这 些 特 征 , 要 求 认 真 地 考 虑 和 进 行 计 划 , 它 们 允 许 你 精 选 搜 索 参 数 , 来增 加 只 寻 找 你 最 感 兴 趣 的 那 些 主 题 的 机 会 。

致 谢 - 图19

图 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( 添 加 ) 按 钮 , 将 该 标 题 添 加 到 列 表 中 ; 双 击 列 表 中 的 一 个 标题 会 回 到 该 文 章 。

致 谢 - 图20

图 1-13 Favorites ( 收 藏 ) 选 项 卡 保 持 想要重新访问的文章列表

访 问 万 维 网

通 过 嵌 入 Internet Explorer 浏 览 器 , M S D N 可 以 接 触 到 其 他 Web 站 点 上 的 信 息 来源 , 不 论 它 们 在 哪 里 。 文 章 可 以 包 含 Internet 地 址 ( 通 用 资 源 定 位 符 或 URL )作为 超 文 本 链 接 , 因 此 , MSDN 可 以 像 打 开 其 他 任 何 库 中 的 文 章 一 样 来 打 开 一 个Web 网 页 。

致 谢 - 图21

图 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 ( 应 用 程 序 向 导 ) 生 成 的 项 目 文 件中 生 成 的 一 个 典 型 的 应 用 程 序 ,它 只 有 一 个 窗 口 。这 个 例 子 中 不 需 要 再 做 其 他 的编 程 工 作 。

致 谢 - 图22

图 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 ( 应用 程 序 向 导 ) 项 目 :

致 谢 - 图23

单 击 New ( 新 建 ) 显 示 New ( 新 建 ) 对 话 框 的 Projec t( 项 目 ) 选 项 卡 , 其 中 列出 了 Visual C++ 中 的 向 导 。要 运 行 向 导 来 为 一 个 典 型 的 Windows 应 用 程 序 创 建 项目 , 选 择 标 有 MFC AppWizard(exe) 的 图 标 , 如 图 2-2 所 示 。现 在 我 们 集 中 讨 论 这个 AppWizard ( 应 用 程 序 向 导 )。 通 过 MFC AppWizard ( 应 用 程 序 向 导 ) (dll) 图标 调 用 的 AppWizard ( 应 用 程 序 向 导 ), 为 你 建 立 动 态 链 接 库 开 发 项 目 , 下 一 章我 们 将 讨 论 这 个 问 题 。

致 谢 - 图24

图 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 ( 文 档 /视 图 结 构 支 持 ) 复 选 项 禁 用 即 可 。

致 谢 - 图25

图 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 ( 文 件 ) 菜 单 的 样 子 。

致 谢 - 图26

图 2-4 在三种不同的语言中的应用程序的 File( 文 件 ) 菜 单

步 骤 2 : 数 据 库 支 持

在 图 2-5 中 所 示 的 AppWizard ( 应 用 程 序 向 导 ) 的 第 二 步 中 , 要 求 你 提 供 项 目 所需 要 的 数 据 库 支 持 种 类 。 这 一 步 和 下 面 的 步 骤 假 定 你 在 第 一 步 中 选 择 了 带 文 档 / 视 图 支 持 的 Single Document ( 单 文 档 ) 或 Multiple Documents ( 多 文 档 ) 选 项 。

致 谢 - 图27

图 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( 数 据 库 选 项 ) 对 话 框 。

致 谢 - 图28

图 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 说 明 了 “ 使 用 者 ” 如 何 同“ 供 应 者 ”( 而 不 是 同 原 始 的 数 据 源 创 立者 ) 通 信 。

致 谢 - 图29

图 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 ( 应 用 程 序 向 导 ) 添 加 到 程 序 中 的 复 合 文 档 支 持 的 类 型 。 下 面 是 这 些 选 项 的 说 明 :

致 谢 - 图30

图 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 创 建 的 文 档 。

如 果 你 希 望 你 的 包 容 器 或 服 务 器 程 序 能 串 行 化 复 合 数 据 , 也 就 是 说 ,把 文 档 和 对象 保 存 到 磁 盘 上 ,打 开 单 选 按 钮 ,来 请 求 对 复 合 文 件 的 支 持 。尽 管 从 概 念 上 来 说 , 复 合 文 档 是 单 纯 的 文 档 , 实 际 上 , 它 代 表 不 同 文 件 的 组 合 , 一 个 文 件 包 含 文 档 , 而 其 他 文 件 则 包 含 链 接 到 文 档 的 对 象 。当 保 存 复 合 文 档 时 ,包 容 器 负 责 把 自 己 的文 档 对 象 写 到 磁 盘 上 。然 后 它 给 服 务 器 传 递 一 个 请 求 , 来 把 包 容 器 正 在 使 用 的 各个 对 象 保 存 到 同 一 个 “ 存 储 器 ” 中 。

致 谢 - 图31

图 2-9 Active 文 档 包 容 器 和 服 务 器 在 一 起 工 作 的 例 子

第 三 步 的 对 话 框 底 部 的 两 个 复 选 项 询 问 ,是 否 要 求 Automation 和 ActiveX 控 件 支持 。 默 认 情 况 下 , AppWizard ( 应 用 程 序 向 导 ) 激 活 ActiveX Controls ( ActiveX 控 件 ) 选 项 ; 如 果 程 序 不 会 嵌 入 ActiveX 控 件 , 请 清 除 该 复 选 项 。 这 个 决 定 并 不是 不 可 取 消 的 , 以 后 , 你 可 以 轻 易 通 过 包 含 一 行 代 码 , 来 向 MFC 程 序 中 添 加ActiveX 控 件 支 持 。 要 了 解 如 何 向 已 存 在 的 MFC 程 序 中 添 加 ActiveX 控 件 支 持 ,

请 参 阅 第 8 章 。

步 骤 4 : 用 户 界 面 特 征

在 图 2-10 中 所 示 的 AppWizar d( 应 用 程 序 向 导 )的 第 四 步 中 可 以 控 制 AppWizard

( 应 用 程 序 向 导 ) 为 程 序 创 建 哪 些 用 户 界 面 元 素 。

致 谢 - 图32

图 2-10 在 AppWizard ( 应 用 程 序 向 导 ) 的 第 四 步 中 选 择 程 序 的 用 户 界 面 特 征

AppWizard ( 应 用 程 序 向 导 ) 自 动 为 程 序 主 窗 口 的 菜 单 系 统 、 工 具 栏 及 状 态 栏 生成 代 码 和 数 据 。 工 具 栏 包 含 与 菜 单 命 令 效 果 一 样 的 按 钮 , 而 状 态 栏 则 显 示 命 令 和工 具 栏 按 钮 的 描 述 信 息 。当 光 标 在 菜 单 命 令 或 工 具 栏 按 钮 上 停 留 一 段 时 间 后 ,帮助 信 息 会 出 现 在 状 态 栏 上 , 如 下 图 所 示 :

致 谢 - 图33

没 有 选 中 命 令 时 , 状 态 栏 显 示 诸 如“ 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( 帮 助 主 题 ) 对 话 框 来 寻 找 想 得 到 的 主 题 帮 助 。

致 谢 - 图34

图 2-11 Help Topics ( 帮 助 主 题 ) 对 话 框

AppWizar d( 应 用 程 序 向 导 )在 程 序 的 工 具 栏 上 也 添 加 了 一 个 Hel p( 帮 助 ) 按 钮 , 它 同 Developer Studio 对 话 框 右 上 角 的 小 问 号 按 钮 相 类 似 。 单 击 Help ( 帮 助 ) 按

钮 , 会 把 鼠 标 形 状 改 变 为 一 个 带 问 号 的 箭 头 。 然 后 , 用 户 可 以 单 击 程 序 窗 口 的 任何 部 分 , 包 括 菜 单 命 令 、 状 态 栏 和 工 具 栏 按 钮 :

致 谢 - 图35

调 用 Help ( 帮 助 ) 工 具 , 将 引 起 程 序 执 行 WinHlp32 , 它 显 示 一 个 描 述 所 单 击 元素 的 帮 助 窗 口 。 例 如 , 通 过 像 上 面 所 说 的 那 样 单 击 Save 按 钮 以 获 取 帮 助 时 , 会显 示 图 2-12 所 示 的 帮 助 窗 口 。

通 过 描 述 其 他 程 序 自 身 的 特 征 ,可 以 加 强 帮 助 系 统 , 在 一 个 能 识 别 多 信 息 文 本 格式 的 字 处 理 程 序 中 加 载 AfxCore.rtf 。 不 要 使 用 W indows 所 带 的 WordPad 实 用 程序 。 尽 管 WordPad 能 读 取 多 信 息 文 本 文 档 , 但 它 不 保 存 帮 助 编 译 器 所 需 要 的 信息 。多 信 息 文 本 文 档 也 是 以 普 通 的 ASCII 格 式 写 的 ,因此,在紧急时候你可以通

过 文 本 编 辑 器 来 作 小 小 的 改 动 。

创 建 自 己 的 帮 助 文 本 的 第 一 步 是 搜 索 字 符 串 “ <<YourApp>> ”, 并 用 应 用 程 序 名来 取 代 它 。 双 击 文 档 中 的 角 括 号 (<<>> ), 会 装 入 提 示 你 应 添 加 的 文 本 类 型 的 占 位符 文 本 。 用 新 的 文 本 来 取 代 提 示 和 角 括 号 。 去 除 应 用 程 序 不 用 的 所 有 主 题 , 并 从AppWizard ( 应 用 程 序 向 导 ) 放 在 文 件 中 的 文 本 中 取 出 对 重 要 格 式 的 提 示 。 文 件中 的 主 题 必 须 由 硬 分 页 符 分 隔 开 。

致 谢 - 图36

图 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 章 中 详 细 讨 论 这 些 字 符 串 。

致 谢 - 图37

对 话 框 的 第 二 页 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 库 。

致 谢 - 图38

图 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( 资 源 管 理 器 ) 形 式 的 应 用 程 序 的 外 观 :

致 谢 - 图39

左 边 窗 格 中 包 含 的 树 形 视 图 控 制 中 的 条 目 有 小 的 加 号 和 减 号 来 展 开 或 折 叠 列表 。应 用 程 序 通 过 在 窗 口 的 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 的 类 ) 外 的 所 有 类 输 入 一 个 新 的 名字 。 包 含 应 用 程 序 类 的 源 文 件 的 名 字 取 自 项 目 , 因 此 不 能 被 改 变 。

致 谢 - 图40

图 2-14 在 AppWizard 的 第 六 步 中 指 定 类 名

单 击 Finish ( 完 成 ) 按 钮 后 , AppWizard ( 应 用 程 序 向 导 ) 显 示 一 个 摘 要 表 , 其中 列 出 了 所 选 的 项 目 特 征 ( 图 2-15) 。 这 个 摘 要 是 你 取 消 项 目 的 最 后 机 会 。 单 击O K ( 确 定 ) 会 使 AppWizard ( 应 用 程 序 向 导 ) 在 摘 要 表 底 部 所 列 的 目 录 下 创 建项 目 。

致 谢 - 图41

图 2-15 在 AppWizard (应用程序向导)中选择的项目特征列表

用 AppWizard ( 应 用 程 序 向 导 ) 来 创 建 DLL 文 件

如 果 你 要 开 发 一 个 动 态 链 接 库 , 而 不 是 一 个 普 通 的 W indows 应 用 程 序 , 在 New

( 新 建 ) 对 话 框 中 选 择 MFC AppWizard(dll) 图 标 ( 参 见 图 2-3) 。 这 个 特 殊 的AppWizar d( 应 用 程 序 向 导 ) 仅 显 示 图 2-16 所 示 的 一 个 步 骤 , 它 询 问 诸 如 你 的 动态 链 接 库 应 如 何 链 接 到 MFC 之 类 的 信 息 。

致 谢 - 图42

图 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++ 按 字 母 顺 序 列 出 可 以 创建 的 文 件 类 型 。

致 谢 - 图43

图 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 中 简 要 列 出 了 使 用 文 本 编 辑 器 时 可 用 的 菜 单 命 令 。

致 谢 - 图44

图 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 ( 打 开 ) 按 钮 。

致 谢 - 图45

  • 按 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 ( 文 件 ) 菜 单 会 显 得 很 拥 挤

致 谢 - 图46

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 )。

致 谢 - 图47

图 3-3 View ( 查 看 ) 和 Window (窗口) 菜单

文 本 编 辑 器 的 文 档 窗 口 允 许 多 窗 格 显 示 ,可 以 将 同 一 文 档 的 一 个 、 两 个 或 四 个 不同 部 分 同 时 显 示 在 窗 口 上 。 图 3-4 就 是 同 一 文 档 的 四 窗 格 显 示 的 例 子 。

致 谢 - 图48

图 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 按 钮 。

致 谢 - 图49

  • 按 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 )。

致 谢 - 图50

图 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++ 文 本 编 辑 器 将 选 择权 交 给 了 你 , 可 按 以 下 步 骤 将 空 白 区 设 置 改 为 自 己 所 喜 好 的 类 型 :

  1. 选 Tools( 工 具 ) 菜 单 下 Options( 选 项 ) 命 令 。

  2. 单 击 Compatibility ( 兼 容 性 ) 选 项 卡 。

  3. 设 置 或 清 除 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 三 个 层 次 的 例 子 :

致 谢 - 图51

这 里 , 最 里 面 的 两 对 括 号 层 次 相 同 , 都 是 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 ( 下 一 个 书 签 ) 按 钮 , 也 会 得 到 同 样 的 结 果 , 如 下 图 所示 :

致 谢 - 图52

通 过 直 接 方 式 移 动 插 入 符 到 书 签 处 , 需 要 再 次 访 问 Boodmark ( 书 签 ) 对 话 框 。双 击 书 签 名 , 或 选 择 目 标 书 签 , 再 单 击 GoT o( 转 到 ) 按 钮 即 可 。也可以通过 Edit

( 编 辑 ) 菜 单 下 的 GoTo ( 转 到 ) 命 令 来 跳 到 某 个 有 名 书 签 处 。

具 体 来 说 , 有 名 书 签 是 一 个 32 位 量 , 用 以 记 录 文 本 中 一 个 特 定 位 置 。 当 在 书 签前 的 文 本 中 添 加 或 删 除 一 个 字 节 时 , 这 个 量 会 相 应 增 加 或 减 小 。 这 样 , 书 签 就 会继 续 指 向 其 目 标 , 文 本 怎 样 变 更 都 不 会 影 响 它 。 与 字 处 理 器 不 同 的 是 , 关 闭 文 档后 , Visual C++ 编 辑 器 不 将 有 名 书 签 保 留 在 文 档 中 , 因 为 额 外 字 符 会 使 编 辑 器 产生 混 乱 。

无 名 书 签

通 常 , 上 面 使 用 书 签 的 方 式 似 乎 有 些 大 材 小 用 。 当 想 定 义 这 样 一 个 书 签 时 , 它 标

志 源 代 码 的 一 处 地 方 , 在 编 辑 文 档 的 其 他 部 分 时 , 只 想 返 回 这 个 地 方 一 两 次 , 然后 它 就 没 用 了 , 在 这 种 情 况 下 , 有 名 书 签 就 不 是 很 方 便 了 。 此 时 , 为 方 便 起 见 , 可 使 用 一 个 无 名 书 签 。无 名 书 签 是 暂 时 的 ,当 取 消 它 或 关 闭 文 档 后 ,它 就 消 失 了 。而 且 , 无 名 书 签 只 标 志 一 行 , 而 不 是 一 个 精 确 位 置 。 当 插 入 符 跳 到 一 个 无 名 书 签处 时 , 插 入 符 自 动 置 于 该 行 开 头 。 如 果 删 除 被 标 志 的 行 , 则 书 签 也 将 被 删 除 。

无 名 书 签 的 好 处 是 , 它 易 于 设 置 , 删 除 更 简 便 。 要 使 用 一 个 无 名 书 签 , 只 需 将 插入 符 置 于 该 行 , 按 Ctrl+F2 , 或 单 击 标 有 旗 帜 的 按 钮 ( 如 图 示 ) 即 可 。

致 谢 - 图53

如 果 页 边 选 择( 本 章 后 面 部 分 将 会 描 述 ) 被 激 活 , 那 么 , 一 个 小 盒 子 图 标 就 会 显示 在 被 标 志 行 左 边 的 页 边 处 。 否 则 , 编 辑 器 将 以 不 同 颜 色 来 显 示 整 个 被 标 志 行 。

可 通 过 单 击 工 具 栏 按 钮 , 或 按 F2/Shift+F2 , 来 移 动 插 入 符 到 无 名 书 签 处 。每 按 一

次 , 插 入 符 将 向 前 或 向 后 移 到 下 一 个 书 签 处 , 无 论 该 书 签 是 有 名 书 签 , 还 是 无 名书 签 。

有 以 下 几 种 方 法 可 删 除 无 名 书 签 :

  • 将 插 入 符 移 到 此 行 , 再 按 Ctrl+F2 即 可 删 除 此 书 签 。

  • 按 Shift+Ctrl+F2 。 这 将 删 除 所 有 无 名 书 签 。

  • 不 去 理 它 。 当 文 档 关 闭 后 , 无 名 书 签 将 自 动 消 失 。

文 本 搜 索

Visual C++ 编 辑 器 提 供 了 三 种 文 本 搜 索 类 型 。 可 以 :

  • 在 已 打 开 的 文 档 中 搜 索 文 本 。

  • 在 已 打 开 的 文 档 中 替 换 文 本 。

  • 在 磁 盘 文 件 中 搜 索 文 本 。

前 两 种 类 型 在 文 本 编 辑 器 中 是 很 普 通 的 ,而 在 磁 盘 文 件 中 搜 索 文 本 ,则 是 一 个 不常 见 但 却 极 有 用 的 类 型 , 它 可 显 示 出 包 含 一 个 特 定 词 或 短 语 的 所 有 文 件 。以 下 我

们 将 详 细 说 明 这 三 个 类 型 。

在 打 开 的 文 档 中 搜 索 文 本

像 大 多 数 文 本 编 辑 器 一 样 , Visual C++ 编 辑 器 能 够 扫 描 文 档 , 并 找 出 给 定 单 词 或短 语 ( 我 们 称 之 为 目 标 字 符 串 ) 的 位 置 。 有 两 种 方 法 可 设 定 目 标 字 符 串 的 内 容 。最 方 便 的 方 法 是 使 用 标 准 工 具 栏 中 的 下 拉 框 , 如 下 图 示 :

致 谢 - 图54

在 下 拉 框 中 输 入 字 符 串 , 或 者 单 击 框 旁 的 箭 头 按 钮 , 再 从 列 表 中 选 择 以 前 输 入 的字 符 串 。 按 Enter 键 开 始 搜 索 。 当 编 辑 器 找 到 该 字 符 串 后 , 它 将 其 高 亮 显 示 , 并将 插 入 符 置 于 此 高 亮 字 符 串 的 首 字 符 旁 。 只 要 组 合 框 允 许 , 按 Enter 键 就 可 继 续按 下 一 个 已 给 出 的 目 标 字 符 串 搜 索 。 按 Esc 键 , 或 单 击 文 档 窗 口 的 任 何 部 分 , 就可 返 回 编 辑 模 式 。再 按 F3 或 Shift+F3 ,就 可 继 续 向 后 或 向 前 继 续 搜 索 。Visual C++ 提 供 了 这 些 命 令 的 工 具 按 钮 ,不 过 需 要 你 自 己 将 它 们 加 到 工 具 栏 中 。本 章 后 面 的“ 为 命 令 创 建 工 具 栏 按 钮 ” 一 节 将 说 明 怎 样 添 加 工 具 按 钮 。下 面 是 它 们 被 加 到 工具 栏 中 后 的 样 子 :

致 谢 - 图55

第 二 种 设 定 目 标 字 符 串 的 方 法 需 要 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 所 示 的 对 话 框 。 这 个 对 话 框 需 要 指 定 目 标 串 、 文 件 类 型 以 及 搜 索 过 程 所 在 的 文 件夹 。

致 谢 - 图56

图 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 下 , 成 员 表 是 如 何 在 完

成 输 入 之 前 找 到 匹 配 名 的 。

致 谢 - 图57

图 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 处 :

致 谢 - 图58

这 里 输 入 的 字 符 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 或 其 他 。

参 数 信 息

参 数 信 息 包 含 函 数 的 各 个 参 数 ,当 在 函 数 后 输 入 第 一 个 括 号 时 , 参 数 信 息 将 以 一

个 工 具 栏 式 窗 口 的 形 式 弹 到 屏 幕 上 。 这 种 工 具 栏 式 窗 口 像 一 个 屏 幕 提 示 , 显 示 出函 数 原 型 , 并 要 求 输 入 参 数 。 如 下 例 :

致 谢 - 图59

输 入 参 数 时 ,函 数 原 型 一 直 显 示 在 屏 幕 上 ,当 输 入 最 后 的 右 括 号 时 ,此 窗 口 消 失 。如 果 这 个 函 数 是 过 载 的 , 可 接 受 多 组 参 数 , 则 参 数 信 息 窗 口 将 显 示 一 个 函 数 原型 , 并 在 窗 口 左 端 给 出 数 字 , 来 说 明 此 函 数 有 多 少 过 载 的 版 本 。 按 Ctrl+PgU p, 或 单 击 参 数 信 息 窗 口 , 可 在 一 个 函 数 原 型 循 环 到 下 一 个 。 如 下 例 :

致 谢 - 图60

有 一 个 命 令 可 使 得 当 把 插 入 符 放 在 函 数 名 上 时 ,参 数 信 息 窗 口 会 自 动 显 示 在 屏 幕上 。 可 通 过 Edit( 编 辑 ) 菜 单 或 按 Ctrl+Shift+Spacebar 来 选 择 这 个 命 令 。 也 可 在文 本 中 用 右 击 一 个 函 数 名 , 来 打 开 上 下 文 菜 单 , 再 从 中 选 择 该 命 令 。 和 其 他 的Visual C++ 命 令 一 样 , 也 可 以 设 置 一 个 快 捷 键 来 激 活 参 数 信 息 工 具 。 本 章 后 面 的“ 未 结 合 命 令 ” 一 节 解 释 这 点 。

输 入 信 息

输 入 信 息 和 参 数 信 息 类 似 , 也 以 工 具 提 示 窗 口 出 现 , 它 包 含 有 关 函 数 和 变 量 的 信息 。 当 系 统 认 出 鼠 标 光 标 处 的 符 号 时 , 输 入 信 息 窗 口 将 自 动 显 示 出 来 , 当 把 光 标移 开 时 , 该 窗 口 将 自 动 消 失 。可 通 过 Edi t( 编 辑 ) 菜 单 、 上 下 文 菜 单 或 按 Ctrl+T , 来 调 用 输 入 信 息 功 能 。如 果 想 了 解 刚 输 入 的 , 或 刚 从 成 员 表 中 粘 贴 过 来 的 代 码 信息 , 那 么 , 最 后 一 种 方 法 是 很 方 便 的 。 当 插 入 符 位 于 一 个 函 数 名 上 时 , 输 入 信 息窗 口 和 参 数 信 息 窗 口 所 提 供 的 信 息 是 一 样 的 , 都 列 出 函 数 的 原 型 。 当 调 用 一 个 定义 的 类 型 时 , 窗 口 中 显 示 创 建 别 名 时 的 typedef 语 句 :

致 谢 - 图61

当 需 要 显 示 某 个 变 量 的 信 息 时 , 输 入 信 息 就 显 得 很 有 用 。 它 给 出 了 变 量 的 说 明 , 使 得 不 再 需 要 查 询 源 代 码 或 类 的 头 文 件 来 确 定 该 变 量 类 型 。 例 如 , 如 果 变 量indicators 的 类 型 不 清 楚 , 使 用 输 入 信 息 窗 口 , 就 会 立 即 看 到 它 是 一 个 整 数 数 组变 量 , 如 下 图 :

致 谢 - 图62

输 入 信 息 窗 口 以 及 其 他 类 似 的 弹 出 式 窗 口 也 许 会 使 你 感 到 眼 花 缭 乱 。 如 果 这 样 , 单 击 Tools( 工 具 ) 菜 单 下 的 Options( 选 项 ) 命 令 , 再 清 除 对 话 框 中 Editor( 编辑 器 ) 选 项 卡 下 的 相 应 复 选 框 即 可 ( 参 看 图 3-11 )。 通 过 相 应 的 快 捷 键 或 菜 单 命令 , 可 再 次 激 活 这 些 工 具 。

Advanced ( 高 级 ) 命 令

Edit( 编 辑 ) 菜 单 底 部 附 近 的 Advanced( 高 级 ) 命 令 提 供 了 一 个 选 项 集 合 , 它 们在 进 行 文 本 文 档 工 作 时 会 非 常 有 用 。 让 光 标 在 Advanced ( 高 级 ) 命 令 上 停 留 一会 儿 ,会 显 示 如 下 所 示 的 子 菜 单 。

致 谢 - 图63

正 如 你 所 看 到 的 那 样 , 菜 单 提 供 了 对 前 述 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 所 示 。

致 谢 - 图64

图 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 ( 指 定 ) 按 钮 后 , 快 捷 键 就 可 以 使 用 了 。

致 谢 - 图65

图 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 命 令 拖 到 同 一 个 工 具 栏 中 。

致 谢 - 图66

图 3-10 Visual C++ 提 供 新 工 具 栏 按 钮 的 图 标 选 择

因 为 WordUpperCase 和 WordLowerCase 命 令 没 有 预 定 义 的 图 标 , Button

Appearance ( 按 钮 外 观 ) 对 话 框 打 开 ( 图 3-10 ), 在 该 对 话 框 中 , 你 可 以 为 每 个新 的 按 钮 选 择 一 个 图 标 。 在 可 用 的 图 标 中 , 没 有 一 个 能 反 映 WordUpperCase 和WordLowerCase 的 不 寻 常 的 功 能 , 但 你 可 以 把 图 像 和 文 字 组 合 起 来 ,以 使 按 钮 的功 能 变 得 明 确 。 在 Button Appearanc e( 按 钮 外 观 ) 对 话 框 中 选 择 一 个 图 标 , 单 击Image And Tex t( 图 像 和 文 本 ) 单 选 钮 , 然 后 , 在 对 话 框 底 部 的 文 本 框 中 键 入 按钮 文 本 。 下 面 是 带 有 WordUpperCase 和 WordLowerCase 命 令 的 按 钮 的 新 工 具 栏的 样 子 :

致 谢 - 图67

未 结 合 命 令 不 只 是 用 于 文 本 编 辑 器 。下 一 章 描 述 如 何 用 同 样 的 方 法 来 通 过 快 捷 键或 工 具 栏 按 钮 来 执 行 图 形 编 辑 器 中 非 常 有 用 的 命 令 。 第 13 章 中 详 细 地 讨 论 了 在Visual C++ 环 境 中 创 建 工 具 栏 的 主 题 , 解 释 了 如 何 重 命 名 或 删 除 工 具 栏 , 如 何 从一 个 工 具 栏 中 向 另 一 个 工 具 栏 中 复 制 按 钮 , 以 及 如 何 定 制 按 钮 图 标 。

宏 的 基 础

你 可 以 把 一 个 结 合 命 令 当 作 一 个 预 定 义 的 宏 , 即 指 派 给 一 个 组 合 键 的 用 法 说 明 。环 境 也 允 许 你 创 建 用 于 文 本 编 辑 器 的 宏 , 你 可 以 通 过 记 录 按 键 和 鼠 标 单 击 活 动 , 来 把 它 们 组 合 成 普 通 的 Visual C++ 命 令 中 的 一 个 可 重 复 使 用 的 命 令 。你 可 以 像 执行 其 他 命 令 一 样 通 过 快 捷 键 、 菜 单 命 令 和 工 具 栏 按 钮 来 执 行 一 个 宏 。 实 际 上 , 宏同 普 通 的 结 合 命 令 几 乎 没 有 区 别 , 这 使 它 们 成 为 扩 展 环 境 功 能 的 一 个 高 级 方 法 。这 一 部 分 只 介 绍 一 下 宏 的 主 题 。 因 为 宏 用 在 整 个 Developer Studio 环 境 中 , 而 不只 是 用 于 文 本 编 辑 器 , 我 们 在 第 13 章 再 作 更 详 细 的 讨 论 。 现 在 , 我 们 可 以 简 单地 通 过 打 开 命 令 录 制 器 来 为 文 本 编 辑 器 创 建 一 个 宏 。

下 面 演 示 如 何 创 建 一 个 建 立 在 前 面 说 过 的 Untabify Selectio n( 解 除 制 表 符 转 换 选择 ) 命 令 上 的 宏 。 该 宏 把 命 令 的 功 能 扩 展 到 整 个 文 档 , 而 不 仅 仅 是 选 中 的 文 本 。首 先 关 闭 文 本 编 辑 器 中 所 有 的 文 档 , 来 防 止 改 变 已 有 的 文 本 , 然 后 通 过 按 下Ctrl+Shift+R ,或从 Tools( 工 具 ) 菜 单 中 选 择 Record Quick Macro( 快 速 录 制 宏 ) 命 令 , 来 开 始 录 制 新 宏 。 这 会 打 开 Recor d( 录 制 ) 工 具 栏 , 并 把 鼠 标 变 成 一 个 盒式 磁 带 形 的 图 像 , 这 表 示 Visual C++ 正 在 录 制 每 一 个 按 键 和 鼠 标 单 击 动 作 。 该 宏包 括 下 面 四 个 步 骤 :

  1. 在 Edit ( 编 辑 ) 菜 单 中 单 击 Select All ( 全 选 ) 命 令 来

    选 中 整 个 文 档 。

  2. 从 Edit( 编 辑 ) 菜 单 中 选 择 Advanced , 并 在 子 菜 单 中 单

    击 Untabify

Selection 命 令 。

  1. 按 下 Ctrl+Home 来 在 文 档 开 头 返 回 一 个 插 入 符 。

  2. 在 Recor d( 录 制 ) 工 具 栏 上 单 击 Stop Recordin g( 停 止 录

    制 ) 按 钮 来 结束 录 制 过 程 。

致 谢 - 图68

现 在 , 我 们 有 了 一 个 新 的 宏 。 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 ( 语 句 补 全 ) 选 项

  • 制 表 符 和 缩 进

  • 模 拟

  • 字 体

致 谢 - 图69

图 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 复 选 项 , 来 让 编辑 器 自 动 加 载 改 变 了 的 文 件 , 而 不 再 提 示 你 。

致 谢 - 图70

图 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 文 件 , 集 成 环境 会 警 告 你 , 当 编 译 这 个 项 目 时 , 这 个 文 件 将 不 会 被 编 译 , 如 下 所 示 .

致 谢 - 图71

然 而 , 一 个 项 目 可 以 有 任 何 数 目 的 资 源 脚 本 文 件 , 但 是 , 所 有 的 二 级 文 件 只 能 通过 #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 文 件 , 除 了 一 些 小 的 变 化 外 , 只 通 过 资 源 编辑 器 来 修 改 资 源 。

致 谢 - 图72

图 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 文件 里 。

致 谢 - 图73

图 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 来 调 用 的 :

致 谢 - 图74

虽 然 一 行 也 没 写 , 但 是 , 效 果 还 不 错 。 然 而 , 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( 完 成 ) 按 钮 , 接 受 为 空 项 目 选 择 的 默 认 设 置 。

致 谢 - 图75

如 果 你 已 经 运 行 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 显 示 后 一 种 选 择 。

致 谢 - 图76

图 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

致 谢 - 图77

图 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 键 时 选 择 的 命 令 。 下一 节 描 述 的 菜 单 编 辑 器 可 以 通 过 在 弹 出 的 上 下 文 菜 单 上 的 命 令 ,来 检 查 重 复 的 助记 符 。 在 编 辑 器 工 作 区 域 的 任 何 地 方 右 击 , 将 打 开 这 个 菜 单 :

致 谢 - 图78

助 记 符 和 加 速 键 并 不 是 相 同 的 东 西 。 加 速 键 不 需 要 通 过 菜 单 系 统 , 就 可 以 激 活 一个 命 令 , 然 而 , 下 划 线 助 记 符 只 有 当 菜 单 可 见 时 才 是 可 用 的 。

每 一 个 菜 单 命 令 都 有 一 个 以 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 条 目 打 开 菜 单 编 辑 器 。

致 谢 - 图79

项 目 必 须 是 打 开 的 , 你 可 能 不 得 不 隐 藏 Workspace 或 Outpu t( 输 出 ) 窗 口 , 以 便不 覆 盖 编 辑 器 的 工 作 区 域 。 当 你 设 计 并 保 存 菜 单 时 , Visual C++ 把 菜 单 脚 本 写 到

项 目 的 RC 文 件 里 , 并 把 标 识 符 #define 语 句 写 到 Resource.h 文 件 里 。其 后 , 当 你打 开 菜 单 资 源 时 , 环 境 自 动 打 开 菜 单 编 辑 器 。 为 了 显 示 Projec t( 项 目 ) 菜 单 标 识符 的 列 表 ,双 击 ResourceVie w( 资 源 查 看 )窗 格 里 的 Menu 条 目( 如 图 4-1 所 示 )。通 过 双 击 列 表 里 的 资 源 标 识 符 或 右 击 标 识 符 , 并 从 上 下 文 菜 单 里 选 择 Open 打 开菜 单 编 辑 器 。

致 谢 - 图80

图 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 程 序 是 不 需 要 的 , 因 为 框 架 会 自 动 更 正 菜 单 。

致 谢 - 图81

图 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:

致 谢 - 图82

双 击 在 文 件 列 表 里 的 新 的 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 命 令不 会 显 示 在 上 面 的 菜 单 脚 本 中 ,因 为 这 些 命 令 是 在 运 行 时 添 加 到 菜 单 上 的 。标 题栏 上 的 图 标 在 本 章 后 面 创 建 。

致 谢 - 图83

图 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 忽 略不 与 已 有 的 驱 动 器 相 对 应 的 按 键 。

致 谢 - 图84

图 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 所 示 。 它与 以 前 给 菜 单 资 源 的 名 字 相 同 。

致 谢 - 图85

图 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 读 取 字 符 串 所 属 的 那 个 完 整 的 段 ,如 果 程 序现 在 想 要 一 个 字 符 串 , 那 么 它 将 很 快 会 要 求 其 他 的 字 符 串 。 出 于 这 个 原 因 , 你 应该 尝 试 通 过 给 字 符 串 连 续 的 标 识 符 值 将 相 关 的 字 符 串 分 组 。 你 可 能 已 经 这 样 做了 , 但 现 在 你 知 道 了 这 样 做 的 原 因 。

致 谢 - 图86

图 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

致 谢 - 图87致 谢 - 图88Toolba r( 工 具栏 )

致 谢 - 图89Cursor ( 光标 )

B M P B M P

C U R CUR

致 谢 - 图90Icon ( 图 标 ) 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 对 话 框 里 , 也 可 以 给 这 个 图 形 文 件 指 定 一 个 名字 。

致 谢 - 图91

图 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++ 环 境 里 使 用 其 他 工 具 栏 一 样 , 你 可 以 通 过 向 内 或 向 外 拖动 工 具 栏 来 缩 小 或 放 大 它 。

致 谢 - 图92

图 4-12 Visual C++ 图 形 编 辑 器 中 的 工 具

图 形 编 辑 器 工 具 很 灵 活 , 而 且 很 友 好 , 只 需 要 几 分 钟 就 可 以 学 会 , 然 而 , 有 几 点可 能 看 起 来 不 那 么 直 观 , 所 以 要 简 要 讨 论 一 下 。 首 先 , 图 形 的 背 景 颜 色 依 赖 于 图形 的 类 型 。图 标 和 光 标 只 有 一 种 透 明 的 背 景 色 ,在 编 辑 器 窗 口 里 用 蓝 绿 色 进 行 着色 。 当 W indows 在 屏 幕 上 画 图 标 或 光 标 时 , 它 只 画 前 景 色 , 在 透 明 背 景 色 下 的所 有 像 素 均 不 擦 除 。 另 一 方 面 , 位 图 的 背 景 色 是 不 透 明 的 。 一 个 位 图 在 屏 幕 上 是作 为 一 块 画 出 来 的 , 它 将 覆 盖 它 下 面 的 任 何 东 西 。 背 景 色 是 否 透 明 , 可 能 是 这 两种 图 形 资 源 类 型 之 间 的 最 大 区 别 。

当 你 单 击 Rectangle Selection( 矩 形 选 择 ), Irregular Selection ( 不 规 则 图 形 选 择 ) 或 Text 按 钮 时 ,透 明 选 择 框 显 示 在 Graphics 工 具 栏 的 底 部 ,它 也 是 编 辑 器 Image 菜 单 上 Draw Opaque ( 不 透 明 画 图 ) 命 令 的 工 具 栏 版 本 。 要 理 解 选 择 框 的 用 途 , 考 虑 一 下 一 个 分 为 两 层 的 图 形 , 一 层 覆 盖 在 另 一 层 上 。 上 层 是 一 个 漂 浮 的 图 形 , 你 可 以 移 动 , 或 设 定 它 的 位 置 。 下 面 这 一 层 叫 做 底 层 , 是 固 定 的 。 利 用 选 择 框 , 你 可 以 设 定 顶 层 的 背 景 透 明 度 ,但 不 能 影 响 底 层 的 透 明 度 。选 择 透 明 度 选 择 框 的顶 部 图 标 , 意 味 着 覆 盖 图 形 层 上 的 背 景 像 素 应 该 当 作 前 景 颜 色 , 使 上 面 的 一 层 成为 实 心 的 矩 形 框 。 选 择 框 的 底 部 图 标 使 上 面 一 层 透 明 , 实 际 上 , 是 从 这 一 层 移 去背 景 像 素 。 例 如 , 下 面 是 当 打 开 或 关 闭 透 明 度 时 , 在 底 层 图 形 上 输 入 字 母 “ A ” 时 的 外 观 :

致 谢 - 图93

不 管 透 明 度 的 设 定 如 何 , 底 层 位 图 图 形 的 背 景 颜 色( 在 当 前 情 况 下 是 白 色 ) 均 保持 不 透 明 , 以 便 在 屏 幕 上 显 示 的 位 图 覆 盖 位 图 矩 形 区 域 内 的 任 何 像 素 。 然 而 , 当显 示 一 个 位 图 时 , 程 序 可 以 模 拟 透 明 的 像 素 , 首 先 掩 盖 位 图 的 背 景 颜 色 , 然 后 用位 图 将 出 现 的 屏 幕 区 域 的 副 本 来 替 代 它 。如 果 你 对 这 个 技 术 感 兴 趣 ,完 全 可 以 从

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 工 具 栏 按 钮

按 钮 说 明

致 谢 - 图94利 用 Rectangle Selection 和 Irregular Selection 工 具 , 可以 标 记 要 移 动 、 清 除 或 复 制 的 图 像 部 分 。 单 击 按 钮 , 然 后 , 拖 动 交 叉 十 字 或 光 标 , 指 向 要 标 记 的 矩 形 或 区域 。 在 释 放 鼠 标 按 钮 时 , 在 标 记 的 区 域 周 围 将 出 现 选择 框 。 你 可 以 移 动 选 择 内 容 , 方 法 是 使 用 鼠 标 拖 动它 ; 要 清 除 它 , 则 按 Del 键 ; 复 制 它 到 剪 贴 板 的 方 法是 按 Ctrl+C

致 谢 - 图95利 用 Select Colo r( 取 色 ) 工 具 , 可 以 从 图 像 中 选 取 颜色 ,而 不 是 从 Colors 调 色 板 中 。单 击 工 具 栏 上 的 按 钮 , 然 后 单 击 要 选 取 颜 色 的 图 像 上 的 区 域 。 使 用 鼠 标 左 键可 以 选 取 前 景 色 , 使 用 鼠 标 右 键 可 以 选 取 背 景 色

续 表

致 谢 - 图96Eras e( 橡 皮 擦 ) 工 具 将 光 标 改 为 一 个 方 块 , 可 以 在 图像 上 拖 动 它 , 来 擦 除 像 素 。 擦 除 的 像 素 改 变 为 当 前 前景 色 , 这 要 取 决 与 当 前 的 资 源 类 型 。 前 面 提 到 过 , 在Colors 调 色 板 的 左 上 角 , 图 标 和 光 标 的 背 景 是 不 透 明的 颜 色 。 要 改 变 擦 除 块 的 大 小 , 可 以 单 击 工 具 栏 底 部选 择 框 中 的 一 个 尺 寸 图 标

致 谢 - 图97Fil l( 填 充 )工 具 将 颜 色 的 像 素 改 变 为 当 前 的 前 景 或 背景 色 。 单 击 Fill 按 钮 , 然 后 单 击 要 改 变 的 颜 色 中 的 任何 地 方 。 若 使 用 鼠 标 左 键 , 则 填 充 前 景 色 ; 使 用 鼠 标右 键 则 填 充 背 景 色 。 编 辑 器 将 更 改 此 颜 色 的 所 有 连 续像 素 , 来 填 充 颜 色 。 像 素 必 须 水 平 或 垂 直 接 触 , 以 对角 方 式 接 触 的 像 素 被 认 为 是 不 连 续 的

续表

致 谢 - 图98要 改 变 所 选 择 图 形 的 大 小 , 可 以 使 用 M agnif y( 放 大 ) 工 具 , 并 选 择 一 个 值 1 , 2 , 6 或 8 。 放 大 值 指 定 对 应于 实 际 图 形 中 一 个 像 素 的 实 际 像 素 数 。 如 果 放 大 的 图形 有 网 格 , 则 放 大 值 确 定 的 是 每 个 网 格 的 宽 度 和 高 度

致 谢 - 图99单 击 左 边 的 图 片 按 钮 , 可 以 手 绘 图 , 然 后 , 拖 动 鼠 标按 钮 , 以 留 下 像 素 的 轨 迹 , 颜 色 是 前 景 色 或 背 景 色 。Pencil ( 铅 笔 ) 工 具 只 画 出 一 个 像 素 宽 的 细 线 。 使 用Brus h( 刷 子 ) 可 以 画 出 粗 线 , 在 工 具 栏 底 部 的 选 择 框中 可 以 选 择 刷 子 的 宽 度

致 谢 - 图100A ir Brush ( 喷 雾 ) 工 具 可 以 画 出 随 机 的 颜 色 图 案 , 模拟 在 画 布 上 轻 微 喷 射 的 效 果 。 在 工 具 栏 的 选 择 框 中 , 可 以 选 择 喷 射 的 密 度 和 尺 寸

续表

致 谢 - 图101画 线 工 具 可 以 画 直 线 , 还 可 以 画 曲 线 , 曲 线 从 初 始 位置 开 始 弹 性 弯 曲 。 单 击 要 开 始 画 线 的 位 置 , 拖 动 光 标到 线 的 终 点 , 然 后 释 放 鼠 标 键 来 确 定 此 线 。 Curve 工具 还 额 外 需 要 一 个 步 骤 : 在 释 放 鼠 标 键 设 置 终 点 后 , 移 动 光 标 来 设 置 曲 线 的 曲 率 。 在 曲 线 以 自 己 需 要 的 方式 成 形 后 , 双 击 便 可 以 确 定 曲 线 ( 双 击 的 鼠 标 键 必 须与 拖 动 光 标 的 鼠 标 键 相 同 )。 如 果 在 画 线 的 过 程 中 改变 了 主 意 , 可 以 按 Esc , 或 者 单 击 另 一 个 鼠 标 键 , 来重 新 开 始

续表

致 谢 - 图102致 谢 - 图103Text( 文 本 ) 工 具 显 示 一 个 小 窗 口 , 可 以 从 中 输 入 在图 形 中 出 现 的 文 字 , 所 用 的 颜 色 是 当 前 的 前 景 色 。 如前 所 述 , 在 透 明 选 择 框 中 选 择 文 字 的 透 明 性 , 然 后 , 在 选 择 完 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 里 放 大 的 位图 和 最 终 的 工 具 栏 。

致 谢 - 图104

图 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 里 所示 的 按 钮 之 间 添 加 分 割 空 隙 ,向 左 或 向 右 拖 动 一 个 按 钮 到 大 约 半 个 按 钮 宽 度 就 可以 了 。 你 可 以 用 同 样 的 方 法 去 掉 这 个 空 隙 。

致 谢 - 图105

图 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 中 , 可 以 看 到 一 些 按钮 图 形 的 特 写 视 图 。

致 谢 - 图106

图 4-15 DiskPie1 的 工 具 栏 位 图

可 以 看 到 , 生 成 位 图 并 不 是 十 分 困 难 , 只 用 了 大 约 20 分 钟 的 时 间 。 这 个 秘 密 就是 , 告 诉 图 形 编 辑 器 你 正 在 创 建 一 个 位 图 , 而 不 是 一 个 工 具 栏 。 第 一 步 在 下 列 两种 情 况 下 是 一 样 的 : 通 过 单 击 Insert 菜 单 上 的 Resource, 来 打 开 图 形 编 辑 器 。 为了 用 重 复 的 图 形 加 宽 如 图 4-15 所 示 的 位 图 , 从 资 源 类 型 列 表 里 选 择 Bitmap , 而不 是 Toolbar。 这 将 可 以 在 一 个 连 续 的 条 中 操 作 按 钮 图 形 , 而 单 独 操 作 每 个 按 钮 。在 图 形 编 辑 器 里 , 将 普 通 位 图 转 换 为 工 具 栏 是 很 容 易 的 , 设 计 它 就 是 做 这 个 的 。

这 里 是 使 用 重 复 图 形 生 成 加 宽 的 位 图 的 步 骤 。双 击 编 辑 器 工 作 区 域 的 空 白 区 域 的任 何 地 方 , 打 开 Bitmap Properties 对 话 框 。 输 入 工 具 栏 标 识 符 , 对 于 D iskPie1 ,

是 IDR_MAINFRAM E , 并 给 B M P 文 件 起 一 个 文 件 名 。 通 过 增 加 按 钮 的 数 目 , 来 增 加 一 个 工 具 栏 按 钮 的 宽 度 ,并 输 入 这 个 数 字 作 为 位 图 的 宽 度 。 位 图 的 高 度 是一 个 按 钮 的 高 度 。 对 于 DiskPie1 , 对 话 框 看 起 来 像 这 样 :

致 谢 - 图107

按 下 Enter 键 返 回 工 作 区 域 , 现 在 它 有 了 新 的 尺 寸 。 下 一 步 , 用 亮 灰 色 画 出 整 个工 作 区 域 , 以 便 每 一 个 图 形 能 和 它 的 按 钮 相 融 合 。 在 Color 调 色 板 里 单 击 亮 灰 色框 , 并 选 择 Graphics 工 具 栏 里 的 Fill 工 具 。

致 谢 - 图108

单 击 工 作 区 域 格 子 里 的 任 何 地 方 , 来 用 亮 灰 色 画 整 个 区 域 。 现 在 , 在 工 作 区 域 里的 一 个 16 × 15 的 块 里 , 画 第 一 个 按 钮 的 图 形( 或 是 任 何 的 按 钮 尺 寸 )。 一 旦 已 经画 出 第 一 个 图 形 , 就 可 以 通 过 单 击 Rectangle Selection 工 具 来 复 制 它 , 并 在 图 形的 16 × 15 方 块 上 拖 动 光 标 。 是 用 鼠 标 左 键 , 还 是 用 右 键 拖 动 , 取 决 于 你 是 移 动这 个 位 图 , 还 是 拷 贝 它 。 如 果 想 移 动 图 形 到 位 图 工 作 区 域 的 其 他 地 方 , 那 么 使 用鼠 标 左 键 。 当 你 释 放 鼠 标 按 钮 时 , 在 图 形 的 周 围 出 现 一 个 选 择 框 , 此 时 可 以 拖 动它 来 重 新 定 位 选 择 区 域 。按 下 Ctrl 键 拖 动 选 择 框 ,便 移 动 了 被 选 择 图 形 的 一 个 副本 , 而 不 是 图 形 本 身 , 但 是 , 有 一 种 更 好 的 方 法 来 复 制 图 形 。

要 生 成 一 个 图 形 的 副 本 , 需 单 击 Rectangle Selection ( 选 择 ) 工 具 , 并 用 按 下 鼠标 右 键( 而 不 是 鼠 标 左 键 ) 来 选 择 图 形 。 释 放 鼠 标 按 钮 时 , 被 选 择 图 形 的 一 个 副

本 将 跟 随 鼠 标 光 标 而 移 动 。 将 副 本 定 位 在 工 作 区 域 的 任 何 地 方 , 并 单 击 , 将 它 放置 在 选 择 的 位 置 上 。单 击 左 键 将 放 下 图 形 的 一 个 副 本 , 单 击 右 键 将 放 下 图 形 的 遮罩 , 其 中 , 前 景 像 素 转 化 为 当 前 图 形 的 背 景 颜 色 , 图 形 里 的 背 景 像 素 被 当 作 透 明的 小 洞 。 你 可 以 用 这 种 方 法 生 成 任 何 数 量 的 副 本 。 完 成 操 作 时 , 按 下 ESC 键 , 或 选 择 另 一 个 工 具 来 返 回 一 般 编 辑 模 式 。

你 将 发 现 图 形 横 越 整 个 16 × 15 方 块 , 像 图 4-16 里 的 磁 盘 驱 动 器 图 形 一 样 , 那 么定 位 它 将 更 加 容 易 。 如 果 图 形 比 方 块 窄 , 那 么 在 方 块 的 顶 部 或 底 部 画 一 条 16 个像 素 宽 的 临 时 黑 线 。 然 后 , 当 你 拷 贝 图 形 时 , 就 可 以 准 确 看 到 正 在 拖 动 什 么 。 如果 你 打 算 使 用 文 本 标 记 每 一 个 按 钮 , 像 图 4-15 里 所 做 的 那 样 , 那 么 , 最 后 , 在所 有 的 图 形 都 到 位 后 , 将 添 加 标 记 。 单 击 Text 工 具 , 输 入 文 字 , 并 拖 动 文 字 图形 到 指 定 位 置 。 在 做 完 每 一 个 文 字 之 后 , 按 下 ESC 键 取 消 Text 工 具 。

致 谢 - 图109

图 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 像 素 尺 寸 状 态 下 , 它 们 看 起 来 像 下 面 这 样 :

致 谢 - 图110

在 一 个 图 标 资 源 里 封 装 的 三 个 图 形 , 可 以 将 可 执 行 文 件 的 大 小 增 加 大 约 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 表 示 :

致 谢 - 图111

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 按 钮 :

致 谢 - 图112

上 述 方 法 都 会 打 开 图 4-17 里 的 New Icon Image 对 话 框 , 在 这 里 , 显 示 了 可 用 的图 形 尺 寸 , 但 是 还 没 有 与 图 标 关 联 。 如 果 你 在 列 表 里 没 有 看 到 想 要 的 尺 寸 , 可 单击 Custom 按 钮 , 并 指 定 一 个 新 的 图 形 尺 寸 。

致 谢 - 图113

图 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 个 像 素 的 正 方 形 :

致 谢 - 图114

  • 般 情 况 下 , 程 序 图 标 里 的 图 形 是 相 同 的 图 片 , 但 是 尺

    寸 不 同 。 我 给 出 了 三 种 不同 的 设 计 图 形 , 来 清 楚 地 显 示 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 键 删 除 光 标 图 形 。

致 谢 - 图115

当 图 形 编 辑 器 加 载 一 个 光 标 图 形 时 , 一 个 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"

致 谢 - 图116

图 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 程 序 源 代 码 )。

致 谢 - 图117

图 4-19 新 的 鼠 标 光 标 在 程 序 中 出 现

光 标 就 讲 这 些 吧 , 我 们 再 来 谈 谈 DiskPie1 程 序 。

向 DiskPie1 添 加 代 码

现 在 , D iskPie1 有 菜 单 、 加 速 键 、 工 具 栏 、 状 态 栏 和 图 标 , 这 些 是 需 要 的 所 有 资源 。 现 在 , 可 以 添 加 代 码 使 它 执 行 。 如 果 你 在 本 章 里 依 照 DiskPie1 的 生 成 过 程进 行 , 那 么 , 你 将 可 以 识 别 在 图 4-20 里 的 用 户 界 面 元 素 。 应 用 程 序 图 标 、 菜 单 、工 具 栏 和 状 态 栏 是 在 前 面 几 节 里 用 Visual C++ 资 源 编 辑 器 设 计 的 。

在 创 建 主 窗 口 的 过 程 中 , D iskPie1 将 找 到 所 有 连 接 的 固 定 磁 盘 , 包 括 远 程 驱 动 器和 RAM 驱 动 器 , 每 找 到 一 个 它 , 都 要 做 下 面 这 些 工 作 :

致 谢 - 图118

图 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 显 示 了 一 个 相 似 的 列 表 。

致 谢 - 图119

图 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 ( 矩 形 ) 工 具 使 用 的 十 字 形 。 但 是 , 当 画 一 个 矩形 时 , 新 的 光 标 会 稍 微 不 同 的 效 果 。 当 你 从 左 上 角 拖 动 光 标 到 右 下 角 时 , 上 边 和左 边 用 目 前 的 前 景 色 , 而 右 边 和 底 部 用 背 景 色 显 示 。通 过 用 鼠 标 右 键 拖 动 来 修 改颜 色 。 使 用 正 确 的 颜 色 组 合 , 嵌 套 的 矩 形 显 示 一 个 三 维 外 观 , 可 以 快 速 生 成 下 面这 样 的 图 标 :

致 谢 - 图120

在 图 形 编 辑 器 里 工 作 时 , 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 的 工 具 栏 按 钮 所 使 用 的 图 像 :

致 谢 - 图121

这 些 图 像 复 制 了 D iskPie1 中 工 具 栏 的 前 两 个 图 形 , 只 是 第 二 个 图 形 没 有 标 记 , 并 使 它 适 于 表 示 任 何 磁 盘 驱 动 器 。 运 行 时 , D iskPie2 给 按 钮 的 磁 盘 驱 动 器 图 形 添加 像 “ C :”和 “ D :” 这 样 的 名 称 。 你 可 以 在 图 4-22 里 看 到 这 个 结 果 。

致 谢 - 图122

图 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 :

致 谢 - 图123

展 开 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 ( 关 于 ) 框 对 话 。

致 谢 - 图124

图 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 的 工 具 栏 需 要 详 细 解 释 一 下 。

致 谢 - 图125

图 5-2 对 话 编 辑 器

Contro l( 控 件 ) 工 具 栏

利 用 Control( 控 件 ) 工 具 栏 , 你 可 以 单 击 访 问 对 话 窗 口 中 放 置 的 控 件 。 单 击 代

表 你 想 要 的 工 具 栏 按 钮 , 并 且 , 将 控 件 从 工 具 栏 拖 入 到 对 话 框 中 的 位 置 。 在 你 拖动 的 时 候 , 一 个 点 划 线 的 矩 形 显 示 了 控 件 窗 口 的 轮 廓 , 这 样 , 在 你 释 放 鼠 标 按 钮放 置 控 件 之 前 , 就 可 以 对 控 件 的 尺 寸 和 位 置 一 目 了 然 。 另 一 种 方 法 是 , 只 需 在 从Controls ( 控 件 ) 工 具 栏 选 中 一 个 按 钮 , 然 后 , 在 对 话 窗 口 的 任 何 地 方 单 击 即 可 。控 件 窗 口 将 在 单 击 位 置 的 中 心 地 方 出 现 。 图 5-3 标 识 了 Controls ( 控 件 ) 工 具 栏上 可 以 提 供 的 控 件 类 型 。

一 旦 已 经 把 自 己 想 要 的 控 件 从 Controls ( 控 件 ) 工 具 栏 拖 进 了 对 话 区 , 那 么 , 下面 就 是 在 自 己 喜 欢 的 位 置 安 排 控 件 了 。D ialo g( 对 话 )工 具 栏 可 以 为 你 提 供 帮 助 , 但 是 , 首 先 我 们 必 须 来 讨 论 一 下 在 对 话 中 选 中 控 件 窗 口 。

致 谢 - 图126

图 5-3 Controls 工 具 栏

选 择 和 安 排 控 件

将 控 件 窗 口 拖 入 对 话 框 的 时 候 ,在 该 控 件 周 围 包 围 着 一 个 有 阴 影 的 矩 形 , 这 就 表示 该 控 件 已 被 选 中 了 。阴 影 的 选 择 矩 形 有 八 个 尺 寸 控 制 柄 ,它 们 是 放 置 在 矩 形 四角 和 四 边 的 小 正 方 形 。 像 在 W indows 中 的 典 型 操 作 一 样 , 你 可 以 通 过 用 鼠 标 指针 来 拖 动 一 个 尺 寸 控 制 柄 , 来 调 整 选 中 的 控 件 ,或 者 如 果 想 更 加 精 确 地 进 行 调 整的 话 , 还 可 以 通 过 按 箭 头 键 的 同 时 按 下 Shift 键 来 完 成 。 每 按 一 次 , 控 件 的 尺 寸改 变 一 个 单 位 。 你 还 可 以 通 过 在 工 作 内 的 任 何 地 方 而 不 是 在 控 件 窗 口 上 单 击 ,来选 中 和 调 整 对 话 框 本 身 。

当 你 将 控 件 窗 口 拖 入 对 话 的 时 候 , 没 有 必 要 对 其 进 行 仔 细 定 位 , 因 为 移 动 已 经 就位 的 控 件 是 很 容 易 的 。单 击 对 话 工 作 区 中 的 控 件 来 选 中 控 件 窗 口 , 然 后 使 用 鼠 标拖 动 或 使 用 箭 头 键 移 动 它 。 为 了 更 好 地 对 齐 , 可 单 击 D ialo g( 对 话 ) 工 具 栏 上 的Toggle Grid ( 开 关 网 格 ) 按 钮 打 开 网 格 。

致 谢 - 图127

当 可 以 在 对 话 窗 口 中 看 到 网 格 的 时 候 , 控 件 仅 从 一 个 网 格 行 移 向 另 一 个 网 格 行 , 这 个 特 征 就 是 大 家 熟 知 的 “ 与 网 格 对 齐 ”。 在 默 认 状 态 下 , 水 平 和 垂 直 网 格 间 距是 5 个 对 话 单 位 , 但 你 可 以 在 图 5-4 所 示 的 Grid Settings( 网 格 设 置 ) 对 话 框 中改 变 这 个 对 话 框 。

致 谢 - 图128

图 5.4 Guide Setting 框

如 果 与 网 格 对 齐 特 征 阻 碍 你 按 照 自 己 的 方 式 来 安 排 控 件 , 那 么 只 需 将 其 关 闭 即可 。 如 果 你 后 来 又 打 开 了 , 编 辑 器 不 影 响 对 话 框 中 已 经 存 在 的 控 件 窗 口 的 放 置 。如 果 想 临 时 抑 制 一 下 此 特 征 , 请 在 拖 动 控 件 的 时 候 按 Alt 键 。

每 次 将 几 个 控 件 作 为 一 组 而 不 是 单 独 一 个 进 行 移 动 或 调 整 往 往 更 加 方 便 。对 话 编辑 器 为 同 时 选 中 几 个 控 件 提 供 了 两 种 方 法 。 第 一 种 方 法 是 在 按 住 Shift 键 的 同 时依 次 单 击 你 想 选 中 的 控 件 。第 二 种 方 法 最 适 于 成 组 安 排 的 控 件 。单 击 Control s( 控件 )工 具 栏 上 的 Selectio n( 选 择 )工 具 ,并 将 虚 线 矩 形 拖 到 控 件 上 面 来 选 中 它 们 。图 5-5 说 明 了 这 个 过 程 。

如 果 你 想 取 消 对 所 选 组 中 某 个 控 件 的 选 中 , 请 在 按 住 Shift 键 的 同 时 单 击 该 控件 。 还 可 以 用 同 样 的 方 法 向 组 中 添 加 控 件 。 选 中 了 多 个 控 件 之 后 , 在 选 中 组 中 , 除 了 一 个 控 件 之 外 ,除 有 控 件 的 尺 寸 控 制 柄 全 都 显 示 为 空 的 ,以 表 明 它 们 处 于 非激 活 状 态 。 剩 下 的 那 个 具 有 实 尺 寸 控 制 柄 的 控 件 被 认 为 是 选 中 组 中 的 支 配 控 件 , 编 辑 器 可 以 从 中 确 定 作 为 整 体 的 选 中 组 的 调 整 或 对 齐 方 式 。 例 如 , 图 5-5 中 的Check1 控 件 就 是 选 中 的 组 中 的 三 个 控 件 的 支 配 控 件 , 因 为 它 是 唯 一 具 有 实 尺 寸控 制 柄 的 控 件 。 在 按 下 Ctrl 键 的 同 时 , 单 击 选 中 组 中 的 另 一 个 控 件 , 可 以 使 其 成为 新 的 支 配 控 件 。

致 谢 - 图129

图 5-5 同时选中几个控件

仅 有 实 尺 寸 控 制 柄 处 于 活 动 状 态 ; 如 果 尺 寸 控 制 柄 是 空 的 ,那 么 该 控 件 就 不 能 在

这 个 方 向 上 进 行 调 整 。组 合 框 控 件 仅 仅 在 两 边 上 具 有 活 动 的 尺 寸 控 制 柄 。这 是 因为 通 常 看 不 到 的 控 件 下 拉 区 域 边 是 控 件 窗 口 的 一 部 分 , 在 建 立 窗 口 尺 寸 的 时 候 , 必 须 将 其 考 虑 进 来 。 图 5-6 说 明 了 如 何 改 变 组 合 框 控 件 下 拉 区 域 的 尺 寸 。

你 可 以 创 建 控 件 的 一 个 副 本 ,并 通 过 在 按 下 Ctrl 键 的 时 候 拖 动 控 件 窗 口 ,来 将 其放 在 工 作 区 中 , 如 图 5-7 所 示 。 该 操 作 将 创 建 一 个 新 窗 口 , 除 了 具 有 自 己 的 标 识符 值 外 , 它 就 是 原 始 窗 口 的 “ 克 隆 ” 体 。

致 谢 - 图130

图 5-6 改变组合框的尺寸

致 谢 - 图131

图 5-7 在 对 话 编 辑 器 中 复 制 控 件 窗 口

Dialog ( 对 话 ) 工 具 栏

既 然 你 已 经 知 道 了 如 何 选 中 一 组 控 件 , 那 么 , 图 5-8 所 示 的 D ialog( 对 话 ) 工 具栏 就 更 有 意 义 了 。 在 对 话 中 四 处 拖 动 控 件 是 找 到 合 适 位 置 的 好 办 法 , 但 是 , 如 果要 精 确 对 齐 控 件 窗 口 , 你 应 该 使 用 D ialog ( 对 话 ) 工 具 栏 上 的 工 具 。 利 用 它 们 , 你 可 以 在 对 话 框 内 部 对 齐 了 的 行 和 列 中 放 置 控 件 窗 口 ,为 对 话 提 供 整 齐 的 和 专 业的 外 观 。这 个 工 具 栏 上 还 有 一 个 测 试 模 式 开 关 ,它 允 许 你 将 新 的 对 话 用 于 测 试 驱动 程 序 , 来 看 看 它 在 实 际 中 的 外 观 和 行 为 。

致 谢 - 图132

图 5-8 Dialog ( 对 话 ) 工 具 栏

所 有 的 D ialo g( 对 话 ) 工 具 栏 按 钮 在 Layou t( 布 局 ) 菜 单 上 都 具 有 功 能 相 同 的 命令 , 因 此 , 如 果 你 不 想 看 见 工 具 栏 的 话 , 还 可 以 把 它 关 闭 。 如 果 想 显 示 或 隐 藏 工具 栏 , 请 从 Tools ( 工 具 ) 菜 单 中 选 择 Customize( 自 定 义 ), 单 击 Toolbars ( 工具 栏 ) 选 项 卡 , 然 后 单 击 列 表 中 的 Dialog( 对 话 ) 复 选 框 。

正 如 你 在 图 5-8 中 所 看 到 的 , 工 具 栏 将 按 钮 安 排 在 五 个 逻 辑 组 中 , 它 们 分 别 用 于对 齐 、 居 中 、 间 隔 、 调 整 控 件 的 尺 寸 , 以 及 打 开 和 关 闭 网 格 和 标 尺 指 南 。 在 图

  1. 中 呈 现 为 灰 色 的 对 齐 、 间 隔 和 尺 寸 调 整 工 具 , 仅 仅 当

    对 话 中 选 中 了 两 个 或 多个 控 件 时 才 被 启 用 。

下 面 几 节 将 阐 述 D ialo g( 对 话 ) 工 具 的 几 个 效 果 。 通 常 , 为 了 将 一 组 控 件 放 到 所需 要 的 位 置 ,需 要 采 用 几 个 工 具 。因 此 ,你 必 须 考 虑 一 下 应 用 工 具 的 顺 序 。不 过 , 即 使 做 错 了 也 没 关 系 。 如 果 一 个 工 具 的 效 果 不 合 适 , 只 需 单 击 Edit( 编 辑 ) 菜 单上 的 Undo ( 撤 消 ) 即 可 。

对 齐 工 具

对 齐 工 具 的 作 用 是 将 所 选 组 的 控 件 与 支 配 控 件 对 齐 。 例 如 , 单 击 Align Left( 左对 齐 ) 按 钮 , 将 改 变 选 中 控 件 的 X 坐 标 , 以 便 与 支 配 控 件 的 X 坐 标 和 匹 配 , 而不 影 响 Y 坐 标 。

致 谢 - 图133

居 中 工 具

居 中 工 具 可 以 作 用 于 单 个 选 中 控 件 或 一 组 控 件 ,将 选 中 部 分 放 在 对 话 客 户 区 的 水平 或 垂 直 中 心 。

致 谢 - 图134

间 隔 工 具

间 隔 工 具 仅 仅 在 包 含 有 三 个 或 更 多 控 件 的 选 中 组 上 才 能 工 作 。 在 D ialog ( 对 话 ) 工 具 中 , 它 们 是 独 一 无 二 的 , 因 为 它 不 能 区 分 哪 一 个 选 中 控 件 是 支 配 控 件 。 水 平间 隔 将 改 变 选 中 组 中 除 了 最 左 边 和 最 右 边 控 件 之 外 的 X 坐 标 , 使 水 平 方 向 的 控件 均 匀 排 列 。 垂 直 间 隔 工 具 完 成 Y 坐 标 方 向 上 相 同 的 工 作 , 使 控 件 在 垂 直 方 向上 均 匀 分 布 。 在 下 列 中 , 垂 直 间 隔 工 具 ( 编 辑 器 为 它 取 了 个 容 易 引 起 混 淆 的 名 字 , Space Dow n( 向 下 间 隔 ) ) 调 整 的 仅 仅 是 Appl y( 应 用 ) 按 钮 , O K 和 Cancel 按 钮

依 旧 在 原 来 的 位 置 不 变 。

致 谢 - 图135

尺 寸 调 整 工 具

尺 寸 调 整 工 具 作 用 于 包 含 有 两 个 或 更 多 控 件 的 选 中 组 。尺 寸 调 整 并 不 移 动 控 件 窗口 , 而 仅 仅 改 变 选 中 的 控 件 的 高 度 和 宽 度 , 以 便 与 选 中 部 分 中 支 配 控 件 的 尺 寸 相配 。

致 谢 - 图136

控 件 属 性

对 话 工 作 区 中 的 每 个 控 件 都 有 一 个 Properties ( 属 性 ) 对 话 框 , 你 可 以 在 里 面 为控 件 指 定 标 识 符 和 值 , 键 入 标 签 , 设 置 适 合 于 控 件 窗 口 的 样 式 标 志 。 如 果 想 展 现控 件 的 Properties( 属 性 ) 框 , 请 右 击 工 作 区 中 的 控 件 窗 口 , 并 从 弹 出 的 上 下 文菜 单 上 选 择 Propertie s。 你 还 可 以 选 中 一 个 控 件 , 并 单 击 View ( 查 看 ) 菜 单 上 的Properties 命 令 。 每 个 控 件 类 型 的 Properties ( 属 性 ) 对 话 在 外 观 和 内 容 上 略 有 不同 。 图 5-9 显 示 了 一 个 复 选 框 控 件 的 Properties ( 属 性 ) 框 。

致 谢 - 图137

图 5-9 一个复选框控件的 Properties(属性)对话

在 第 4 章 中 ,你 可 能 已 经 习 惯 于 在 Visual C++ 图 形 编 辑 器 中 双 击 一 个 项 目 来 打 开合 适 的 Properties( 属 性 ) 框 了 , 但 该 项 技 术 在 对 话 编 辑 器 中 则 不 具 有 相 同 的 效果 。 双 击 对 话 工 作 区 中 的 一 个 控 件 窗 口 可 以 导 致 三 个 结 果 之 一 , 这 主 要 取 决 于 环境 和 控 件 类 型 。

  • 如 果 控 件 接 受 用 户 输 入 ,双 击 控 件 窗 口 ,将 调 用 一 个

    题 为 Add Function

( 添 加 函 数 ) 的 对 话 , 它 允 许 你 为 这 个 控 件 快 速 添 加 存 根 处 理 程 序 函数 。

  • 双 击 静 态 控 件 或 对 话 窗 口 , 将 在 文 本 编 辑 器 中 打 开 对

    话 类 的 源 文 件 , 并 在 构 造 器 中 放 置 插 入 符 。

  • 如 果 项 目 没 有 ClassWizard 数 据 库 CLW 文 件( 将 在 下 章 介 绍

    ),那 么 双击 非 静 态 控 件 的 一 个 控 件 将 没 有 任 何 效 果 。 这 种 行 为 不 同 于 版 本 5 , 在 版 本 5 中 , 没 有 CLW 文 件 时 , 双 击 将 显 示 该 控 件 的 Properties ( 属性 ) 框 。

如 果 控 件 接 受 用 户 输 入 , 例 如 复 选 框 或 滑 块 控 件 , 那 么 , 当 你 键 入 控 件 标 题 的 时候 ,将 分 配 一 个 独 一 无 二 的 助 记 键 。利 用 助 记 键 ,用 户 通 过 按 下 键 盘 上 的 一 个 键 , 可 以 将 输 入 焦 点 移 到 控 件 上 。前 一 章 介 绍 了 用 于 菜 单 命 令 的 助 记 键 ,用 于 标 签 的助 记 键 也 没 有 什 么 差 别 。 只 需 要 在 任 何 字 符 前 加 上 “ 与 ” 符 号 (& ), 将 字 符 作 为控 件 的 助 记 键 标 识 即 可 。 例 如 图 5-9 中 的 复 选 框 就 具 有 标 题 “ &Red ”, 在 里 面 , 助 记 键 是 字 母 “ R ”。

对 于 滑 块 控 件 或 像 编 辑 框 这 样 的 文 字 条 目 控 件 ,应 在 静 态 控 件 标 签 中 为 其 分 配 助记 键 , 下 面 是 一 个 简 单 的 例 子 :

致 谢 - 图138

在 这 种 情 况 下 , 按 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 键 移 动 顺 序 , 该 顺 序 是 作 为 序 号 码

在 对 话 控 件 附 近 出 现 的 。 下 面 是 在 前 面 的 脚 本 中 定 义 的 用 于 对 话 的 工 作 区 :

致 谢 - 图139

如 果 想 修 改 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( 关 于 ) 框 , 它 制 作 得 更 加 精 心 。

致 谢 - 图140

图 5-10 修 改 后 的 Abou t(关于)框

位 图 标 志 事 先 在 Visual C++ 图 形 编 辑 器 中 创 建 , 并 保 存 在 名 为 XYZCorp.bmp 的

文 件 之 中 。 除 此 之 外 , 在 对 话 编 辑 器 中 所 做 的 改 动 只 用 几 个 步 骤 即 可 完 成 , 所 花的 时 间 也 就 5 分 钟 。 如 果 你 想 试 着 自 己 修 改 About ( 关 于 ) 框 , 那 么 , 可 以 以 一个 名 为 Demo 的 免 费 分 布 的 AppWizard 项 目 作 为 开 始 。 然 后 按 如 下 步 骤 进 行 操作 。

  1. **创 建 标 志 :**单 击 Inse r(t 插 入 )菜 单 上 的 Resourc e( 资

    源 ),并 选 中 Bitmap

( 位 图 ),来启动 Visual C++ 图 形 编 辑 器 。设计标志位图,从 View( 查

看 ) 菜 单 选 择 Properties , 来 为 新 的 位 图 资 源 提 供 标 识 符 , 并 指 定 文 件名 。 完 成 之 后 单 击 File ( 文 件 ) 菜 单 上 的 Save ( 保 存 )。

  1. 启 动 对 话 编 辑 器 并 加 载 Abou t( 关 于 ) 框 :

    Workspace( 工 作 空 间 ) 窗 口 的 ResourceView 窗 格 中 , 双 击 IDD_ABOUTBOX 来 启 动 对 话 编辑 器 。

  2. 调 整 对 话 的 尺 寸 : 通 过 单 击 没 有 被 控 件 占 据 的 灰

    色 对 话 框 里 面 的 任 何地 方 , 来 选 中 对 话 窗 口 , 并 拖 动 底 部 尺 寸 调 整 控 制 柄 来 扩 大 窗 口 。

  3. 改 变 标 题 : 在 对 话 窗 口 处 于 选 中 状 态 的 时 候 , 单

    击 View( 查 看 ) 菜 单上 的 Properties 命 令 , 并 在 D ialog Properties ( 对 话 属 性 ) 框 中 重 新 编写 标 题 。

  4. 添 加 标 志 : 在 对 话 工 作 区 中 选 中 MFC 图 标 , 通 过 按

    Del 键 将 其 删 除 , 然 后 用 在 步 骤 1 中 创 建 的 代 表 公 司 标 志 的 新 位 图 来 代 替 它 。 如 果 想 向

对 话 添 加 一 个 位 图 , 请 单 击 Controls ( 控 件 ) 工 具 栏 上 的 Picture ( 图片 ) 按 钮 , 并 将 控 件 拖 到 对 话 中 的 任 何 地 方 ( 位 置 不 需 要 十 分 精 确 )。在 图 形 控 件 处 于 选 中 状 态 的 时 候 , 使 用 Propertie s( 属 性 ) 命 令 可 以 调用 代 表 新 图 形 控 件 的 Picture Propertie s( 图 片 属 性 ) 框 ( 如 果 想 选 中 像图 片 这 样 的 空 控 件 , 请 单 击 该 控 件 周 围 的 框 架 , 原 因 是 编 辑 器 不 能 将框 架 里 面 的 单 击 识 别 为 以 控 件 作 为 目 标 )。从 Typ e( 类 型 ) 框 的 列 表 中选 择 Bitmap ( 位 图 ), 并 在 Imag e( 图 像 ) 框 中 键 入 位 图 标 识 符 。 一 定要 键 入 与 在 步 骤 1 给 定 的 相 同 的 标 识 符 。 你 可 以 按 照 同 样 的 方 式 向 对话 中 添 加 图 标 , 只 是 应 选 择 Type ( 类 型 ) 框 中 的 Icon ( 图 标 ), 而 不是 Bitmap( 位 图 )。

致 谢 - 图141

  1. 编 辑 对 话 文 字 : 对 话 中 每 两 行 文 字 就 是 一 个 静 态

    控 件 。 为 每 个 静 态 控件 调 用 Text Propertie s(属性)框,并修改 Captio n( 标 题 ) 框 中 的 文 字 。在 上 例 中 , 将 “ Dem o ” 改 为 “ SpitfyDem o”, 版 权 行 扩 展 为 包 括 XYZ Corporation 。 在 原 来 文 字 中 用 \251 代替 “ (C )” 版 权 符 号 , \251 是 AXSI

字 符 的 八 进 制 代 码 ( 如 果 想 获 得 你 想 用 相 同 方 式 添 加 到 文 字 控 件 的 其 他

ANSI 字 符 列 表 , 请 参 考 附 录 A )。

  1. **添 加 电 话 号 码 :**该 步 骤 需 要 用 Contro l (s 控 件 )工 具

    栏 提 供 的 Group Box

( 组 框 ) 工 具 和 Static Tex t( 静 态 文 本 ) 工 具 。 首 先 , 单 击 Group Box

( 组 框 ) 按 钮 , 并 将 它 的 图 像 移 动 到 对 话 框 的 下 半 空 白 区 域 。 在 需 要的 时 候 将 其 扩 大 ,然 后 再 次 单 击 Propertie s( 属 性 )命 令 打 开 Group Box Properties ( 组 框 属 性 ) 对 话 , 并 将 标 题 改 为 “ Phone Numbers ”, 下 一步 , 单 击 Static tex t( 静 态 文 本 ) 按 钮 , 并 将 其 拖 到 对 话 中 的 组 合 框 里面 。 在 静 态 控 件 窗 口 仍 处 于 选 中 状 态 的 时 候 , 通 过 在 按 住 Ctrl 键 的 同时 短 距 离 地 拖 动 控 件 , 可 以 创 建 它 的 多 个 副 本 。 将 这 些 副 本 拖 到 独 立的 行 上 , 一 个 接 一 个 地 放 置 。 在 这 个 阶 段 , 对 齐 并 不 是 很 重 要 的 , 因为 以 后 可 以 更 加 仔 细 地 进 行 。

致 谢 - 图142

在 默 认 状 态 下 , 静 态 控 件 包 含 有 单 个 单 词 “ Static ”。 为 这 三 个 静 态 控件 中 的 每 一 个 打 开 Text Properties( 属 性 ) 对 话 , 并 在 Caption( 标 题 ) 框 中 用 新 文 字 和 电 话 号 码 代 替“ Static ”。 单 击 位 于 Properties 对 话 左 上角 的 按 钉 按 钮 , 可 以 阻 止 它 在 两 个 选 择 之 间 消 失 。

\t 制 表 符 在 三 个 静 态 控 件 中 为 电 话 号 码 留 空 , 并 将 它 们 对 齐 , 例 如“ Sales:\t\t\t(206)555-1212 ”。 不 过 , 在 Caption 栏 中 键 入 \t 字 符 将 只 为

静 态 控 件 扩 展 一 个 单 空 格 , 因 此 , \t 字 符 后 面 的 文 字 可 能 不 会 在 控 件窗 口 中 出 现 。 如 果 看 到 它 , 你 可 以 通 过 拖 动 控 件 的 右 尺 寸 调 整 控 制 柄来 手 工 加 长 每 个 静 态 控 件 。

  1. 对 齐 控 件 : 打 开 网 格 , 并 使 用 鼠 标 拖 动 控 件 就 位

    。 三 个 带 有 电 话 号 码的 文 字 控 件 应 当 被 对 齐 , 而 且 被 均 匀 排 列 。 在 你 所 希 望 的 地 方 设 置 第一 行 , 然 后 选 中 全 部 三 行 , 并 且 单 击 D ialo g( 对 话 ) 工 具 栏 上 的 Align

Left( 左 对 齐 ) 和 Space Down ( 向 下 间 隔 ) 按 钮 。

致 谢 - 图143

如 果 想 使 对 话 的 外 观 均 衡 , 在 上 面 的 例 子 中 , 还 可 以 扩 大 O K 按 钮 。只 需 单 击 该 按 钮 便 可 选 中 它 , 然 后 根 据 需 要 拖 动 尺 寸 调 整 控 制 柄 即可 。

  1. 测 试 : 单 击 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 ( 可 见 性 ) 复 选 框 :

致 谢 - 图144

该 操 作 将 把 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 来 删 除 它 们 。

致 谢 - 图145

图 5-11 Color 程序

致 谢 - 图146

Color 对 话 仅 仅 包 含 三 个 不 同 的 类 型 , 它 们 是 由 来 自 编 辑 器 的 Controls ( 控 件 ) 工 具 栏 的 Static Tex t( 静 态 文 本 ) ,Button ( 按 钮 ) 和 Slide r( 滑 块 ) 工 具 创 建 的 。

滑 块 栏 在 对 话 中 形 成 了 三 条 分 界 线 , 在 图 5-11 中 分 别 标 为 Red, Green 和 Blue 。为 了 创 建 Red (上 ) 线 , 首 先 需 要 在 两 个 静 态 文 本 控 件 之 间 放 置 一 个 滑 块 控 件 , 然后 所 有 的 控 件 都 要 对 齐 , 并 留 出 间 隔 。 将 文 本 控 件 的 标 题 初 始 化 为 Red , 并 在Text Properties 对 话 中 键 入 X 。X 的 作 用 是 充 当 Color 在 运 行 期 间 用 滑 块 位 置 的 新值 进 行 覆 盖 的 占 位 符 。为 滑 块 控 件 分 配 一 个 静 态 边 缘 的 边 框 和 一 个 具 有 指 针 的 按钮 。 这 些 样 式 可 以 在 Slider Propertie s( 滑 块 属 性 ) 对 话 中 进 行 设 置 , 可 以 通 过 右击 对 话 中 的 滑 块 控 件 窗 口 , 并 选 择 Properties 来 设 置 :

  1. 在 Style ( 样 式 ) 选 项 卡 中 , 在 拇 指 样 式 的 Point( 指 向

    ) 框 中 选 中

Bottom/Righ t( 底 部 /右 边 )。

  1. 在 Extender Style( 扩 展 样 式 ) 选 项 卡 中 , 单 击 Static Edg

    e( 静 态 边 缘 ) 复 选 框 。

Green 和 Blue 线 的 创 建 方 法 与 Red 线 完 全 相 同 , 通 过 将 Red 的 三 个 控 件 做 为 一组 选 中 来 复 制 , 然 后 按 照 前 一 章 中 介 绍 的 方 法 , 在 按 下 Ctrl 的 同 时 拖 动 该 组 控件 。 这 时 候 , 对 话 编 辑 器 工 作 区 看 上 去 与 下 图 类 似 , 完 成 该 对 话 仅 仅 需 要 将 第 二个 和 第 三 个 标 题 分 别 改 为 Green 和 Blue,将 控 件 对 齐 ,并 在 对 话 窗 口 的 底 部 添 加O K 按 钮 。 为 该 按 钮 分 配 一 个 标 识 符 IDOK , 并 设 置 该 按 钮 的 Propertie s( 属 性 ) 对 话 Styles 选 项 卡 中 的 Default Button ( 默 认 按 钮 ) 复 选 框 。

致 谢 - 图147

在 复 制 选 定 了 的 控 件 的 时 候 ,对 话 编 辑 器 将 自 动 为 新 的 控 件 分 配 不 同 的 标 识 符 符号 , 以 确 保 该 对 话 中 的 每 个 控 件 都 被 独 一 无 二 地 标 识 。新 的 符 号 与 原 来 的 符 号 具

有 相 同 的 名 字 , 只 是 后 面 添 加 了 数 字 。 例 如 , 第 一 行 的 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 章 , 我 们 还 要 对 其 进 行 改 进 。

致 谢 - 图148

图 5-12 MfcTree 程序

该 程 序 的 创 建 过 程 可 分 为 五 步 :

  1. 运 行 AppWizard 创 建 M fcTree 项 目 。

  2. 在 对 话 编 辑 器 中 创 建 对 话 资 源 。

  3. 向 项 目 添 加 新 的 对 话 类 的 资 源 文 件 。

  4. 修 改 菜 单 。

  5. 向 项 目 资 源 文 件 添 加 必 要 的 源 代 码 。下 面 , 我 们 来 一

    步 一 步 地 进 行 。

步 骤 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 。

致 谢 - 图149

下 一 步 是 添 加 树 状 视 图 控 件 , 从 Controls (控件)工具栏中,将 Tree Contro l( 树状 控 件 ) 工 具 拖 入 对 话 工 作 区 , 并 根 据 需 要 调 整 对 话 工 作 区 和 控 件 的 大 小 。 单 击View ( 查 看 ) 菜 单 上 的 Properties 来 调 用 Tree Control Propertie s( 树 状 控 件 属 性 ) 框 ,并 将 标 识 符 符 号 改 为 IDC_MFC_TREE 。在 Style 选 项 卡 中 ,单 击 Has Buttons

( 有 按 钮 ), Has Lines ( 有 线 ) 和 Lines At Roo t( 根 位 置 的 线 ) 复 选 框 , 如 下 图所 示 :

致 谢 - 图150

这 些 样 式 改 变 将 向 列 表 视 图 添 加 小 的 加 号 或 减 号 图 标 , 当 单 击 这 些 图 标 的 时 候 , 将 折 叠 或 展 开 列 表 层 次 中 的 各 级 。使 用 本 章 前 面 介 绍 的 水 平 间 隔 工 具 将 O K 按 钮移 到 对 话 和 中 心 两 个 控 件 的 底 部 。 现 在 , 对 话 在 编 辑 工 作 区 中 的 样 子 如 图 所 示 :

致 谢 - 图151

从 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 文 件 , 将 它 添 加 到 项 目 之 中 。

致 谢 - 图152

不 必 用 相 同 的 方 法 来 添 加 M fcDlg.h 文 件 , 因 为 Visual C++ 将 头 文 件 识 别 为

M fcDlg.cpp 的 相 关 文 件 。

步 骤 4 : 修 改 菜 单

M fcTree 需 要 一 个 菜 单 命 令 来 调 用 对 话 , 但 是 , 不 需 要 AppWizard 放 在 菜 单 上 的其 他 命 令 。 使 用 第 4 章 中 介 绍 的 Visual C++ 菜 单 编 辑 器 将 M fcTree 的 菜 单 修 改 成如 下 的 样 子 。

致 谢 - 图153

在 菜 单 编 辑 器 中 , 双 击 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 窗 口 中 的 对 话 标 识 符 才 能 启动 。

致 谢 - 图154

图 5-13 在 AppWizard 中创建基于对话的应用程序

用 AppWizard 创 建 M fcTree 的 基 于 对 话 的 版 本 只 需 三 个 步 骤 ,与 前 一 节 中 的 五 个步 骤 对 比 如 下 :

步 骤 主 窗 口 版 本 基 于 对 话 的 版 本

  1. 运 行 AppWizard 创 建 项 目 √ √

  2. 创 建 或 修 改 对 话 √ √

  3. 插 入 新 对 话 类 的 源 文 件 √

  4. 修 改 菜 单 √

  5. 添 加 所 必 需 的 源 代 码 √ √

为 对 话 创 建 新 类 的 步 骤 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 文 件 类 中 找 到 它 。

致 谢 - 图155

图 5-14 MfcTree 程序基于对话的版本

例 5 : 不 用 AppWizard 实 现 的 基 于 对 话 的 应 用 程 序

在 创 建 基 于 对 话 的 应 用 程 序 的 时 候 , AppWizard 起 了 很 大 的 作 用 , 因 为 这 样 的 应用 程 序 在 方 法 上 很 一 致 , 因 此 AppWizard 添 加 你 不 想 要 的 代 码 的 可 能 性 就 很 小 。但 AppWizard 可 能 仍 然 满 足 不 了 你 的 特 殊 需 要 , 如 果 你 对 不 用 AppWizard 编 写基 于 对 话 的 应 用 程 序 感 兴 趣 , 那 么 本 节 将 告 诉 你 如 何 去 做 。 它 用 名 为 D irList1 的范 例 程 序 来 进 行 说 明 , 该 程 序 的 作 用 是 在 对 话 中 显 示 一 个 目 录 列 表 。但 是 为 了 更加 有 趣 ,D irList1 展 现 给 用 户 的 对 话 是 一 个 属 性 表 ,通 常 叫 做 多 选 项 卡 的 对 话 框 。

属 性 表 可 以 向 用 户 展 示 大 量 的 信 息 , 这 就 很 好 地 解 决 了 对 话 框 过 分 拥 挤 的 问 题 , 但 从 本 质 上 讲 , 属 性 表 也 仅 仅 是 一 个 对 话 , 或 者 可 以 说 是 一 系 列 叫 做 页 面 的 对话 , 这 些 页 面 一 个 盖 着 另 一 个 , 你 可 以 像 设 计 其 他 对 话 一 样 用 对 话 编 辑 器 设 计 属性 表 的 每 页 。 RC 文 件 中 一 个 页 面 的 属 性 脚 本 看 上 去 与 普 通 的 对 话 是 一 样 的 , 只是 属 性 表 的 所 有 页 面 都 具 有 相 同 的 大 小 。当 程 序 调 用 PropertySheet API 函 数 创 建MFC CPropertySheet 对 象 的 时 候 , Windows 将 属 性 表 页 面 做 为 对 话 来 显 示 。

致 谢 - 图156

偶 然 情 况 下 ,你 可 能 会 遇 到 对 话 编 辑 器 的 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( 向 上 一 级 目 录 ) 的 大 按 钮 , 用 户 可 以 回 到上 一 级 目 录 。

致 谢 - 图157

图 5-15 DirList1 程 序 的 Location 和 Date 选项卡

D irList1 中 的 属 性 表 对 话 仅 用 到 了 五 种 控 件 类 型 : 推 压 按 钮 、单 选 按 钮 、列 表 框 、编 辑 控 件 和 微 调 框 。 如 果 你 对 这 些 控 件 的 安 装 方 式 感 兴 趣 , 请 打 开 D irList.rc 文件 , 并 且 通 过 双 击 下 图 所 示 的 一 个 对 话 标 识 符 来 启 动 对 话 编 辑 器 。

致 谢 - 图158

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 可 以 生 成 运 行 该 对 话 的 源 代 码 。 下 一 章 将 显 示 如 何 去 做 。