Database 版 (精华区)

发信人: wodeji (西西), 信区: Database
标  题: [转载] PowerBuilder 开 发 系 列 谈 (20) 
发信站: 紫 丁 香 (Tue Sep 29 17:52:24 1998), 站内信件

【 以下文字转载自 Programming 讨论区 】
【 原文由 two 所发表 】
Email: sjhzyz@public.bta.net.cn 

        上 期 我 们 介 绍 了 调 用WindowsAPI 函 数 的 方 法, 本 期 我 们 继 续 介 绍 几 个 常
 用 的API 函 数。 

 一 个 简 单 的 文 件 拷 贝 例 程 

        Windows 操 作 系 统 在 象 文 件 操 纵 一 类 的 低 级 函 数 调 用 方 面 是 相 当 灵 活
 的。 而 在PowerBuilder 中 为 了 实 现 这 一 些 低 级 操 作, 开 发 者 们 必 须 用 第 三 方 开
 发 库( 如:FUNCkyforPowerBuilder 库) 或 用C 语 言 之 类 的 语 言 开 发 自 己 的 库, 这
 种 方 法 我 们 将 在 后 面 的 章 节 中 讨 论。 在 这 里, 我 们 首 先 展 示 如 何 通 过 调
 用WindowsAPI 函 数 实 现 简 单 而 又 常 用 的 低 级 操 作: 文 件 拷 贝。 

        使 用WindowsAPI 而 不 用 第 三 方 开 发 库 的 主 要 好 处 是, 如 果 这 是 您 所 要 的
 唯 一 的 低 级 操 作, 在 发 布 您 的 应 用 时 就 不 需 要 同 时 将 额 外 的 库 打 包 进 您 的
 应 用 中。 但 如 果 您 还 需 使 用 了 第 三 方 开 发 库 提 供 的 其 它 服 务, 为 简 单 起
 见, 您 使 用 第 三 方 开 发 库 所 提 供 的 例 程 可 能 要 更 方 便 些。 

 实 现: 首 先 声 明 下 列localexternal 函 数 

 Function  long  LZOpenFile(string  FileName,  REF ws_ofstruct  FileStructure,  
 uint  style) Library "lzexpand.dll"
 Function  long  CopyLZFile(uint  SourceHandle, uint  DestHandle)  
 Library  "lzexpand.dll"
 Function  long  LZClose (uint  FileHandle)  Library  "lzexpand.dll"
 ws_ofstruct的窗口级结构如下:
 Variable Name
 Data Type

 byte[1]
 char

 fixed_disk[1]
 char

 errorcode
 uint

 reserverd[4]
 char

 pathname[128]
 char键入下面的一个窗口级函数:
 wf_copy
 // 返 回:       boolean
 // 参 数:
         string  as_source
         string  as_dest
 long            ll_SourceFileHandle, ll_DestFileHandle, ll_result
 ws_ofstruct        lstr_SourceFileStructure, lstr_DestFileStructure
 // 打 开 源 文 件
 ll_SourceFileHandle = LZOpenFile ( as_source, lstr_SourceFileStructure, 0 )
 IF ll_SourceFileHandle = -1 THEN
         MessageBox ( " 程 序 错 误", " 无 法 打 开 文 件: " + as_source )
         Return FALSE
 END IF
 // 打 开 目 标 文 件
 ll_DestFileHandle = LZOpenFile ( as_dest, lstr_DestFileStructure, 4096 )
 IF ll_DestFileHandle = -1 THEN
         MessageBox ( " 程 序 错 误", " 无 法 创 建 文 件: " + as_dest )
         LZClose ( ll_SourceFileHandle )
         Return FALSE
 END IF
 // 拷 贝
 ll_result = CopyLZFile ( ll_SourceFileHandle, ll_DestFileHandle )
 IF li_result < 0 THEN
         MessageBox (" 程 序 错 误"," 无 法 拷 贝 文 件: " + as_source &
                 + " to file: " + as_dest )
         LZClose ( ll_SourceFileHandle )
         LZClose ( ll_DestFileHandle )
         Return FALSE
 END IF
 // 关 闭 文 件
 LZClose ( ll_SourceFileHandle )
 LZClose ( ll_DestFileHandle )
 Return TRUE

 工 作 原 理 

        Windows 所 带 的COMPRESS.EXE 是 一 个 处 理 采 用Lempel-ziv 算 法 压 缩 的 文 件 的
 可 执 行 文 件。 此 外Windows 内 部 还 包 含 了 几 个 处 理 这 一 算 法 的 函 数, 其 中 之
 一 是LzCopy 函 数, 该 函 数 可 以 用 来 生 成 解 压 缩 文 件。 同 时LzCopy 函 数 的 文 档
 中 还 说 明 了:“ 如 果 原 文 件 未 被 压 缩, 该 函 数 复 制 原 文 件。” 于 是LzCopy 函
 数 也 可 以 用 作 一 个 快 速 的 文 件 拷 贝 函 数。 

        LzCopy 函 数 有 两 个 参 数, 原 文 件 和 目 标 文 件 的 句 柄。 但 是 不 幸 的
 是,PowerBuilder 提 供 的FileOpen 函 数 返 回 的 文 件 句 柄 并 不 是LzCopy 所 需 要 的 那
 个 句 柄。 因 此, 如 果 调 用WindowsAPI 中 的LzCopy 函 数, 我 们 必 须 同 时 使
 用LzOpenFile 和LzClose 函 数, 以 确 保 获 得 所 需 要 的 文 件 句 柄。 

        LzFileOpen 函 数 有 三 个 参 数。 第 一 个 参 数 是 将 要 打 开 的 文 件 名, 第 二 个 参
 数 是 一 个 结 构, 这 个 结 构 将 在 函 数 调 用 时 填 入 有 关 这 个 文 件 的 信 息,
 与PowerBuilder 的FileOpen 函 数 一 样,LzFileOpen 函 数 可 以 创 建 或 打 开 一 个 文 件。
 该 函 数 的 第 三 个 参 数 指 明 该 函 数 是 被 用 来 以 只 读 方 式 打 开 文 件(0) 还 是 以
 只 写 方 式 创 建 文 件(4096)。 当 我 们 打 开 了 源 文 件 和 目 标 文 件 后, 我 们 只 要 简
 单 地 将 返 回 的 这 两 个 文 件 的 句 柄 传 递 给LzCopy 函 数, 就 可 实 现 文 件 拷 贝。
 最 后, 在 退 出 之 前 调 用LzClose 函 数 来 关 闭 这 两 个 文 件。 

 判 断 另 一 应 用 是 否 正 在 运 行 

        实 现: 首 先 声 明 下 列localexternal 函 数 

 Function uint  GetModuleHandle(string ModuleName)  Library "kernel"
 Function uint  GetModuleUsage(uint  ModuleName)  Library "kernel"
 Function uint  FindExecutable(string  FileName, &
         REF string Directory,  REF string Result)  Library "shell"
 键入下面的一个窗口级函数:
 fw_check_app_status
 // 返 回:       boolean
 // 参 数:       
 //      string  as_filename     
 //      string  as_directory
 integer li_size = 144, li_result
 string  ls_executable = Space ( li_size )
 integer li_module_usage
 uint            li_module_handle
 li_result = FindExecutable ( as_filename, as_directory, ls_executable )
 IF li_result < 32 THEN Return FALSE
 //如可执行文件已载入,获取这个执行文件的句柄
 li_module_handle = GetModuleHandle ( ls_executable )
 IF li_module_handle < 1 THEN
         // 没 有 载 入
         Return FALSE
 ELSE
         // 获 取 有 多 少 个 实 例 被 载 入
         li_module_usage = GetModuleUsage ( li_module_handle )
         Return TRUE
 END IF

 工 作 原 理 

        这 段 程 序 可 以 获 取 某 个 应 用 是 否 正 在 运 行。 

        我 们 用windowsAPI 中 的GetModueHandle 函 数 来 判 定 是 否 另 一 个 应 用 正 在 运
 行。 为 了 做 到 这 一 点, 我 们 需 要 知 道 文 件 的 全 路 径 名( 包 括 驱 动 器 名 和 路
 径)。 我 们 可 以 将 它 包 含 在 应 用 的INI 文 件 中, 也 可 以 通 过 写 入 源 代 码 将 它
 嵌 入 可 执 行 程 序。 这 里 向 大 家 推 荐 的 是 采 用 前 者 的 方 法, 这 样 作 可 使 应 用
 具 有 更 多 的 灵 活 性。 在 上 面 的 窗 口 级 函 数 中, 我 们 首 先 在 用 户 的Windows 目
 录 中 查 找win.ini 文 件。 因 为 对 于 我 们 需 要 进 行 查 询 的 应 用 与 特 定 扩 展 名 的 文
 档 之 间 的 关 联 被 记 录 在WIN.INI 文 件 中。 于 是 我 们 所 要 做 的 第 一 件 事 就 是
 在WIN.INI 文 档 中 查 找 这 一 关 联, 以 知 道 我 们 所 要 寻 找 应 用 是 从 通 过 哪 个 软
 件 装 入 的。 我 们 可 以 自 己 搜 索WIN.INI 文 件, 或 者 调 用WindowsAPI 中
 的FindExecutable 函 数 来 得 到 这 一 信 息。 这 里, 我 们 使 用 了 第 二 种 方 法。 我 们
 只 要 将 与 我 们 所 希 望 寻 找 的 可 执 行 程 序 相 关 联 的 一 个 文 件 的 文 件 名 与 路
 径 传 递 给FindExecutable 函 数, 就 会 得 到 该 可 执 行 程 序 的 全 路 径 名。 这 在 我 们
 判 断 出 该 可 执 行 程 序 没 有 在 运 行 以 后 启 动 该 程 序 时 是 很 有 用 的。 

        一 旦 获 得 了 可 执 行 程 序 的 全 路 径 名, 我 们 将 它 传 递 给GefModuleHandle 函
 数。 如 果 应 用 正 在 运 行, 则 该 函 数 返 回 应 用 的 句 柄。 如 果 返 回0, 说 明 应 用
 并 没 有 装 入, 此 时 退 出 函 数。 如 果 应 用 正 在 运 行, 我 们 将 获 得 的 应 用 的 句
 柄 传 递 给GetModuleUsage 函 数。 这 个 函 数 的 返 回 值 会 告 诉 我 们 这 个 应 用 有 几
 个 不 同 的 实 例。 在 我 们 的 例 子 中, 如 查 询 的 应 用 是MicrosoftWord, 该 应 用 是
 不 允 许 多 个 实 例 同 时 运 行, 但 象NotePad 这 样 的 应 用, 这 些 信 息 对 还 是 非 常
 有 用 的。 

        激 活 另 一 个 应 用 

        实 现: 首 先 声 明 下 列localexternal 函 数 

 Subroutine  BringWindowToTop(int hWnd)  Library "User"
 Function      uint  GetNextWindow(uint hWnd, int Flag)  Library "user"
 Function      uint  GetWindowText(uint hWnd, REF string Title, uint Size )
 Library  "user"
 Function      uint  ShowWindow(uint  hWnd, int  CmdShow)  Library "user"
 Function    integer  IsIconic(uint  hWnd)  Library "user"
 Function    integer  OPenIcon(uint hWnd)  Library  "user"
 Function    integer  FindWindow(string  ClassName,  string  WindowName)
 Library  "user"
 Function    integer  FindWindow(long    ClassName,  string  WindowName)  
 Library  "user"
 Function    integer  FindWindow(string  ClassName,  long    WindowName)  
 Library  "user"
 键入下面的一个窗口级函数:
 fw_make_app_active
 // 返 回:boolean
 // 参 数:
 //string   as_title
 boolean lb_cont = TRUE
 integer li_result, li_size
 string          ls_title
 uint            li_handle
 li_handle = Handle ( this )
 li_size = Len ( at_title ) + 1

 //li_handle = FindWindow ( 0, "Control Panel" )

 DO WHILE lb_cont
         li_handle = GetNextWindow ( li_handle, 1 )
         If li_handle = Handle ( this ) THEN Return FALSE
         li_result = GetWindowText ( li_handle, ls_title, li_size )
         IF ls_title = as_title THEN lb_cont = FALSE
 LOOP

 //ShowWindow ( li_handle, 3 )

 IF IsIconic ( li_handle ) > 0 THEN
         OpenIcon ( li_handle )  
 ELSE
         BringWindowToTop ( li_handle )
 END IF
 Return TRUE

 工 作 原 理 

        获 得 另 一 个 应 用 最 顶 层 窗 口 引 用 的 最 简 单 的 方 法 就 是 用FindWindow 函 数
 来 查 找。FindWindow 函 数 有 两 个 参 数: 您 要 找 的 窗 口 的 类 名 和 窗 口 的 标 题。
 注 意, 我 们 在localexternal 函 数 中 用 三 种 方 式 声 明 了 这 一 函 数。 这 是 因 为 您 可
 以 用null 作 为“ 通 配 符” 分 别 传 递 两 个 参 数。 为 了 传 递null, 您 必 须 将 参 数 类
 型 定 义 成long 型, 其 值 为0。 所 以 我 们 需 要 为 每 一 种 可 能 的 调 用 形 式 定 义 一
 个localexternal 函 数。 当 我 们 真 正 使 用 这 个 函 数 时,PowerBuilder 自 动 判 断 我 们 要
 用 哪 一 种 形 式。 

        例 如 在 窗 口 函 数fw_make_app_active 中, 我 们 可 以 用 这 种 手 段 使Findwindow 函
 数 搜 索ControlPanel 窗 口。 接 下 来 只 要 将Findwindow 函 数 返 回 的 窗 口 句 柄 传 递
 给BringWindowToTop 函 数 就 可 以 激 活ControlPanel 窗 口 了。 

        但 是 这 样 的 做 法 有 这 样 两 点 缺 陷: 

        您 并 不 总 是 知 道 某 个 应 用 的 顶 层 窗 口 的 全 名。 例 如 当 您 使
 用MicosotWord, 当 前 打 开 的 文 档 的 名 字 也 将 出 现 在 窗 口 的 标 题 上。 因 此, 这
 种 情 况 下, 寻 找 顶 层 窗 口 需 要 另 一 种 方 法。 

        如 果 您 希 望 激 活 的 窗 口 正 处 于 最 小 化 状 态,BringWindowToTop 函 数 将 不 能
 正 常 工 作。 

        实 际 上, 上 面 提 到 的 第 二 个 问 题 比 较 容 易 解 决。 我 们 加 入IsIconic 函 数 判
 断 我 们 所 要 激 活 的 窗 口 是 否 最 小 化。 如 果 不 是 最 小 化 状 态, 就 使
 用BringWindowsToTop 函 数。 如 果 是 最 小 化 状 态, 就 用OpenIcon 函 数 来 激 活 该 窗
 口。 这 种 方 法 只 假 定 我 们 想 以 窗 口 最 小 化 前 的 大 小 及 位 置 显 示 该 窗 口。 我
 们 也 可 以 用ShoWindow 函 数 来 对 要 显 示 的 其 它 应 用 的 窗 口 施 以 更 多 的 控 制。 

        本 例 中, 我 们 传 送 一 个 参 数 使 被 激 活 窗 口 以 最 大 化 方 式 显 示。 如 果 您
 想 以 不 同 的 方 式 激 活 窗 口, 请 参 照 下 表 的 参 数 对 应: 

        0 
        隐 藏 窗 口 

        1 
        以 窗 口 原 来 的 大 小 和 位 置( 如 果 当 前 窗 口 处 于 最 大 化 或 最 小 化 状 态) 并
 激 活 该 窗 口( 与 值 相 同) 

        2 
        以 最 小 化 方 式 显 示 并 激 活 窗 口 

        3 
        以 最 大 化 方 式 显 示 并 激 活 窗 口 

        4 
        以 窗 口 最 近 一 次 的 大 小 和 位 置 显 示 但 不 激 活 窗 口 

        5 
        以 窗 口 最 近 一 次 的 大 小 和 位 置 显 示 并 激 活 窗 口 

        6 
        最 小 化 窗 口 并 在 系 统 列 表 中 激 活 顶 层 窗 口 

        7 
        最 小 化 窗 口 但 不 激 活 窗 口( 保 持 当 前 窗 口 激 活) 

        8 
        以 窗 口 的 当 前 状 态 显 示 但 并 不 激 活 它( 保 持 当 前 窗 口 激 活) 

        9 
        恢 复 窗 口 原 先 的 大 小 和 位 置( 如 果 窗 口 处 于 最 小 化 或 最 大 化 状 态) 并 激
 活 它 解 决 第 二 个 问 题 时, 我 们 声 明 了 另 外 两 个 函 数,GetNextWindow
 和GetWindowsText。 如 果 我 们 将 一 个 窗 口 句 柄 传 递 给GetNextWindow 函 数, 它 将
 在 父 窗 口 所 属 的 所 有 子 窗 口 之 间 循 环。 如 果 将 一 个 顶 层 窗 口 句 柄 传 递 给 该
 函 数, 该 函 数 将 在 所 有 顶 层 窗 口 之 间 循 环。 我 们 希 望 得 到 的 是 后 一 种 方
 式, 所 以 我 们 首 先 要 获 取 自 己 应 用 的 顶 层 窗 口 句 柄。 

        当 我 们 在 顶 层 窗 口 之 间 循 环 时, 用GetWindowText 函 数 返 回 它 们 的 标 题。
 这 个 函 数 有 三 个 参 数, 窗 口 句 柄, 一 个 用 以 返 回 标 题 的 字 符 串 以 及 返 回 字
 符 串 的 最 大 长 度。 我 们 要 好 好 利 用 最 后 一 个 参 数, 因 为 我 们 并 不 想 要 匹 配
 整 个 窗 口 标 题, 而 是 要 匹 配 能 保 证 我 们 发 现 所 要 寻 找 的 窗 口 的 长 度。 例
 如, 如 果 我 们 将“MicrosoftWord” 传 递 给 这 个 窗 口 函 数 时, 这 个 函 数 判 断 文
 本 的 长 度 并 将 它 加1, 这 样 只 将 我 们 将 要 比 较 的 串 的 长 度 传 递 给
 了GetWindowText 函 数, 该 函 数 在 顶 层 窗 口 之 间 循 环, 寻 找 以 该 字 符 串 开 头 的
 窗 口。 如 果 我 们 发 现 了 一 个 匹 配, 就 设 置 结 束 循 环 标 志, 退 出 循 环 并 继 续
 执 行。 如 果 我 们 没 有 发 现 匹 配, 将 在 循 环 到 我 们 自 己 的 应 用 窗 口 时 退 出 循
 环。 这 时, 我 们 简 单 地 退 出 函 数。 

                       


--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.97.236.132]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: whs.hit.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: cadcam.hit.edu.c]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.391毫秒