COM编程入门-.pdf

上传人:索**** 文档编号:76258720 上传时间:2023-03-08 格式:PDF 页数:24 大小:274.99KB
返回 下载 相关 举报
COM编程入门-.pdf_第1页
第1页 / 共24页
COM编程入门-.pdf_第2页
第2页 / 共24页
点击查看更多>>
资源描述

《COM编程入门-.pdf》由会员分享,可在线阅读,更多相关《COM编程入门-.pdf(24页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、1 COM编 程 入 门第 一 部 分 什 么 是 COM,如 何 使 用 COM 本 文 的 目 的 是 为 刚 刚 接 触 COM 的 程 序 员 提 供 编 程 指 南,并 帮 助 他 们 理 解 COM 的 基 本 概 念。内 容 包 括 COM 规 范 简 介,重 要 的 COM 术 语 以 及 如 何 重 用 现 有 的 COM 组 件。本 文 不 包 括 如 何 编写 自 己 的 COM 对 象 和 接 口。COM 即 组 件 对 象 模 型,是 Component Object Model 取 前 三 个 字 母 的 缩 写,这 三 个 字 母 在当 今 W indows的 世

2、 界 中 随 处 可 见。随 时 涌 现 出 来 的 大 把 大 把 的 新 技 术 都 以 COM 为 基 础。各 种文 档 中 也 充 斥 着 诸 如 COM 对 象、接 口、服 务 器 之 类 的 术 语。因 此,对 于 一 个 程 序 员 来 说,不 仅要 掌 握 使 用 COM 的 方 法,而 且 还 要 彻 底 熟 悉 COM 的 所 有 一 切。本 文 由 浅 入 深 描 述 COM 的 内 在 运 行 机 制,教 你 如 何 使 用 第 三 方 提 供 的 COM 对 象(以W indows 外 壳 组 件 Shell 为 例)。读 完 本 文 后,你 就 能 掌 握 如 何

3、使 用 W indows操 作 系 统 中 内 建的 组 件 和 第 三 方 提 供 的 COM 对 象。本 文 假 设 你 精 通 C+语 言。在 例 子 代 码 中 使 用 了 一 点 MFC 和 ATL,如 果 你 不 熟 悉 MFC 和ATL 也 没 关 系,本 文 会 对 这 些 代 码 进 行 完 全 透 彻 的 解 释。本 文 包 括 以 下 几 个 部 分:COM 到 底 是 什 么?CO M 标 准 的 要 点 介 绍,它 被 设 计 用 来 解 决 什 么 问 题基 本 元 素 的 定 义 COM 术 语 以 及 这 些 术 语 的 含 义使 用 和 处 理 COM 对 象

4、 如 何 创 建、使 用 和 销 毁 COM对 象基 本 接 口 描 述 IUnknown 基 本 接 口 及 其 方 法掌 握 串 的 处 理 在 COM 代 码 中 如 何 处 理 串应 用 COM 技 术 例 子 代 码,举 例 说 明 本 文 所 讨 论 的 所 有 概 念处 理 HRES ULT HRES ULT 类 型 描 述,如 何 监 测 错 误 及 成 功 代 码COM 到 底 是 什 么简 单 地 说,COM 是 一 种 跨 应 用 和 语 言 共 享 二 进 制 代 码 的 方 法。与C+不 同,它 提 倡 源 代 码重 用。ATL 便 是 一 个 很 好 的 例 证。源

5、 码 级 重 用 虽 然 好,但 只 能 用 于 C+。它 还 带 来 了 名 字 冲 突的 可 能 性,更 不 用 说 不 断 拷 贝 重 用 代 码 而 导 致 工 程 膨 胀 和 臃 肿。W indows使 用 DLLs 在 二 进 制 级 共 享 代 码。这 也 是 W indows程 序 运 行 的 关 键 重 用kernel32.dll,user32.dll 等。但 DLLs 是 针 对 C 接 口 而 写 的,它 们 只 能 被 C 或 理 解 C 调 用 规 范 的语 言 使 用。由 编 程 语 言 来 负 责 实 现 共 享 代 码,而 不 是 由 DLLs 本 身。这 样

6、的 话 DLLs 的 使 用 受 到限 制。MFC 引 入 了 另 外 一 种 MFC 扩 展 DLLs 二 进 制 共 享 机 制。但 它 的 使 用 仍 受 限 制 只 能 在 MFC 程序 中 使 用。COM 通 过 定 义 二 进 制 标 准 解 决 了 这 些 问 题,即 COM 明 确 指 出 二 进 制 模 块(DLLs 和 EXEs)必 须 被 编 译 成 与 指 定 的 结 构 匹 配。这 个 标 准 也 确 切 规 定 了 在 内 存 中 如 何 组 织 COM 对 象。COM定 义 的 二 进 制 标 准 还 必 须 独 立 于 任 何 编 程 语 言(如 C+中 的 命

7、 名 修 饰)。一 旦 满 足 了 这 些 条 件,就 可 以 轻 松 地 从 任 何 编 程 语 言 中 存 取 这 些 模 块。由 编 译 器 负 责 所 产 生 的 二 进 制 代 码 与 标 准 兼 容。这 样 使 后 来 的 人 就 能 更 容 易 地 使 用 这 些 二 进 制 代 码。在 内 存 中,COM 对 象 的 这 种 标 准 形 式 在 C+虚 函 数 中 偶 尔 用 到,所 以 这 就 是 为 什 么 许 多COM 代 码 使 用 C+的 原 因。但 是 记 住,编 写 模 块 所 用 的 语 言 是 无 关 的,因 为 结 果 二 进 制 代 码 为所 有 语 言

8、可 用。此 外,COM 不 是 W in32特 有 的。从 理 论 上 讲,它 可 以 被 移 植 到 Unix 或 其 它 操 作 系 统。但是 我 好 像 还 从 来 没 有 在 W indows以 外 的 地 方 听 说 过 COM。基 本 元 素 的 定 义我 们 从 下 往 上 看。接 口 只 不 过 是 一 组 函 数。这 些 函 数 被 称 为 方 法。接 口 名 字 以 大 写 的 I 开头,例 如 C+中 的 IShellL ink,接 口 被 设 计 成 一 个 抽 象 基 类,其 中 只 有 纯 粹 的 虚 拟 函 数。接 口 可 以 从 其 它 接 口 继 承,这 里

9、所 说 的 继 承 的 原 理 就 好 像 C+中 的 单 继 承。接 口 是 不 允 许多 继 承 的。2 coclass(简 称 组 件 对 象 类 component object class)被 包 含 在 DLL 或 EXE 中,并 且 包 含 着 一个 或 者 多 个 接 口 的 代 码。组 件 对 象 类(coclasss)实 现 这 些 接 口。COM 对 象 在 内 存 中 表 现 为 组件 对 象 类(coclasss)的 一 个 实 例。注 意 COM“类”和 C+“类”是 不 相 同 的,尽 管 常 常 COM 类 实现 的 就 是 一 个 C+类。/哪 里 不 同?C

10、OM 服 务 器 是 包 含 了 一 个 或 多 个 coclass的 二 进 制(DLL 或 EXE)。注 册(Registration)是 创 建 注 册 表 入 口 的 一 个 过 程,告 诉 W indows 操 作 系 统 COM 服 务 器 放 在什 么 位 置。取 消 注 册(Unregistration)则 相 反 从 注 册 表 删 除 这 些 注 册 入 口。GUID(谐 音 为“flu id”,意 思 是 全 球 唯 一 标 示 符 globally un ique identifier)是 个 128 位 的 数字。它 是 一 种 独 立 于 COM 编 程 语 言 的

11、 标 示 方 法。每 一 个 接 口 和 coclas s 有 一 个 GU ID。因 为 每 一个 GU ID 都 是 全 球 唯 一 的,所 以 避 免 了 名 字 冲 突(只 要 你 用 COM AP I 创 建 它 们)。有 时 你 还 会碰 到 另 一 个 术 语 UU ID(意 思 也 是 全 球 唯 一 标 示 符 univ ersally unique identifier)。UU IDs和 GU IDs 在 实 际 使 用 时 的 用 途 是 一 样 的。类 ID 或 者 CLSID 是 命 名 coclass的 GU ID。接 口 ID 或 者 IID 是 命 名 接 口

12、的 GUID。在 COM 中 广 泛 地 使 用 GU ID 有 两 个 理 由:1.GUIDs 只 是 简 单 的 数 字,任 何 编 程 语 言 都 可 以 对 之 进 行 处 理;2.GUIDs 可 以 在 任 何 机 器 上 被 任 何 人 创 建,一 旦 完 成 创 建,它 就 是 唯 一 的。因 此,COM 开 发 人 员 可 以 创 建 自 己 特 有 的 GUIDs 而 不 会 与 其 它 开 发 人 员 所 创 建 的 GUIDs 有 冲 突。这样 就 消 除 了 集 中 授 权 发 布 GU IDs 的 必 要。/不 同 的 机 器 如 何 避 免 GUID的 冲 突?HR

13、ESULT是 COM 用 来 返 回 错 误 和 成 功 代 码 的 整 型 数 字。除 此 之 外,别 无 它 意,虽 然 以 H作 前 缀,但 没 有 句 柄 之 意。下 文 会 对 它 有 更 多 的 讨 论。最 后,COM库 是 在 你 使 用 COM时 与 你 交 互 的 操 作 系 统 的 一 部 分,它 常 常 指 的 就 是 COM本 身。但 是 为 了 避 免 混 淆 才 分 开 描 述 的。使 用 和 处 理 COM 对 象每 一 种 语 言 都 有 其 自 己 处 理 对 象 的 方 式。例 如,C+是 在 栈 中 创 建 对 象,或 者 用 new 动 态分 配。因 为

14、 COM必 须 独 立 于 语 言,所 以 COM库 为 自 己 提 供 对 象 管 理 例 程。下 面 是 对 COM 对象 管 理 和 C+对 象 管 理 所 做 的 一 个 比 较:创 建一个 新对象C+中,用 new 操 作 符,或 者 在 栈 中 创 建 对 象。COM 中,调 用 COM 库 中 的 API。删 除对象C+中,用 delete操 作 符,或 将 栈 对 象 踢 出。COM中,所 有 的 对 象 保 持 它 们 自 己 的 引 用 计 数。调 用 者 必 须 通 知 对 象 什 么 时 候 用 完 这 个 对 象。当 引 用 计 数 为 零 时,COM对 象 将 自

15、己 从 内 存 中 释 放。由 此 可 见,对 象 处 理 的 两 个 阶 段:创 建 和 销 毁,缺 一 不 可。当 创 建 COM对 象 时 要 通 知 COM库 使 用 哪 一 个 接 口。如 果 这 个 对 象 创 建 成 功,COM库 返 回 所 请 求 接 口 的 指 针。然 后 通 过 这 个 指针 调 用 方 法,就 像 使 用 常 规 C+对 象 指 针 一 样。创 建 COM 对 象为 了 创 建 COM对 象 并 从 这 个 对 象 获 得 接 口,必 须 调 用 COM库 的 API函 数,CoCreateInstance()。其 原 型 如 下:HRESULT CoC

16、reateInstance(REFCLSID rclsid,3 LPUNKNOWN pUnkOuter,DWORD dwClsContext,REFIID riid,LPVOID*ppv);以 下 是 参 数 解 释:rclsid:coclass的 CLSID,例如,可 以 传 递 CLSID_ShellLink创 建一个 COM 对象 来建 立快 捷 方 式。pUnkOut er:这 个参 数 只 用于 COM对 象 的聚合,利 用它向 现 有 的 coclass添 加新 方 法。参 数值 为 null表 示不使 用聚 合。/不 明白 啊?dwClsContext:表示 所使 用 COM 服

17、 务器 的 种类。本 文使 用 的 是最 简 单 的 COM 服 务器,一 个进 程 内(in-process)DLL,所 以传 递的 参数 值为 CLSCTX_INPROC_SERVER。注 意这 里不要 随意使 用 CLSCTX_ALL(在 ATL 中,它 是个 缺 省值),因 为在 没有 安装 DCOM 的 Windows95 系 统 上 会导 致失败。riid:请 求接 口的 IID。例如,可 以 传递 IID_IShellLink获得 IShellLink接口 指针。ppv:接 口指针 的 地 址。COM库通过 这 个 参数 返 回 请求 的接 口。当 你 调 用 CoCreateI

18、nstance()时,它 负 责 在 注 册 表 中 查 找 COM 服 务 器 的 位 置,将 服 务 器 加载 到 内 存,并 创 建 你 所 请 求 的 coclass实 例。以 下 是 一 个 调 用 的 例 子,创 建 一 个 CLSID_ShellLink对 象 的 实 例 并 请 求 指 向 这 个 对 象 IShellLink 接 口 指 针。HRESULT hr;IShellLink*pISL;hr=CoCreateInstance(CLSID_ShellLink,/coclass 的 CLSID NULL,/不是 用聚 合CLSCTX_INPROC_SERVER,/服 务器

19、 类 型IID_IShellLink,/接 口 的 IID(void*)&pISL);/指 向 接 口的指 针if(SUCCEEDED(hr)/用 pISL 调 用方 法 else /不 能创 建 COM 对 象,hr 为 出 错代 码 首 先 声 明 一 个 接 受 CoCreateInstance()返 回 值 的 HRESULT和 IShellLink 指 针。调 用CoCreateInstance()来 创 建 新 的 COM 对 象。如 果 hr 接 受 到 一 个 表 示 成 功 的 代 码,则 SUCCEEDED宏 返 回 TRUE,否 则 返 回 FALSE。FAILED是 一

20、 个 与 SUCCEEDED对 应 的 宏 用 来 检 查 失 败 代 码。删 除 COM 对 象前 面 说 过,你 不 用 释 放 COM 对 象,只 要 告 诉 它 们 你 已 经 用 完 对 象。IUnknown是 每 一 个COM对 象 必 须 实 现 的 接 口,它 有 一 个 方 法,Release()。调 用 这 个 方 法 通 知 CO M 对 象 你 不 再需 要 对 象。一 旦 调 用 了 这 个 方 法 之 后,就 不 能 再 次 使 用 这 个 接 口,因 为 这 个 COM 对 象 可 能 从 此就 从 内 存 中 消 失 了。如 果 你 的 应 用 程 序 使 用

21、许 多 不 同 的 COM 对 象,因 此 在 用 完 某 个 接 口 后 调 用 Release()就 显得 非 常 重 要。如 果 你 不 释 放 接 口,这 个 COM 对 象(包 含 代 码 的 DLLs)将 保 留 在 内 存 中,这 会4 增 加 不 必 要 的 开 销。如 果 你 的 应 用 程 序 要 长 时 间 运 行,就 应 该 在 应 用 程 序 处 于 空 闲 期 间 调 用CoFreeUnusedLibraries()API。这 个 API将 卸 载 任 何 没 有 明 显 引 用 的 COM服 务 器,因 此 这也 降 低 了 应 用 程 序 使 用 的 内 存 开

22、 销。继 续 用 上 面 的 例 子 来 说 明 如 何 使 用 Releas e():/像上 面一 样 创 建 COM 对 象,然 后,if(SUCCEEDED(hr)/用 pISL 调 用方 法/通 知 COM 对象 不再 使 用它pISL-Release();接 下 来 将 详 细 讨 论 IUnknown接 口。基 本 接 口 IUnknown每 一 个 COM 接 口 都 派 生 于 IUnknown。这 个 名 字 有 点 误 导 人,其 中 没 有 未 知(Unknown)接 口 的 意 思。它 的 原 意 是 如 果 有 一 个 指 向 某 COM 对 象 的 IUnknown

23、指 针,就 不 用 知 道 潜 在 的 对象 是 什 么,因 为 每 个 COM 对 象 都 实 现 IUnknown。IUnknown 有 三 个 方 法:/接 口 本 身 不 就 是 方 法 吗?AddRef()通 知 COM 对 象 增 加 它 的 引 用 计 数。如 果 你 进 行 了 一 次 接 口 指 针 的拷 贝,就 必 须 调 用 一 次 这 个 方 法,并 且 原 始 的 值 和 拷 贝 的 值 两 者 都 要 用 到。在 本 文 的 例 子 中 没有 用 到 AddRef()方 法;Releas e()通 知 COM 对 象 减 少 它 的 引 用 计 数。参 见 前 面

24、的 Release()示 例 代码 段;Query Interface()从 COM 对 象 请 求 一 个 接 口 指 针。当 coclass实 现 一 个 以 上的 接 口 时,就 要 用 到 这 个 方 法;前 面 已 经 看 到 了 Releas e()的 使 用,但 如 何 使 用 Qu ery Interface()呢?当 你 用CoCreateInstance()创 建 对 象 的 时 候,你 得 到 一 个 返 回 的 接 口 指 针。如 果 这 个 COM 对 象 实 现 一个 以 上 的 接 口(不 包 括 IUnknown),你 就 必 须 用 Query Interfa

25、ce()方 法 来 获 得 任 何 你 需 要 的 附加 的 接 口 指 针。Query Interface()的 原 型 如 下:HRESULT IUnknown:QueryInterface(REFIID iid,void*ppv);以 下 是 参 数 解 释:iid:所 请求的 接 口 的 IID。ppv:接 口指针 的 地 址,QueryInterface()通过 这 个 参数 在 成功 时返 回这 个 接 口。让 我 们 继 续 外 壳 链 接 的 例 子。它 实 现 了 IShellLink 和 IPer sistF ile 接 口。如 果 你 已 经 有 一 个IShellLin

26、k 指 针,p ISL,可 以 从 COM 对 象 请 求 IPers istF ile 接 口:HRESULT hr;IPersistFile*pIPF;hr=pISL-QueryInterface(IID_IPersistFile,(void*)&pIPF);然 后 使 用 SUCCEEDED宏 检 查 hr 的 值 以 确 定 Query Interface()的 调 用 情 况,如 果 成 功 的 话你 就 可 以 象 使 用 其 它 接 口 指 针 那 样 使 用 新 的 接 口 指 针,pIPF。但 必 须 记 住 调 用 p IPF-Release()通 知 COM 对 象 已

27、经 用 完 这 个 接 口。仔 细 做 好 串 处 理5 这 一 部 分 将 花 点 时 间 来 讨 论 如 何 在 COM 代 码 中 处 理 串。如 果 你 熟 悉 Unicode 和 ANS I,并知 道 如 何 对 它 们 进 行 转 换 的 话,你 就 可 以 跳 过 这 一 部 分,否 则 还 是 读 一 下 这 一 部 分 的 内 容。不 管 什 么 时 候,只 要 COM 方 法 返 回 一 个 串,这 个 串 都 是 Un icode串(这 里 指 的 是 写 入 COM规 范 的 所 有 方 法)。Un icode是 一 种 字 符 编 码 集,类 似 ASCII,但 用

28、两 个 字 节 表 示 一 个 字 符。如果 你 想 更 好 地 控 制 或 操 作 串 的 话,应 该 将 它 转 换 成 TCHAR 类 型 串。TCHAR 和 以 _t 开 头 的 函 数(如 _tcscpy())被 设 计 用 来 让 你 用 相 同 的 源 代 码 处 理 Unicode和ANS I 串。在 大 多 数 情 况 下 编 写 的 代 码 都 是 用 来 处 理 ANS I 串 和 ANSI WindowsAPIs,所 以 在下 文 中,除 非 另 外 说 明,我 所 说 的 字 符/串 都 是 指 TCHAR 类 型。你 应 该 熟 练 掌 握 TCHAR 类 型,尤

29、其 是 当 你 阅 读 其 他 人 写 的 有 关 代 码 时,要 特 别 注 意 TCHAR 类 型。当 你 从 某 个 COM 方 法 返 回 得 到 一 个 Unicode串 时,可 以 用 下 列 几 种 方 法 之 一 将 它 转 换 成char类 型 串:1.调 用WideCharToMult iByte()API;2.调 用 CRT 函 数 wcstombs();3.使 用 CString 构 造 器 或 赋 值 操 作(仅 用 于 MFC);4.使 用 ATL 串 转 换 宏;WideCharToMultiByte()你 可 以 用 W ideCharToMultiBy te(

30、)将 一 个 Un icode串 转 换 成 一 个 ANS I 串。此 函 数 的 原 型 如 下:int WideCharToMultiByte(UINT CodePage,DWORD dwFlags,LPCWSTR lpWideCharStr,int cchWideChar,LPSTR lpMultiByteStr,int cbMultiByte,LPCSTR lpDefaultChar,LPBOOL lpUsedDefaultChar);以 下 是 参 数 解 释:CodePage:Unicode字 符 转 换 成 的 代 码 页。你 可 以 传 递 CP_ACP 来 使 用 当 前

31、的 ANSI代 码 页。代 码 页 是 256个 字 符 集。字 符 0 127 与 ANSI 编 码 一 样。字 符 128 255与 ANSI字 符 不 同,它 可 以 包 含 图 形 字 符 或 者 读 音 符 号。每 一 种 语 言 或 地 区 都 有 其 自 己 的 代 码 页,所 以使 用 正 确 的 代 码 页 对 于 正 确 地 显 示 重 音 字 符 很 重 要。dwF lags:dwF lags 确 定 Windows如 何 处 理“复 合”Unicode字 符,它 是 一 种后 面 带 读 音 符 号 的 字 符。如 就 是 一 个 复 合 字 符。如 果 这 些 字 符

32、 在 CodePage参 数 指 定 的 代 码 页 中,不 会 出 什 么 事。否 则,W indows必 须 对 之 进 行 转 换。传 递 WC_COMPOSITECHECK使 得 这 个 API检 查 非 映 射复 合 字 符。传 递 WC_SEPCHARS使 得 W indows将 字 符 分 为 两 段,即 字 符 加 读 音,如 e。传 递 WC_DISCARDNS使 得 W indows丢 弃 读 音 符 号。传 递 W C_DEFAULTCHAR使 得 W indows用 lpDefaultChar参 数 中 说 明 的 缺 省 字 符 替 代 复 合 字 符。缺 省 行 为

33、 是 WC_SEPCHARS。lpW ideCharStr 要 转 换 的 Unicode串。cchW ideChar lpWideCharStr在 Unicode 字 符 中 的 长 度。通 常 传 递-1,表 示 这 个串 是 以 0 x00结 尾。lp Mu lt iBy teStr 接 受 转 换 的 串 的 字 符 缓 冲cbMultiByte lp Mu lt iBy teStr的 字 节 大小。6 lpDefaultChar 可 选 当 dwFlags包 含 W C_COMPOSITECHECK|WC_DEFAULTCHAR并 且 某 个 Unicode字 符 不 能 被 映 射

34、 到 同 等 的 ANSI 串 时 所 传 递 的 一 个 单 字 符ANS I 串,包 含 被 插 入 的“缺 省”字 符。可 以 传 递 NULL,让 AP I 使 用 系 统 缺 省 字 符(一 种 写 法 是一 个 问 号)。lpUs edDefaultChar 可 选 指 向 BOOL 类 型 的 一 个 指 针,设 置 它 来 表 示 是 否 缺 省字 符 曾 被 插 入 ANS I 串。可 以 传 递 NULL 来 忽 略 这 个 参 数。我 自 己 都 有 点 晕 菜 了!,万 事 开 头 难 啊,不 搞 清 楚 这 些 东 西 就 很 难 搞 清 楚 COM 的 串处 理。何

35、 况 文 档 中 列 出 的 比 实 际 应 用 的 要 复 杂 得多。下 面 就 给 出 了 如 何 使 用 这 个 API 的 例 子:/假设 已经 有 了 一个 Unicode 串wszSomeString.char szANSIString MAX_PATH;WideCharToMultiByte(CP_ACP,/ANSI 代 码 页WC_COMPOSITECHECK,/检查 重音 字符wszSomeString,/原 Unicode 串-1,/-1 意思 是串 以 0 x00 结 尾szANSIString,/目 的 char字符串sizeof(szANSIString),/缓 冲大

36、 小NULL,/肥 缺省 字 符 串NULL);/忽 略 这 个参 数调 用 这 个 函 数 后,szANS IStr ing 将 包 含 Un icode串 的 ANS I 版 本。调 用 这 个 函 数 后,sz ANS IStr ing将 包 含 Unicode串 的 ANS I 版 本。wcstombs()这 个 CRT 函 数 wcstombs()是 个 简 化 版,但 它 终 结 了 W ideCharToMultiBy te()的 调 用,所 以 最 终结 果 是 一 样 的。其 原 型 如 下:size_t wcstombs(char*mbstr,const wchar_t*w

37、cstr,size_t count);以 下 是 参 数 解 释:mbstr:接受结 果 ANSI 串 的字 符(char)缓冲。wcstr:要转换 的 Unicode串。count:mbstr参数 所 指 的缓 冲大小。wcstombs()在 它 对 WideCharToMultiBy te()的 调 用 中 使 用 W C_COMPOSITECHECK|WC_SEPCHARS标 志。用 wcstombs()转 换 前 面 例 子 中 的 Unicode串,结 果 一 样:wcstombs(szANSIString,wszSomeString,sizeof(szANSIString);CSt

38、ring MFC 中 的 CString包 含 有 构 造 函 数 和 接 受 Un icode串 的 赋 值 操 作,所 以 你 可 以 用 CString来 实 现转 换。例 如:/假设 有一 个 Unicode串 wszSomeString.CString str1(wszSomeString);/用 构造 器 转 换CString str2;str2=wszSomeString;/用赋 值操 作 转 换ATL 宏7 ATL有 一 组 很 方 便 的 宏 用 于 串 的 转 换。W2A()用 于 将 Unicode串 转 换 为 ANSI串(记 忆方 法 是“wide to ANSI”宽

39、 字 符 到 ANSI)。实 际 上 使 用 OLE2A()更 精 确,“OLE”表 示 的 意思 是 COM串 或 者 OLE 串。下 面 是 使 用 这 些 宏 的 例 子:#include /还是 假设 有 一 个 Unicode串 wszSomeString.char szANSIString MAX_PATH;USES_CO NVERSION;/声 明 这 个 宏 要使 用 的 局部 变量lstrcpy(szANSIString,OLE2A(wszSomeString);OLE2A()宏“返 回”转 换 的 串 的 指 针,但 转 换 的 串 被 存 储 在 某 个 临 时 栈 变

40、量 中,所 以 要 用lstrcpy()来 获 得 自 己 的 拷 贝。其 它 的 几 个 宏 是 W2T()(Unicode 到TCHAR)以 及 W 2CT()(Unicode到 常 量 TCHAR 串)。有 个 宏 是 OLE2CA()(Unicode到 常 量 char 串),可 以 被 用 到 上 面 的 例 子 中,OLE2CA()实际 上 是 个 更 正 宏,因 为 lstrcpy()的 第 二 个 参 数 是 一 个 常 量 char*,关 于 这 个 问 题 本 文 将 在 以 后 作详 细 讨 论。另 一 方 面,如 果 你 不 想 做 以 上 复 杂 的 串 处 理,尽

41、管 让 它 还 保 持 为 Unicode串,如 果 编 写 的是 控 制 台 应 用 程 序,输 出/显 示 Un icode串 时 应 该 用 全 程 变 量 std:wcout,如:wcout wszSomeString;但 是 要 记 住,std:wcout只 认 Unicode,所 以 你 要 是“正 常”串 的 话,还 得 用 std:cout输 出/显 示。对 于 Unicode串 文 字 量,要 使 用 前 缀 L 标 示,如:wcout LThe Oracle says.endl GetWallpaper(wszWallpaper,MAX_PATH,0);if(SUCCEED

42、ED(hr)/4.如果GetWallpaper()成功,则 输出它 返回 的 文 件名 字。/注 意这 里使 用 wcout 来 显示 Unicode 串 wszWallpaper.wcout 是/Unicode 专 用,功 能 与 cout.相 同。wcout LWallpaper path is:n wszWallpaper endl endl;else cout _T(GetWallpaper()failed.)endl Release();else cout _T(CoCreateInstance()failed.)endl SetPath(sWallpaper);if(SUCCEED

43、ED(hr)/4.获取 这 个 对象 的 第 二个 接口(IPersistFile)。hr=pISL-QueryInterface(IID_IPersistFile,(void*)&pIPF);if(SUCCEEDED(hr)/5.调 Save()方 法保 存 某 个文 件 得 快捷 方式。第 一 个参 数是/Unicode 串。hr=pIPF-Save(LC:wallpaper.lnk,FALSE);/6a.释放 IPersistFile 接口。10 pIPF-Release();/6.释 放 IShellLink 接 口。pISL-Release();/输出 错误 信 息 部分 这 里 省

44、略。/7.收 回 COM 库。MFC 程序不 用这 一步,它 自动 完成。CoUninitialize();处 理HRESULT这 一 部 分 准 备 用 SUCCEEDED 和FAILED宏 进 行 一 些 简 单 的 出 错 处 理。主 要 是 深 入 研 究 从COM 方 法 返 回 的 HRESULT,以 便 达 到 完 全 理 解 和 熟 练 应 用。HRESULT是 个 32 位 符 号 整 数,其 非 负 值 表 示 成 功,负 值 表 示 失 败。HRESULT有 三 个 域:程 度 位(表 示 成 功 或 失 败),功 能 码 和 状 态 码。功 能 码 表 示 HRESUL

45、T来 自 什 么 组 件 或 程 序。微软 给 不 同 的 组 件 多 赋 予 功 能 码,如:COM、任 务 调 度 程 序 等 都 有 功 能 码。功 能 码 是 个 16 位 的 值,仅 此 而 已,没 有 其 它 内 在 含 义;它 在 数 字 和 意 义 之 间 是 随 意 关 联 的;类 似 GetLastError()返 回 的值。如 果 你 在 winerror.h头 文 件 中 查 找 错 误 代 码,会 看 到 许 多 按 照 功 能 _ 程 度 _ 描 述 命 名 规范 列 出 的 HRESULT值,由 组 件 返 回 的 通 用 的 HRESULT(类 似 E_OUTO

46、FMEMORY)在 名 字 中 没有 功 能 码。如:REGDB_E_READREGDB:功 能 码=REGDB,指“注 册 表 数 据 库(reg istry database)”;程 度=E 意 思 是 错 误(error);描 述=READREGDB 是 对 错 误 的 描 述(意 思 是 不 能 读 注 册 表 数 据 库)。S_OK:没 有 功 能 码 通 用(gener ic)HRESULT;程 度=S;表 示 成 功(success);OK 是 状 态 描 述 表 示 一 切 都 好(ev ery things OK)。好 在 有 一 种 比 察 看 winerror.h文 件

47、更 容 易 的 方 法 来 确 定 HRESULT的 意 思。使 用 VC 提 供 的错 误 查 找 工 具(Error Lookup)可 以 轻 松 查 到 为 HRESULT内 建 功 能 码。例 如,假 设 你 在CoCreateInstance()之 前 忘 了 调 用 CoIn it ializ e()。CoCreateInstance()返 回 的 值 是 0 x 800401F0。你 只 要 将 这 个 值 输 入 到 错 误 查 找 工 具 按“Look Up”按 钮,便 可 以 看 到 错 误 信 息 描 述“尚 未 调 用CoInitialize”如 下 图 所 示:11

48、另 外 一 种 查 找 HRESULT描 述 的 方 法 是 在 调 试 器 中。假 设 有 一 个 HRESULT变 量 是 hres。在W atch 窗 口 的 左 边 框 中 输 入“hres,hr”,表 示 想 要 看 的 值,“hr”便 会 通 知 VC 显 示 HRESULT所 描述 的 值。如 下 图 所 示:通 过 以 上 的 讨 论,想 必 你 对 COM 编 程 有 了 初 步 的 认 识,本 文 第 二 部 分 将 探 讨 COM 的 内 部 机 制。教 你 如 何 用 C+编 写 自 己 的 接 口。COM编 程 入 门第 二 部 分 深 入 COM服 务 器本 文 为

49、 刚 刚 接 触 COM 的 程 序 员 提 供 编 程 指 南,解 释 COM 服 务 器 内 幕 以 及 如 何 用 C+编 写自 己 的 接 口。继 上 一 篇 COM 编 程 入 门 之 后,本 文 将 讨 论 有 关 COM 服 务 器 的 内 容,解 释 编 写 自己 的 COM 接 口 和 COM 服 务 器 所 需 要 的 步 骤 和 知 识,以 及 详 细 讨 论 当 COM 库 对 COM 服 务 器 进行 调 用 时,COM 服 务 器 运 行 的 内 部 机 制。如 果 你 读 过 上 一 篇 文 章。应 该 很 熟 悉 COM 客 户 端 是 怎 么 会 事 了。本

50、文 将 讨 论 COM 的 另 一端 COM 服 务 器。内 容 包 括 如 何 用 C+编 写 一 个 简 单 的 不 涉 及 类 库 的 COM 服 务 器。深 入 到 创建 COM 服 务 器 的 内 部 过 程,毫 无 遮 掩 地 研 究 那 些 库 代 码 是 充 分 理 解 COM 服 务 器 内 部 机 制 的 最好 方 法。本 文 假 设 你 精 通 C+并 掌 握 了 上 一 篇 文 章 所 讨 论 的 概 念 和 术 语。在 这 一 部 分 将 包 括 如 下 内 容:走 马 观 花 看 COM 服 务 器 描 述 COM 服 务 器 的 基 本 要 求服 务 器 生 命

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 技术标书

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com