1999年4月5日
在VB 应 用 程 序 中 巧 用DLL
中 国 航 空 信 息 中 心(100029) 吴 斌
----在 使 用VB 开 发 多 媒 体 应 用 程 序 时, 如
何 合 理 地 存 放 大 量 的 多 媒 体 资 源, 是 一 件 十 分 棘 手 的 事。 如 果
将 资 源 以 文 件 形 式 存 放 在 磁( 光) 盘 上, 使 用 时 再 从 盘 上 读 取,
势 必 大 大 影 响 资 源 调 用 的 速 度。 如 果 将 资 源 直 接 编 译 在 应 用 程
序 的 可 执 行 文 件 中, 虽 然 可 以 获 得 令 人 满 意 的 资 源 存 取 速 度,
但 会 导 致 最 终 的 可 执 行 文 件 尺 寸 大 大 膨 胀。 如 何 解 决 这 个 矛 盾
呢 ? 笔 者 从Windows 动 态 链 接 库 的 原 理 中 得 到 启 发, 找 到 了 一 个
结 合 二 者 优 势 的 解 决 方 法。
一、 制 作 资 源 动 态 链 接 库
----常 见 的 动 态 库 包 含 外 部 函 数 和 资 源, 也
有 一 些 动 态 库 只 包 含 资 源, 如Windows 字 体 资 源 文 件, 我 们 将 这 类
动 态 库 称 之 为 资 源 动 态 链 接 库。 制 作 资 源 动 态 库 的 方 法 很 多,
笔 者 在 此 提 供 了 一 种 无 需 编 程、 简 单 有 效 的 方 法。 该 方 法 利 用
了Borland C + + 的 资 源 管 理 器Resource Workshop 的 反 编 译 能 力, 借 用 现
成 的 动 态 库, 将 其 改 制 为 自 己 的 资 源 动 态 库。 具 体 方 法 是, 拷 贝
一 个 现 成 的 资 源 动 态 库 文 件( 如windows\system 目 录 下 的 字 体 资 源
文 件arial.fot) 到 应 用 程 序 工 作 目 录, 更 改 文 件 名, 如 改 为DEMO.DLL。
然 后 在Resource Workshop 中 打 开 该 文 件, 选 择 其 中 原 有 的 资 源 将 其
删 除, 再 加 入 自 己 的 资 源, 即 可 制 成 自 己 的 资 源 动 态 库。 有 两 个
关 键 问 题 需 要 提 请 读 者 注 意, 其 一, 对 于 声 音 这 类 非Windows 传 统
资 源, 在 加 入 动 态 库 之 前, 需 要 用 户 自 定 义 一 个 资 源 类 型 以 存
放 这 类 资 源, 如 笔 者 在DEMO.DLL 中 为Windows 音 频 文 件 定 义 了WAVE
资 源 类 型; 其 二, 动 态 库 中 每 一 个 资 源 的 资 源 名 十 分 重 要, 它 是
调 用 资 源 的 关 键, 建 议 用 户 最 好 在 加 入 资 源 后 为 其 定 义 一 个 有
意 义 的 资 源 名。
二、 调 用 资 源 动 态 库
----VB 本 身 并 没 有 调 用 动 态 库 的 函 数 和 语
句, 因 此 必 须 借 助 于Windows API 函 数。 下 面 笔 者 将 结 合 一 个 实 例,
具 体 介 绍 调 用 方 法。 实 例 中 使 用 的 是 笔 者 通 过 上 述 方 法 制 作 的
资 源 动 态 库DEMO.DLL, 其 中 包 含 两 个BITMAP(.bmp) 类 型 资 源B1 和
B2, 两 个WAVE(.wav) 类 型 资 源S1 和S2。
----首 先, 新 建 一 个VB 工 程, 其 中 包 含 一 个 窗
体Form1 和 一 个 模 块Module1。 在 窗 体Form1 中 加 入 了 一 个 图 片 框 控 件
Picture1 和 四 个 命 令 按 钮 控 件,Picture1 用 于 显 示 动 态 库 中 的 位 图 资
源, 四 个 命 令 按 钮 的 属 性 设 置 和 功 能 含 义 如 下 表:
----接 着 在Module1 和Form1 中 加 入 下 列 代 码, 便
可 完 成 实 例 程 序:
※Moudle1.bas 清 单
' 声 明API 函 数
Declare Function LoadLibrary %Lib
“Kernel" (ByVal lpLibFileName $)
Declare Sub FreeLibrary Lib
“Kernel" (ByVal hLibModule %)
Declare Function LoadBitmap %Lib
“User" (ByVal hInstance %, ByVal lpBitmapName As Any)
Declare Function GetObj % Lib
“GDI" Alias "GetObject"
(ByVal hObject %, ByVal nCount %, lpObject As Any)
Declare Function CreateCompatibleDC % Lib
“GDI" (ByVal hDC %)
Declare Function SelectObject %Lib
“GDI" (ByVal hDC %, ByVal hObject %)
Declare Function BitBlt % Lib
“GDI" (ByVal hDestDC %, ByVal x %, ByVal y %,
ByVal nWidth %, ByVal nHeight %, ByVal hSrcDC %,
ByVal XSrc %, ByVal YSrc %, ByVal dwRop &)
Declare Function DeleteDC %Lib
“GDI" (ByVal hDC %)
Declare Function DeleteObject % Lib
“GDI" (ByVal hObject %)
Declare Function FindResource % Lib
“Kernel" (ByVal hInstance %, ByVal lpName $,
ByVal lpType As Any)
Declare Function LockResource &Lib
“Kernel" (ByVal hResData %)
Declare Function LoadResource %Lib
“Kernel" (ByVal hInstance %, ByVal hResInfo %)
Declare Function GlobalUnlock %Lib
“Kernel" (ByVal hMem %)
Declare Function sndPlaySound %Lib
“MMSYSTEM" (ByVal lpszSoundName As Any,
ByVal uFlags %)
' 位 图 数 据 结 构 类 型
Type BITMAP
bmType As Integer
bmWidth As Integer
bmHeight As Integer
bmWidthBytes As Integer
bmPlanes As String * 1
bmBitsPixel As String * 1
bmBits As Long
End Type
' 光 栅 操 作 代 码 常 量
Public Const SRCCOPY = &HCC0020
' 声 音 播 放 状 态 常 量
Public Const SND_SYNC = &H0
Public Const SND_MEMORY = &H4
' 调 用 位 图 资 源 子 例 程
Sub load_pic(picName As String)
Dim hDLL As Integer
Dim hdcMemory, hLoadedbitmap, hOldBitmap As Integer
Dim retVal As Integer
Dim bmpInfo As BITMAP
' 安 装 动 态 链 接 库DEMO.DLL
hDLL = LoadLibrary(App.Path & “\DEMO.DLL")
' 根 据 资 源 名 从 动 态 链 接 库 中
加 载 相 应 的 位 图 资 源
hLoadedbitmap = LoadBitmap(hDLL, picName)
' 获 取 位 图 信 息
retVal = GetObj(hLoadedbitmap, Len(bmpInfo), bmpInfo)
' 创 建 一 个 与 图 片 框 控 件 的 设 备
描 述 表 兼 容 的 内 存 设 备 描 述 表
hdcMemory = CreateCompatibleDC(Form1.Picture1.hDC)
' 将 位 图 选 入 内 存 设 备 描 述 表
hOldBitmap = SelectObject(hdcMemory, hLoadedbitmap)
' 将 位 图 从 内 存 设 备 描 述 表 中 拷 入
图 片 框 控 件 的 设 备 描 述 表 中
retVal = BitBlt(Form1.Picture1.hDC, 0, 0,
bmpInfo.bmWidth, bmpInfo.bmHeight, hdcMemory,
0, 0, SRCCOPY)
' 将 原 始 位 图 选 入 内 存 设 备 描 述 表
retVal = SelectObject(hdcMemory, hOldBitmap)
' 删 除 加 载 的 位 图,
释 放 其 占 用 的 所 有 系 统 资 源
retVal = DeleteObject(hLoadedbitmap)
' 删 除 内 存 设 备 描 述 表
retVal = DeleteDC(hdcMemory)
' 释 放 动 态 链 接 库
FreeLibrary (hDLL)
End Sub
' 调 用 声 音 资 源 子 例 程
Sub load_sound(wavName As String)
Dim hDLL As Integer
Dim hloadwave As Integer
Dim hwaveres As Integer
Dim hsound As Long
Dim hrelease As Integer
Dim resVal As Integer
hDLL = LoadLibrary(App.Path & “\DEMO.DLL")
' 在 动 态 链 接 库 中 查 找 资 源 类 型
为WAVE, 资 源 名 为wavName 的 资 源
hwaveres = FindResource(hDLL, wavName, “WAVE")
' 将 该 资 源 装 入 内 存
hloadwave = LoadResource(hDLL, hwaveres)
' 锁 定 该 资 源
hsound = LockResource(hloadwave)
' 以 同 步 方 式 播 放 内 存 中 的 声 音 资 源
resVal = sndPlaySound
(hsound, SND_SYNC + SND_MEMORY)
' 释 放 该 资 源 占 用 的 内 存
hrelease = GlobalUnlock(hloadwave)
FreeLibrary (hDLL)
End Sub
※FORM1.FRM 代 码 清 单
Private Sub cmdBitmap_Click(Index As Integer)
Picture1.Picture = LoadPicture(“")
' 清 空 图 片 框 控 件
Select Case Index
Case 0
load_pic (“B1")
Case 1
load_pic (“B2")
End Select
End Sub
Private Sub cmdSound_Click(Index As Integer)
Select Case Index
Case 0
load_sound (“S1")
Case 1
load_sound (“S2")
End Select
End Sub
----本 实 例 程 序 已 在Windows 3.X 环 境 下 通 过 测
试。 程 序 中 的 某 些 参 数 设 置 与 特 定 需 求( 如 资 源 动 态 库 的 内 容
等) 有 关, 读 者 在 开 发 实 际 应 用 时 应 做 相 应 的 改 动。
|