1:VB对注册表操作程序开机时运行
我们可以看到一些程序在开机时就会自动运行,象Winpopup就是这样的,这是怎么实现的呢?可以把需要运行的程序添加到“开始”-“程序”-“启动”中,还有一种方法就是写入注册表了,这里我们讨论通过写注册表来实现的方法,从中可以看到三个对注册表操作的API函数的使用技巧。
首先要声明这三个API函数,它们分别是:RegSetValue、RegCreateKey、RegCloseKey,其作用是设置某一个主键的键值、创建一个主键、关闭对注册表主键的操作。
Private Declare Function RegSetValue Lib "advapi32.dll" Alias "RegSetValueA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long
Private Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
然后声明以下两个常数,要进行注册表写入的位置是在HKEY_LOCAL_MACHINE下,我们可以在VB自带的API文本查看器中找到这些常数的定义方法。
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const REG_SZ = 1
然后使用如下语句就行了,你可以把这段代码放在程序的某个位置:
写注册表
Dim Ret2 As Long
打开 HKEY_LOCAL_MACHINE 下的 software\microsoft\windows\currentVersion\runServices 主键
RegCreateKey HKEY_LOCAL_MACHINE, "software\microsoft\windows\currentVersion\runServices", Ret2
将此主键下的“默认”项的值改为"c:\windows\system\myprogram.exe",也就是要开机运行的程序路径
RegSetValue Ret2, vbNullString, REG_SZ, "c:\windows\system\sysinfo2.exe", 4
关闭对主键的操作
RegCloseKey Ret2
2: 防止应用程序加载两份
当 同 时 运 行 两 份 相 同 的 程 序 时, 两 份 程 序 的 模 块 代 码 都 相 同, 因 此, 只 要 找 到 内 存 中 两 个 相 同 的 模 块 代 码, 我 们 就 知 道 有 两 份 程 序 在 运 行, 从 而 可 以 控 制 它。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 文 件, 在 程 序 管 理 器 下, 启 动 该 应 用 程 序, 然 后 把 产 生 的 窗 体 最 小 化, 接 着 从 程 序 管 理 器 下 再 运 行 它, 用 户 将 看 到 一 个 消 息 框, 告 诉 用 户, 应 用 程 序 已 被 加 载 过 了, 第 二 份 程 序 终 止 执 行。 上 面 的 程 序 仅 用 来 防 止 加 载 二 份 程 序, 但 还 没 有 做 到 当 不 能 启 动 第 二 份 时, 自 动 进 入 到 第 一 份 程 序。 要 做 到 这 一 点, 所 涉 及 的 程 序 较 复 杂, 这 里 就 不 详 细 介 绍 了。
3:判 断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
4: 在关掉窗体前提示存数据
一 般 说 来, 通 常 用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 控 制 过 程 传 递 消 息, 从 而 控 制 程 序 的 走 向。
判断程序本身是否运行,不需要调用API函数
只需要加一句话就可以了
if app.previnstance then
msgbox ....
end
endif