VB 程序设计

10个成员

VisualBasic 软件设计中的几个问题

发表于 2016-12-22 3342 次查看
在 软 件 开 发 过 程 中, 有 一 些 看 似 很 简 单 的 问 题, 却 很 容 易 被 一 般 的 开 发 人 员 所 忽 略, 这 些“Bugs” 的 存 在, 影 响 我 们 软 件 走 向 商 品 化。 下 面 所 列 出 的 是 笔 者 在 使 用Visual Basic 开 发 软 件 时, 碰 到 了 几 个 这 类 问 题, 这 里 给 出 其 解 决 方 法, 供 大 家 探 讨 交 流。

一  防 止 应 用 程 序 加 载 两 份
当 我 们 的 应 用 程 序 在Windows 下 运 行 后, 在 操 作 过 程 中, 有 时 会 把 它 最 小 化 隐 藏 起 来, 或 者 切 换 到 程 序 管 理 器 下 进 行 其 它 操 作, 而 后 又 想 进 入 原 来 的 应 用 程 序, 这 时 如 果 忘 记 了 刚 才 启 动 的 应 用 程 序, 又 去 重 新 启 动 该 应 用 程 序, 在 内 存 中 就 同 时 加 载 了 两 份 同 样 的 应 用 程 序, 这 样 不 但 占 用 了 内 存 空 间, 而 且 容 易 引 起 误 操 作, 造 成 数 据 的 损 失。 为 了 避 免 这 种 情 况 发 生, 就 需 要 程 序 能 够 给 出 提 示“ 已 经 加 载 过” 或 直 接 进 入 第 一 次 被 加 载 的 应 用 程 序 中。 对 于 这 个 问 题, 看 起 来 比 较 难 办, 其 实 我 们 只 要 对Windows 管 理 应 用 程 序 的 机 理 有 所 了 解, 就 很 容 易 解 决。
我 们 知 道, 对 于 每 一 个 运 行 着 的 应 用 程 序,Windows 都 分 配 给 一 个 唯 一 的“ 句 柄(Handle)” 和 一 个 模 块 代 码(Module)。 当 同 时 运 行 两 份 相 同 的 程 序 时, 两 份 程 序 的 模 块 代 码 都 相 同, 因 此, 只 要 找 到 内 存 中 两 个 相 同 的 模 块 代 码, 我 们 就 知 道 有 两 份 程 序 在 运 行, 从 而 可 以 控 制 它。Windows 提 供 的 两 个 接 口 函 数GetModuleHandle 和GetModuleUsage 可 以 完 成 此 任 务。 具 体 方 法 如 下, 首 先 在 一 个 新 的 模 块 文 件( *.Bas) 中 声 明API 函 数。

Declare Function GetModuleHandle Lib"Kernel"(ByVallpProgName$)

Declare Function GetModuleUsage Lib"Kernel"(ByVal hModule)

同 时 建 立 一 个 子 过 程, 名 字 为main, 子 过 程 中 的 代 码 如 下:

Sub Main()
On Error GoTo errMain‘错误处理
Dim hModule% ‘模块句柄
Dim AppCount% ‘应用程序的个数
appPath$=app.Path + "\" ‘应用程序的启动路径
hModule %=GetModuleHandle(appPath$+app.EXEName+".exe")‘获得该程序的句柄。
AppCount %=GetModuleUsage(hModule)‘获得模块代码,即运行的应用程序数目。
lf AppCount%>1 Then‘同一应用程序数大于1
MsgBox"程序已经加载",64
End ‘结束当前启动的应用程序
Elsc
mainForm.Show ‘mainForm是程序的主窗体
End lf
Exit Sub
errMain:
lf Err<>0 Then
MsgBox"启动程序时发生错误",64
Exit Sub
End lf
End Sub
该 过 程 完 成 后, 在VB3.0 主 菜 单 [options ] 下, 选 择 [Project ] 菜 单 项, 设 定 [Start up From ] 项 为Sub main, 即 程 序 运 行 时, 最 先 从Sub main 子 程 序 开 始。 这 样 保 证 上 面 的 代 码 一 定 被 执 行。Sub main 是VB3.0 约 定 的 子 过 程 名, 不 能 用 其 它 的 名 字 来 代 替。
重 新 生 成EXE 文 件, 在 程 序 管 理 器 下, 启 动 该 应 用 程 序, 然 后 把 产 生 的 窗 体 最 小 化, 接 着 从 程 序 管 理 器 下 再 运 行 它, 用 户 将 看 到 一 个 消 息 框, 告 诉 用 户, 应 用 程 序 已 被 加 载 过 了, 第 二 份 程 序 终 止 执 行。 上 面 的 程 序 仅 用 来 防 止 加 载 二 份 程 序, 但 还 没 有 做 到 当 不 能 启 动 第 二 份 时, 自 动 进 入 到 第 一 份 程 序。 要 做 到 这 一 点, 所 涉 及 的 程 序 较 复 杂, 这 里 就 不 详 细 介 绍 了。

二判 断Windows 的 安 装 路 径
在 我 们 开 发 的 软 件 中, 有 时 会 直 接 调 用Windows 提 供 的 小 应 用 程 序, 如 计 算 器、 计 事 本 等; 或 需 要 把 一 些 特 殊 的 文 件 放 到Windows 或SYSTEM 的 路 径 下。 通 常,Windows 都 安 装 在C: \WINDOWS 目 录 下, 但 用 户 可 以 任 意 修 改Windows 的 主 目 录 名, 因 此, 在 我 们 的 软 件 中, 就 需 要 判 断Windows 的 安 装 路 径。 对 于 这 个 问 题,Windows 提 供 了 两 个API 函 数:GetWindowsDirectory 和GetSystemDirectory, 可 以 返 回Windows 目 录 和SYSTEM 目 录 的 名 称。
为 此, 编 制 一 个 通 用 函 数 GetWinDir, 它 返 回Windows 的 安 装 目 录 名 称。 类 似, 可 以 写 出GetSysDir, 略。

在*.BAS 模 块 文 件 中 声 明API 函 数

Declare Function GetWindowsDirectory Lib "Kernel" (ByVal IpBuffer As String,ByV al nSize As Integer) as IntegerFunction GetWinDir () As String Dim Windir$ Windir$=Space$(144) ‘144 是WINDOWS 目 录 名 称 理 论 上 的 最 大 长 度。

lf GetWindowsDirectory(Windir$,144)=0Then
MsgBox" 不 能 确 定WINDOWS 的 安 装 路 径",16
GetWinDir=""
Else
Windir$=ALLTrim$(Windir$)
if Right$(Windir$,1)<>“\” then Windir$=Windir$+“\”
‘加上反斜杠
GetWinDir=Windir$
End lf
End Function
其 中ALLTRIM 是 用 来 去 掉 字 符 串 中 空 字 符 的 函 数
FunctionALLTrim(FatStr$)As String
'this Function delete Space char in string of FatStr$
Dim SlimStr$,I%
SlimStr$=FatStr$
I%=lnStr(SlimStr$,Chr$(0)) ‘ 空 格 的 位 置
IfI% Then SlimStr$=Left$(SlimStr$,I%-1)
SlimStr$=Ltrim$(Rtrim$)(SlimStr$))
AIITrim$=SlimStr$
End Function
三  在 关 掉 窗 体 前 提 示 保 存 数 据
一 般 说 来, 通 常 用5 种 方 式 可 以 关 闭 一 个 应 用 程 序:
1. 用 户 选 择 了 当 前 窗 体Control Box 中 的 [ 关 闭 ] 命 令
2. 激 发 程 序 中 的 结 束 命 令 代 码( 如End,Unload)
3. 退 出Windows
4. 在Windows 的 任 务 列 表 中 关 闭 应 用 程 序。
5. 多 文 档 操 作 时, 关 闭 主MDI 窗 体, 引 起 子MDI 窗 体 关 闭。
在 关 闭 一 个 应 用 程 序 前, 我 们 要 给 用 户 一 个 机 会, 提 示“ 是 否 保 存 数 据”, 或 者 取 消“ 关 闭” 的 操 作。 在VB 中, 窗 体 的 关 闭 引 发 的 是Form _Unload 事 件, 我 们 可 以 对 该 事 件 进 行 编 程, 来 控 制“ 关 闭” 操 作。 假 设 现 已 有 一 个 过 程FileSave 用 来 保 存 文 件, 则 可 以 这 样 来 编 写 程 序。
Sub Form_Unload(CancelAs lnteger)
select cast Msagbox (“ 是 否 保 存 数 据?”,3+32)
‘Yes,No,Cnacel 三 种 选 择
case 6 ‘YES
FileSave ‘ 保 存 数 据
case2‘cancel
Cancel=TRUE ‘ 取 消 关 闭 操 作
case else ‘NO‘ 不 保 存, 执 行 关 闭 操 作
End select
End Sub
上 面 代 码 中 的Cancel 变 量, 是Form _unload 事 件 本 身 的 固 有 传 出 变 量, 它 给Windows 控 制 过 程 传 递 消 息, 从 而 控 制 程 序 的 走 向。

上 面 三 个 例 子, 只 是 软 件 完 善 过 程 中 的 一 些 小 问 题, 要 使 软 件 稳 定 可 靠, 需 要 做 大 量 细 致 认 真 的 工 作。 有 些 问 题, 我 们 可 以 通 过 发 掘VB 本 身 的 潜 力, 深 入 掌 握 一 些 过 程 的 操 作 技 巧 来 解 决; 而 有 些 较 复 杂 的 问 题, 涉 及 到Windows 底 层 方 面 的 操 作, 采 用Windows 的API 函 数, 可 以 很 容 易 实 现。 当 然 这 需 要 对Windows 的 函 数 和 机 理 有 一 定 的 了 解。 随 着Windows 编 程 水 平 的 提 高, 我 们 会 逐 渐 学 会 并 喜 欢 利 用API 函 数 来 辅 助 完 成 程 序 编 码。

 

发表回复
你还没有登录,请先登录注册