欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
在VB 中調用動(dòng)態(tài)連接庫

作 為 一 種 簡(jiǎn) 單 易 用 的Windows 開(kāi) 發(fā) 環(huán) 境,Visual Basic 從 一 推 出 就 受 到 了 廣 大 編 程 人 員 的 歡 迎。 它 使 程 序 員 不 必 再 直 接 面 對 紛 繁 復 雜 的Windows 消 息, 而 可 以 將 精 力 主 要 集 中 在 程 序 功 能 的 實(shí) 現 上, 大 大 提 高 了 編 程 效 率。 但 凡 事 有 利 必 有 弊。VB 中 高 度 的 封 裝 和 模 塊 化 減 輕 了 編 程 者 的 負 擔, 同 時(shí) 也 使 開(kāi) 發(fā) 人 員 失 去 了 許 多 訪(fǎng) 問(wèn) 低 層API 函 數 和 直 接 與Windows 交 互 的 機 會(huì )。 因 此, 相 比 而 言,VB 應 用 程 序 的 執 行 效 率 和 功 能 比C/C++ 或Delphi 生 成 的 程 序 要 差。 為 了 解 決 這 個(gè) 問(wèn) 題, 在 一 個(gè) 大 型 的VB 開(kāi) 發(fā) 應 用 中, 直 接 調 用Windows API 函 數 幾 乎 是 不 可 避 免 的; 同 時(shí), 還 有 可 能 需 要 程 序 員 自 己 用C/C++ 等 開(kāi) 發(fā) 一 些 動(dòng) 態(tài) 連 接 庫, 用 于 在VB 中 調 用。 本 文 主 要 討 論 在32 位 開(kāi) 發(fā) 環(huán) 境Visual Basic 5.0 中 直 接 調 用Windows 95 API 函 數 或 用 戶(hù) 生 成 的32 位 動(dòng) 態(tài) 連 接 庫 的 方 法 與 規 則。

---- Windows 動(dòng) 態(tài) 連 接 庫 是 包 含 數 據 和 函 數 的 模 塊, 可 以 被 其 它 可 執 行 文 件(EXE、DLL、OCX 等) 調 用。 動(dòng) 態(tài) 連 接 庫 包 含 兩 種 函 數: 輸 出(exported) 函 數 和 內 部(internal) 函 數。 輸 出 函 數 可 以 被 其 它 模 塊 調 用, 而 內 部 函 數 則 只 能 在 動(dòng) 態(tài) 連 接 庫 內 部 使 用。 盡 管 動(dòng) 態(tài) 連 接 庫 也 能 輸 出 數 據, 但 實(shí) 際 上 它 的 數 據 通 常 是 只 在 內 部 使 用 的。 使 用 動(dòng) 態(tài) 連 接 庫 的 優(yōu) 點(diǎn) 是 顯 而 易 見(jiàn) 的。 將 應 用 程 序 的 一 部 分 功 能 提 取 出 來(lái) 做 成 動(dòng) 態(tài) 連 接 庫, 不 但 減 小 了 主 應 用 程 序 的 大 小, 提 高 了 程 序 運 行 效 率, 還 使 它 更 加 易 于 升 級。 多 個(gè) 應 用 程 序 共 享 一 個(gè) 動(dòng) 態(tài) 連 接 庫 還 能 有 效 地 節 省 系 統 資 源。 正 因 為 如 此, 在Windows 系 統 中, 動(dòng) 態(tài) 連 接 庫 得 到 了 大 量 的 使 用。

---- 一 般 來(lái) 說(shuō), 動(dòng) 態(tài) 連 接 庫 都 是 以DLL 為 擴 展 名 的 文 件, 如Kernel32.dll 、commdlg.dll 等。 但 也 有 例 外, 如16 位Windows 的 核 心 部 件 之 一GDI.exe 其 實(shí) 也 是 一 個(gè) 動(dòng) 態(tài) 庫。 編 寫(xiě) 動(dòng) 態(tài) 連 接 庫 的 工 具 很 多, 如Visual C++、Borland C++、Delphi 等, 具 體 方 法 可 以 參 見(jiàn) 相 關(guān) 文 檔。 下 面 只 以Visual C++ 5.0 為 例, 介 紹 一 下 開(kāi) 發(fā) 應 用 于Visual Basic 5.0 的 動(dòng) 態(tài) 連 接 庫 時(shí) 應 注 意 的 問(wèn) 題( 本 文 中 所 有 涉 及C/C++ 語(yǔ) 言 或 編 譯 環(huán) 境 的 地 方, 都 以VC5 為 例; 所 有 涉 及Visual Basic 的 地 方 都 以VB5 為 例)。

---- 作 為 一 種32 位Windows 應 用 程 序 的 開(kāi) 發(fā) 工 具,VB5 生 成 的exe 文 件 自 然 也 都 是32 位 的, 通 常 情 況 下 也 只 能 調 用32 位 的 動(dòng) 態(tài) 連 接 庫。 但 是, 并 不 是 所 有 的32 位 動(dòng) 態(tài) 庫 都 能 被VB 生 成 的exe 文 件 正 確 地 識 別。 一 般 來(lái) 說(shuō), 自 己 編 寫(xiě) 用 于VB 應 用 程 序 調 用 的 動(dòng) 態(tài) 連 接 庫 時(shí), 應 注 意 以 下 幾 個(gè) 方 面 的 問(wèn) 題:

---- 1、 生 成 動(dòng) 態(tài) 庫 時(shí) 要 使 用__stdcall 調 用 約 定, 而 不 能 使 用 缺 省 的__cdecl 調 用 約 定;__stdcall 約 定 通 常 用 于32 位API 函 數 的 調 用。

---- 2、 在VC5 中 的 定 義 文 件(.def) 中, 必 須 列 出 輸 出 函 數 的 函 數 名, 以 強 制VC5 系 統 將 輸 出 函 數 的 裝 飾 名(decorated name) 改 成 普 通 函 數 名; 所 謂 裝 飾 名 是VC 的 編 譯 器 在 編 譯 過(guò) 程 中 生 成 的 輸 出 函 數 名, 它 包 含 了 用 戶(hù) 定 義 的 函 數 名、 函 數 參 數 及 函 數 所 在 的 類(lèi) 等 多 方 面 的 信 息。 由 于 在VC5 中 定 義 文 件 不 是 必 需 的, 因 此 工 程 不 包 含 定 義 文 件 時(shí)VC5 就 按 自 己 的 約 定 將 用 戶(hù) 定 義 的 輸 出 函 數 名 修 改 成 裝 飾 名 后 放 到 輸 出 函 數 列 表 中, 這 樣 的 輸 出 函 數 在VB 生 成 的 應 用 程 序 中 是 不 能 正 確 調 用 的( 除 非 聲 明 時(shí) 使 用Alias 子 句)。 因 此 需 要 增 加 一 個(gè).def 文 件, 其 中 列 出 用 戶(hù) 需 要 的 函 數 名, 以 強 制VC5 不 按 裝 飾 名 進(jìn) 行 輸 出。

---- 3、VC5 中 的 編 譯 選 項" 結 構 成 員 對 齊 方 式(structure member alignment)" 應 設 成4 字 節, 其 原 因 將 在 后 文 詳 細 介 紹。

---- 4、 由 于 在C 中 整 型 變 量 是4 個(gè) 字 節, 而VB 中 的 整 型 變 量 依 然 只 有2 個(gè) 字 節, 因 此 在C 中 聲 明 的 整 型(int) 變 量 在VB 中 調 用 時(shí) 要 聲 明 為 長(cháng) 整 型(long), 而C 中 的 短 整 型(short) 在VB 中 則 要 聲 明 成 整 型(integer); 下 表 針 對 最 常 用 的 C 語(yǔ) 言 數 據 類(lèi) 型 列 出 了 與 之 等 價(jià) 的 Visual Basic 類(lèi) 型( 用 于 32 位 版 本 的 Windows)。

---- C 語(yǔ) 言 數 據 類(lèi) 型 在Visual Basic 中 聲 明 為 調 用 時(shí) 使 用 的 表 達 式

---- ATOM ByVal variable As Integer 結 果 為Integer 類(lèi) 型 的 表 達 式

---- BOOL ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- BYTE ByVal variable As Byte 結 果 為 Byte 類(lèi) 型 的 表 達 式

---- CHAR ByVal variable As Byte 結 果 為 Byte 類(lèi) 型 的 表 達 式

---- COLORREF ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- DWORD ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- HWND, HDC, HMENU ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式 等Windows 句 柄

---- INT, UINT ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- LONG ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- LPARAM ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- LPDWORD variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- LPINT, LPUINT variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- LPRECT variable As type 自 定 義 類(lèi) 型 的 任 意 變 量

---- LPSTR, LPCSTR ByVal variable As String 結 果 為 String 類(lèi) 型 的 表 達 式

---- LPVOID variable As Any 任 何 變 量( 在 傳 遞 字 符 串 的 時(shí) 候 使 用ByVal)

---- LPWORD variable As Integer 結 果 為Integer 類(lèi) 型 的 表 達 式

---- LRESULT ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- NULL As Any 或 ByVal Nothing 或

---- ByVal variable As Long ByVal 0& 或 VBNullString

---- SHORT ByVal variable As Integer 結 果 為Integer 類(lèi) 型 的 表 達 式

---- VOID Sub procedure 不 可 用

---- WORD ByVal variable As Integer 結 果 為Integer 類(lèi) 型 的 表 達 式

---- WPARAM ByVal variable As Long 結 果 為 Long 類(lèi) 型 的 表 達 式

---- 5、VB 中 進(jìn) 行32 位 動(dòng) 態(tài) 庫 的 聲 明 時(shí), 函 數 名 是 大 小 寫(xiě) 敏 感 的。 在 獲 得 了 需 要 的 動(dòng) 態(tài) 連 接 庫 之 后, 就 可 以 在VB 中 進(jìn) 行 調 用 了。 但 是, 由 于VB 不 能 驗 證 應 用 程 序 傳 遞 到 動(dòng) 態(tài) 連 接 庫 中 的 參 數 值 是 否 正 確, 因 此VB 程 序 中 大 量 的API 調 用 可 能 會(huì ) 降 低 整 個(gè) 應 用 程 序 的 穩 定 性, 也 會(huì ) 增 加 以 后 維 護 的 難 度。 所 以, 決 定 在VB 程 序 中 直 接 調 用API 函 數 時(shí) 要 慎 重, 但 適 當 的 使 用API 調 用 確 實(shí) 能 夠 有 效 地 提 高VB 程 序 的 性 能。 這 之 間 的 平 衡 需 要 編 程 人 員 根 據 實(shí) 際 情 況 來(lái) 掌 握。 下 面 就 具 體 介 紹 一 下 在VB 中 調 用API 函 數 時(shí) 需 要 做 的 工 作。

---- 要 聲 明 一 個(gè)DLL 過(guò) 程, 首 先 需 要 在 代 碼 窗 口 的" 通 用(General)" 部 分 增 加 一 個(gè)Declare 語(yǔ) 句。 如 果 該 過(guò) 程 返 回 一 個(gè) 值, 應 將 其 聲 明 為Function:

---- Declare Function publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])] As Type

---- 如 果 過(guò) 程 沒(méi) 有 返 回 值, 可 將 其 聲 明 為Sub:

---- Declare Sub publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])]

---- 缺 省 情 況 下, 在 標 準 模 塊 中 聲 明 的DLL 過(guò) 程, 可 以 在 應 用 程 序 的 任 何 地 方 調 用 它。 在 其 它 類(lèi) 型 的 模 塊 中 定 義 的DLL 過(guò) 程 則 是 模 塊 私 有 的, 必 須 在 它 們 前 面 聲 明Private 關(guān) 鍵 字, 以 示 區 分。 下 面 分 別 介 紹 聲 明 語(yǔ) 句 的 各 個(gè) 組 成 部 分。

---- 1、 指 定 動(dòng) 態(tài) 庫:

---- Declare 語(yǔ) 句 中 的 Lib 子 句 用 來(lái) 告 訴 Visual Basic 如 何 找 到 包 含 過(guò) 程 的 .dll 文 件。 如 果 引 用 的 過(guò) 程 屬 于 Windows 核 心 庫(User32、Kernel32 或 GDI32), 則 可 以 不 包 含 文 件 擴 展 名, 如:

---- Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long

---- 對 于 其 它 動(dòng) 態(tài) 連 接 庫, 可 以 在Lib 子 句 指 定 文 件 的 路 徑:

---- Declare Function lzCopy Lib "c:windowslzexpand.dll" _

---- (ByVal S As Integer, ByVal D As Integer) As Long

---- 如 果 未 指 定 libname 的 路 徑,Visual Basic 將 按 照 下 列 順 序 查 找 該 文 件:

---- ①.exe 文 件 所 在 的 目 錄

---- ② 當 前 目 錄

---- ③Windows 系 統 目 錄

---- ④Windows 目 錄

---- ⑤Path 環(huán) 境 變 量 中 的 目 錄

---- 下 表 中 列 出 了 常 用 的 操 作 系 統 環(huán) 境 庫 文 件。

---- 動(dòng) 態(tài) 鏈 接 庫 描 述

---- Advapi32.dll 高 級 API 服 務(wù), 支 持 大 量 的 API( 其 中 包 括 許 多 安 全 與 注 冊 方 面 的 調 用)

---- Comdlg32.dll 通 用 對 話(huà) 框 API 庫

---- Gdi32.dll 圖 形 設 備 接 口 API 庫

---- Kernel32.dll Windows 32 位 核 心 的 API 支 持

---- Lz32.dll 32 位 壓 縮 例 程

---- Mpr.dll 多 接 口 路 由 器 庫

---- Netapi32.dll 32 位 網(wǎng) 絡(luò ) API 庫

---- Shell32.dll 32 位 Shell API 庫

---- User32.dll 用 戶(hù) 接 口 例 程 庫

---- Version.dll 版 本 庫

---- Winmm.dll Windows 多 媒 體 庫

---- Winspool.drv 后 臺 打 印 接 口, 包 含 后 臺 打 印 API 調 用。

---- 對 于Windows 的 系 統API 函 數, 可 以 利 用VB 提 供 的 工 具API Viewer 查 找 某 一 函 數 及 其 相 關(guān) 數 據 結 構 和 常 數 的 聲 明, 并 復 制 到 自 己 的 程 序 中。

---- 2、 使 用 別 名:

---- Declare 語(yǔ) 句 中 的Alias 子 句 是 一 個(gè) 可 選 的 部 分, 用 戶(hù) 可 以 通 過(guò) 它 所 標 識 的 別 名 對 動(dòng) 態(tài) 庫 中 的 函 數 進(jìn) 行 引 用。 例 如, 在 下 面 的 語(yǔ) 句 中, 聲 明 了 一 個(gè) 在VB 中 名 為MyFunction 的 函 數, 而 它 在 動(dòng) 態(tài) 庫Mydll.dll 中 最 初 的 名 字 是MyFunctionX。

---- Private Declare Function MyFunction Lib "Mydll.dll" _

---- Alias "MyFunctionX" ( ) As Long

---- 需 要 注 意 的 是,Alias 子 句 中 的 函 數 名 是 大 小 寫(xiě) 敏 感 的, 也 就 是 說(shuō), 必 須 與 函 數 在 生 成 時(shí) 的 聲 明( 如 在C 源 文 件 中 的 聲 明) 一 致。 這 是 因 為32 位 動(dòng) 態(tài) 庫 與16 位 動(dòng) 態(tài) 庫 不 同, 其 中 的 函 數 名 是 區 分 大 小 寫(xiě) 的。 同 樣 道 理, 如 果 沒(méi) 有 使 用Alias 子 句, 那 么 在Function( 或Sub) 后 的 函 數 名 也 是 區 分 大 小 寫(xiě) 的。

---- 通 常 在 以 下 幾 種 情 況 時(shí) 需 要 使 用Alias 子 句:

---- A. 處 理 使 用 字 符 串 的 系 統 Windows API 過(guò) 程

---- 如 果 調 用 的 系 統 Windows API 過(guò) 程 要 使 用 字 符 串, 那 么 聲 明 語(yǔ) 句中 必 須 增 加 一 個(gè) Alias 子 句, 以 指 定 正 確 的 字 符 集。 包 含 字 符 串 的 系 統 Windows API 函 數 實(shí) 際 有 兩 種 格 式:ANSI 和 Unicode( 關(guān) 于A(yíng)NSI 和 Unicode 兩 種 字 符 集 的 區 別 將 在 后 面 詳 細 闡 述)。 因 此, 在 Windows 頭 文 件 中, 每 個(gè) 包 含 字 符 串 的 函 數 都 同 時(shí) 有 ANSI 版 本 和 Unicode 版 本。 例 如, 下 面 是 SetWindowText 函 數 的 兩 種 C 語(yǔ) 言 描 述。 可 以 看 到, 第 一 個(gè) 描 述 將 函 數 定 義 為 SetWindowTextA, 尾 部 的"A" 表 明 它 是 一 個(gè) ANSI 函 數:

---- WINUSERAPI BOOL WINAPI SetWindowTextA(HWND hWnd, LPCSTR lpString);

---- 第 二 個(gè) 描 述 將 它 定 義 為 SetWindowTextW, 尾 部 的"W" 表 明 它 是 一 個(gè) Unicode 函 數:

---- WINUSERAPI BOOL WINAPI SetWindowTextW(HWND hWnd, LPCWSTR lpString);

---- 因 為 兩 個(gè) 函 數 實(shí) 際 的 名 稱(chēng) 都 不 是"SetWindowText", 要 引 用 正 確 的 函 數 就 必 須 增 加 一 個(gè) Alias 子 句:

Private Declare Function SetWindowText Lib "user32" _
Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal _
lpString As String) As Long

---- 應 當 注 意, 對 于VB 中 使 用 的 系 統Windows API 函 數, 應 該 指 定 函 數 的 ANSI 版 本, 因 為 只 有 Windows NT 才 支 持 Unicode 版 本, 而 Windows 95 不 支 持 這 個(gè) 版 本。 僅 當 應 用 程 序 只 運 行 在 Windows NT 平 臺 上 的 時(shí) 候 才 可 以 使 用 Unicode 版 本。

---- B. 函 數 名 是 不 標 準 的 名 稱(chēng)

---- 有 時(shí), 個(gè) 別 的 DLL 過(guò) 程 的 名 稱(chēng) 不 是 有 效 的 標 識 符。 例 如, 它 可 能 包 含 了 非 法 的 字 符( 如 連 字 符), 或 者 名 稱(chēng) 是 VB 的 關(guān) 鍵 字( 如 GetObject)。 在 這 種 情 況 下, 可 以 使 用 Alias 關(guān) 鍵 字。 例 如, 操 作 環(huán) 境 DLLs 中 的 某 些 過(guò) 程 名 以 下 劃 線(xiàn) 開(kāi) 始。 盡 管 在 VB 標 識 符 中 允 許 使 用 標 識 符, 但 是 下 劃 線(xiàn) 不 能 作 為 標 識 符 的 第 一 個(gè) 字 符。 為 了 使 用 這 種 過(guò) 程, 必 須 先 聲 明 一 個(gè) 名 稱(chēng) 合 法 的 過(guò) 程, 然 后 用 Alias 子 句 引 用 過(guò) 程 的 真 實(shí) 名 稱(chēng):

Declare Function lopen Lib "kernel32" Alias "_lopen" _
(ByVal lpPathName As String, ByVal iReadWrite _
As Long) As Long

---- 在 上 例 中,lopen 是 VB 中 使 用 的 過(guò) 程 名 稱(chēng)。 而 _lopen 則 是 動(dòng) 態(tài) 連 接 庫 中 可 以 識 別 的 名 稱(chēng)。

---- C. 使 用 序 號 標 識 DLL 過(guò) 程

---- 除 了 使 用 名 稱(chēng) 之 外, 還 可 以 使 用 序 號 來(lái) 標 識 DLL 過(guò) 程。 某 些 動(dòng) 態(tài) 連 接 庫 中 不 包 含 過(guò) 程 的 名 稱(chēng), 在 聲 明 它 們 包 含 的 過(guò) 程 時(shí) 必 須 使 用 序 號。 同 使 用 名 稱(chēng) 標 識 的DLL 過(guò) 程 相 比, 如 果 使 用 序 號, 在 最 終 的 應 用 程 序 中 消 耗 的 內 存 將 比 較 少, 而 且 速 度 會(huì ) 快 些。 但 是, 一 個(gè) 具 體 的API 的 序 號 在 不 同 的 操 作 系 統 中 可 能 是 不 同 的。 例 如 GetWindowsDirectory 在 Win95 下 的 序 號 為 432, 而 在 Windows NT 4.0 下 為 338。 總 而 言 之, 如 果 希 望 應 用 程 序 能 夠 在 不 同 的 操 作 系 統 下 運 行, 那 么 最 好 不 要 使 用 序 號 來(lái) 標 識 API 過(guò) 程。 如 果 過(guò) 程 不 屬 于A(yíng)PI, 或 者 應 用 程 序 使 用 的 范 圍 很 有 限, 那 么 使 用 序 號 還 是 有 好 處 的。

---- 要 使 用 序 號 來(lái) 聲 明 DLL 過(guò) 程,Alias 子 句 中 的 字 符 串 需 要 包 含 過(guò) 程 的 序 號, 并 在 序 號 的 前 面 加 一 個(gè) 數 字 標 記 字 符 (#)。 例 如,Windows kernel 中 的 GetWindowsDirectory 函 數 的 序 號 為 432; 可 以 用 下 面 的 語(yǔ) 句 來(lái) 聲 明 該 DLL 過(guò) 程:

Declare Function GetWindowsDirectory Lib "kernel32" _
Alias "#432" (ByVal lpBuffer As String, _
ByVal nSize As Long) As Long

---- 在 這 里, 可 以 使 用 任 意 的 合 法 名 稱(chēng) 作 為 過(guò) 程 的 名 稱(chēng),VB 將 用 序 號 在 DLL 中 尋 找 過(guò) 程。

---- 為 了 得 到 要 聲 明 的 過(guò) 程 的 序 號, 可 以 使 用 Dumpbin.exe 等 實(shí) 用 工 具(Dumpbin.exe 是 Microsoft Visual C++ 提 供 的 一 個(gè) 實(shí) 用 工 具, 它 的 使 用 說(shuō) 明 可 以 參 見(jiàn)VC 的 文 檔)。 利 用 Dumpbin, 可 以 提 取 出 .dll 文 件 中 的 各 種 信 息, 例 如 DLL 中 的 函 數 列 表, 它 們 的 序 號 以 及 與 代 碼 有 關(guān) 的 其 它 信 息。

---- 3、 使 用 值 或 引 用 傳 遞

---- 在 缺 省 的 情 況 下,VB 以 引 用 方 式 傳 遞 所 有 參 數(ByRef)。 這 意 味 著(zhù) 并 沒(méi) 有 傳 遞 實(shí) 際 的 參 數 值,VB 只 傳 遞 了 數 據 的 32 位 地 址。 另 外 有 許 多 DLL 過(guò) 程 要 求 參 數 以 值 方 式 傳 遞(ByVal)。 這 意 味 著(zhù) 它 們 需 要 實(shí) 際 的 數 據, 而 不 是 數 據 的 內 存 地 址。 如 果 過(guò) 程 需 要 一 個(gè) 傳 值 參 數, 而 傳 遞 給 它 的 參 數 是 一 個(gè) 指 針, 那 么 由 于 得 到 了 錯 誤 的 數 據, 該 過(guò) 程 將 不 能 正 確 地 工 作。

---- 要 使 參 數 以 使 用 值 方 式 傳 遞, 在 Declare 語(yǔ) 句 中 需 要 在 參 數 聲 明 的 前 面 加 上 ByVal 關(guān) 鍵 字。 例 如InvertRect 過(guò) 程 要 求 第 一 個(gè) 參 數 用 傳 值 方 式 傳 遞, 而 第 二 個(gè) 用 引 用 方 式 傳 遞:

Declare Function InvertRect Lib "user32" Alias _
"InvertRectA" (ByVal hdc As Long, lpRect As RECT) As Long

---- 動(dòng) 態(tài) 連 接 庫 的 參 數 傳 遞 是 一 個(gè) 復 雜 的 問(wèn) 題, 也 是VB 中 調 用 動(dòng) 態(tài) 連 接 庫 時(shí) 最 容 易 出 現 錯 誤 的 地 方。 參 數 類(lèi) 型 或 傳 遞 方 式 的 聲 明 錯 誤 都 可 能 導 致 應 用 程 序 出 現GPF( 通 用 保 護 錯 誤), 甚 至 使 操 作 系 統 崩 潰, 因 此 我 們 將 在 后 面 專(zhuān) 門(mén) 詳 細 地 討 論 這 個(gè) 問(wèn) 題。

---- 4、 靈 活 的 參 數 類(lèi) 型

---- 某 些 DLL 過(guò) 程 的 同 一 個(gè) 參 數 能 夠 接 受 多 種 數 據 類(lèi) 型。 如 果 需 要 傳 遞 多 種 類(lèi) 型 的 數 據, 可 以 將 參 數 聲 明 為 As Any, 從 而 取 消 類(lèi) 型 限 制。 例 如, 下 面 的 聲 明 中 的 第 三 個(gè) 參 數 (lppt As Any) 既 可 以 傳 遞 一 個(gè) POINT 結 構 的 數 組, 也 可 以 傳 遞 一 個(gè) RECT 結 構:

Declare Function MapWindowPoints Lib "user32" Alias _
"MapWindowPoints" (ByVal hwndFrom As Long, _
ByVal hwndTo As Long, lppt As Any, _
ByVal cPoints As Long) As Long

---- As Any 子 句 提 供 了 一 定 的 靈 活 性, 但 是, 由 于 它 不 進(jìn) 行 任 何 的 類(lèi) 型 檢 查, 風(fēng) 險 也 隨 之 增 加。 因 此 在 使 用 As Any 子 句 時(shí), 必 須 仔 細 檢 查 所 有 參 數 的 類(lèi) 型。

---- 正 確 的 函 數 聲 明 是 在VB 中 調 用 動(dòng) 態(tài) 連 接 庫 的 前 提, 但 要 想 在VB 中 用 對、 用 好 動(dòng) 態(tài) 庫 中 的 函 數, 僅 僅 有 聲 明 還 是 遠 遠 不 夠 的。 前 面 已 經(jīng) 說(shuō) 過(guò), 由 于VB 不 能 驗 證 應 用 程 序 傳 遞 到 動(dòng) 態(tài) 連 接 庫 中 的 參 數 值 是 否 正 確, 因 此 就 要 求 程 序 員 應 對 參 數 類(lèi) 型 有 非 常 詳 細 的 了 解, 否 則 很 容 易 引 起 應 用 程 序 發(fā) 生 通 用 保 護 錯 或 導 致 潛 在 的Bug, 降 低 軟 件 的 可 靠 性。 下 面 將 參 數 類(lèi) 型 分 為 簡(jiǎn) 單 數 據 類(lèi) 型、 字 符 串、 和 用 戶(hù) 自 定 義 類(lèi) 型 三 種 分 別 進(jìn) 行 討 論。

---- 1、 簡(jiǎn) 單 數 據 類(lèi) 型:

---- 簡(jiǎn) 單 數 據 類(lèi) 型 是 指Numeric 數 據 類(lèi) 型( 包 括Integer、Long、Single、Double、Currency 類(lèi) 型)、Byte 數 據 類(lèi) 型 和Boolean 數 據 類(lèi) 型。 它 們 的 共 同 的 特 點(diǎn) 是 結 構 簡(jiǎn) 單, 操 作 系 統 在 處 理 時(shí) 不 必 進(jìn) 行 特 殊 的 轉 換。

---- 簡(jiǎn) 單 數 據 類(lèi) 型 參 數 的 傳 遞 比 較 簡(jiǎn) 單。 我 們 知 道, 在VB 中 傳 遞 參 數 的 方 式 有 兩 種: 傳 值(Byval) 和 傳 址(ByRef), 缺 省 的 方 式 是 傳 址。 所 謂 傳 值, 就 是 對 一 個(gè) 變 量 的 具 體 值 進(jìn) 行 傳 遞; 而 傳 址 則 是 傳 遞 變 量 的 地 址。 例 如, 在VB 程 序 中 需 要 將 一 個(gè) 整 型 變 量m=10 的 值 傳 進(jìn) 動(dòng) 態(tài) 庫, 如 果 用 傳 值 方 式, 那 么 傳 進(jìn) 動(dòng) 態(tài) 庫 的 值 就 是10, 而 在 傳 址 方 式 下, 傳 入 的 則 是 變 量 m 的 地 址, 相 當 于C/C++ 中 &m 的 值。 需 要 注 意 的 是, 以 傳 值 方 式 傳 進(jìn) 動(dòng) 態(tài) 連 接 庫 的 變 量, 其 值 在 動(dòng) 態(tài) 庫 中 是 不 能 被 改 變 的; 如 果 需 要 在 動(dòng) 態(tài) 連 接 庫 中 修 改 傳 入 參 數 的 值, 則 必 須 使 用 傳 址 方 式。 一 般 來(lái) 說(shuō), 在VB 和 動(dòng) 態(tài) 連 接 庫 之 間 傳 遞 單 個(gè) 的 簡(jiǎn) 單 數 據 類(lèi) 型, 只 要 注 意 了 以 上 幾 個(gè) 方 面 就 可 以 了。 當 需 要 將 一 個(gè) 簡(jiǎn) 單 數 據 類(lèi) 型 的 整 個(gè) 數 組 傳 進(jìn) 動(dòng) 態(tài) 庫 時(shí), 必 須 將 相 應 參 數 聲 明 為 傳 址 方 式, 然 后 把 數 組 的 第 一 個(gè) 元 素 作 為 參 數 傳 入, 這 樣 在 動(dòng) 態(tài) 連 接 庫 中 就 得 到 了 數 組 的 首 地 址, 從 而 可 以 對 整 個(gè) 數 組 進(jìn) 行 訪(fǎng) 問(wèn)。 例 如, 聲 明 了 一 個(gè) 名 為ReadArray 的DLL 過(guò) 程, 要 求 傳 入 一 個(gè) 整 型 數 組aArray:

Declare Function ReadArray Lib "mydll.dll" _
(aArray As Integer) As Integer
在 調 用 時(shí) 可 以 采 用 如 下 方 式:
Dim ret,I(5) as Integer
… …
ret = ReadArray(I(0)) ‘ 將 整 個(gè) 數 組 傳 入 動(dòng) 態(tài) 連 接 庫

---- 2、 字 符 串 參 數 的 傳 遞:

---- 與 簡(jiǎn) 單 數 據 類(lèi) 型 相 比, 字 符 串 類(lèi) 型(String、String * n) 的 參 數 傳 遞 要 復 雜 得 多,這 主 要 是Windows 95 API 和VB 使 用 的 字 符 串 類(lèi) 型 不 同 的 緣 故。VB 使 用 被 稱(chēng) 為 BSTR 的 String 數 據 類(lèi) 型, 它 是 由 自 動(dòng) 化( 以 前 被 稱(chēng) 為 OLE Automation) 定 義 的 數 據 類(lèi) 型。 一 個(gè) BSTR 由 頭 部 和 字 符 串 組 成, 頭 部 包 含 了 字 符 串 的 長(cháng) 度 信 息, 字 符 串 中 可 以 包 含 嵌 入 的 null 值。 大 部 分 的 BSTR 是 Unicode 的, 即 每 個(gè) 字 符 需 要 兩 個(gè) 字 節。BSTR 通 常 以 兩 字 節 的 兩 個(gè) null 字 符 結 束。 下 圖 表 示 了 一 個(gè)BSTR 類(lèi) 型 的 字 符 串。

( 前 綴) a T e s t {content}
頭 部 BSTR指向數據的第一個(gè)字節

---- 另 一 方 面, 大 部 分 的DLL 過(guò) 程( 包 括 Windows 95 API 中 的 所 有 過(guò) 程) 使 用 LPSTR 類(lèi) 型 字 符 串, 這 是 指 向 標 準 的 以 null 結 束 的 C 語(yǔ) 言 字 符 串 的 指 針, 它 也 被 稱(chēng) 為 ASCIIZ 字 符 串。LPSTR 沒(méi) 有 前 綴。 下 圖 顯 示 了 一 個(gè) 指 向 ASCIIZ 字 符 串 的 LPSTR。

---- a T e s t {content}

---- LPSTR 指 向 一 個(gè) 以null 結 尾 的 字 符 串 數 據 的 第 一 個(gè) 字 節

---- 如 果 DLL 過(guò) 程 需 要 一 個(gè) LPSTR( 指 向 以 null 結 束 的 字 符 串 的 指 針) 作 為 參 數, 可 以 在VB 中 將 一 個(gè) 字 符 串 以 傳 值 的 方 式 傳 遞 給 它。 因 為 指 向 BSTR 的 指 針 實(shí) 際 指 向 以 null 值 結 束 的 字 符 串 的 第 一 個(gè) 數 據 字 節, 所 以 對 于 DLL 過(guò) 程 來(lái) 說(shuō), 它 就 是 一 個(gè) LPSTR。 這 樣 傳 入 動(dòng) 態(tài) 連 接 庫 的 字 符 串,DLL 過(guò) 程 也 可 以 對 它 進(jìn) 行 修 改, 盡 管 它 是 以 傳 值 方 式 傳 入 的。 只 有 當DLL 過(guò) 程 需 要 一 個(gè) 指 向LPSTR 的 指 針 時(shí), 才 以 傳 址 的 方 式 傳 入 字 符 串, 這 時(shí)DLL 過(guò) 程 得 到 的 是 一 個(gè) 指 向 字 符 串 指 針 的 指 針( 相 當 于C/C++ 中 的char * *), 而 不 是 通 常 所 用 的 字 符 串 的 首 地 址( 相 當 于C/C++ 中 的char *)。

---- 當 需 要 把 一 個(gè) 字 符 串 數 組 整 個(gè) 傳 入 動(dòng) 態(tài) 連 接 庫 時(shí), 情 況 就 變 得 復 雜 多 了, 用 傳 遞 簡(jiǎn) 單 數 據 類(lèi) 型 數 組 的 方 式 來(lái) 傳 遞 字 符 串 數 組 是 行 不 通 的。 當 我 們 以 傳 值 的 方 式 將 一 個(gè) 字 符 串 數 組 的 第 一 個(gè) 元 素 傳 進(jìn) 動(dòng) 態(tài) 連 接 庫 時(shí),DLL 過(guò) 程 得 到 的 實(shí) 際 上 是 該 元 素 壓 入 堆 棧 段 后 的 地 址, 而 不 是 數 據 段 中 整 個(gè) 數 組 的 首 地 址。 也 就 是 說(shuō), 這 時(shí)DLL 過(guò) 程 只 能 得 到 數 組 的 第 一 個(gè) 元 素, 而 無(wú) 法 訪(fǎng) 問(wèn) 整 個(gè) 數 組。 而 以 傳 址 方 式 傳 入 第 一 個(gè) 元 素 時(shí),DLL 過(guò) 程 只 能 得 到 指 向 該 元 素 在 堆 棧 段 中 地 址 的 指 針, 同 樣 無(wú) 法 訪(fǎng) 問(wèn) 整 個(gè) 數 組。 這 不 能 不 說(shuō) 是VB 的 一 個(gè) 不 足。 因 此, 在 程 序 設 計 中, 如 果 確 實(shí) 需 要 將 整 個(gè) 字 符 串 數 組 傳 入 動(dòng) 態(tài) 庫, 就 必 須 采 取 其 它 方 法。

---- 我 們 知 道, 在VB 中, 有 一 種Byte 數 據 類(lèi) 型。 每 個(gè)Byte 型 變 量 占 一 個(gè) 字 節, 不 含 符 號 位, 因 此 所 能 表 示 的 范 圍 為0 到255。 這 種 數 據 類(lèi) 型 是 專(zhuān) 門(mén) 用 于 存 放 二 進(jìn) 制 數 據 的。 為 了 將 整 個(gè) 字 符 串 數 組 傳 進(jìn) 動(dòng) 態(tài) 庫, 可 以 用 字 節 數 組 來(lái) 保 存 字 符 串。 由 于Byte 是 一 種 簡(jiǎn) 單 數 據 類(lèi) 型, 因 此 字 節 數 組 的 傳 遞 是 非 常 簡(jiǎn) 單 的。 首 先, 需 要 把 一 個(gè) 字 符 串 正 確 地 轉 變 成 一 個(gè) 字 節 數 組。 這 要 涉 及 一 些 字 符 集 的 知 識。Windows 95 和VB 使 用 不 同 的 字 符 集,Windows 95 API 使 用 的 是ANSI 或DBCS 字 符 集, 而VB 使 用 的 則 是Unicode 字 符 集。 所 謂ANSI 字 符 集, 是 指 每 個(gè) 字 符 都 用 一 個(gè) 字 節 表 示, 因 此 最 多 只 能 有28=256 個(gè) 不 同 的 字 符, 這 對 于 英 語(yǔ) 來(lái) 說(shuō) 已 經(jīng) 足 夠 了, 但 不 能 完 全 支 持 其 它 語(yǔ) 言。DBCS 字 符 集 支 持 很 多 不 同 的 東 亞 語(yǔ) 言, 如 漢 語(yǔ)、 日 語(yǔ) 和 朝 鮮 語(yǔ), 它 使 用 數 字 0-255 表 示 ASCII 字 符, 其 它 大 于255 或 小 于0 的 數 字 表 明 該 字 符 屬 于 非 拉 丁 字 符 集; 在 DBCS 中,ASCII 字 符 的 長(cháng) 度 是 一 個(gè) 字 節, 而 漢 語(yǔ)、 日 語(yǔ) 和 其 它 東 亞 字 符 的 長(cháng) 度 是 2 個(gè) 字 節。 而Unicode 字 符 集 則 完 全 用 兩 個(gè) 字 節 表 示 一 個(gè) 字 符, 因 此 最 多 可 以 表 示216=65536 個(gè) 不 同 字 符。 也 就 是 說(shuō),ANSI 字 符 集 中 所 有 的 字 符 都 只 占 一 個(gè) 字 節,DBCS 字 符 集 中ASCII 字 符 占 一 個(gè) 字 節, 漢 字 占 兩 個(gè) 字 節,Unicode 字 符 集 中 每 個(gè) 字 符 都 占 兩 個(gè) 字 節。 由 于VB 與Windows API 使 用 的 字 符 集 不 同, 因 此 在 進(jìn) 行 字 符 串 到 字 節 數 組 的 轉 換 時(shí), 當 用Asc 函 數 取 得 一 個(gè) 字 符 的 字 節 碼 后, 需 要 判 斷 它 是 否 是 一 個(gè)ASCII 字 符; 如 果 是ASCII 字 符, 則 在 轉 換 后 的 字 節 數 組 中 就 只 占 一 個(gè) 字 節, 否 則 要 占 兩 個(gè) 字 節。 如 下 流 程 圖 表 示 了 轉 換 一 個(gè) 字 符 串 的 過(guò) 程。

---- 下 面 給 出 了 轉 換 函 數:GetCharByte 得 到 一 個(gè) 字 符 的 高 字 節 或 低 字 節, 它 的 第 一 個(gè) 參 數 是 一 個(gè) 字 符 的ASCII 碼, 第 二 個(gè) 參 數 是 標 志 取 高 字 節 還 是 低 字 節;StrToByte 按DBCS 或ANSI 格 式 將 一 個(gè) 字 符 串 轉 換 成 一 個(gè) 字 節 數 組, 第 一 個(gè) 參 數 是 待 轉 換 的 字 符 串, 第 二 個(gè) 參 數 是 轉 換 后 的 一 個(gè) 定 長(cháng) 字 節 數 組, 若 該 數 組 長(cháng) 度 不 足 以 存 放 整 個(gè) 字 符 串, 則 截 去 超 長(cháng) 的 部 分;ChangeStrAryToByte 利 用 前 兩 個(gè) 函 數 將 字 符 串 數 組 轉 換 成 字 節 數 組, 第 一 個(gè) 參 數 是 定 長(cháng) 的 字 符 串 數 組, 其 中 每 個(gè) 元 素 都 是 一 個(gè) 字 符 串( 各 個(gè) 元 素 包 含 的 字 符 數 可 以 不 同), 第 二 個(gè) 參 數 是 一 個(gè) 變 長(cháng) 的 字 節 數 組, 保 存 轉 換 后 的 結 果。

---- Function GetCharByte(ByVal OneChar As Integer, ByVal IsHighByte As Boolean) As Byte ‘ 該 函 數 獲 得 一 個(gè) 字 符 的 高 字 節 或 低 字 節

If IsHighByte Then
If OneChar >= 0 Then
GetCharByte = CByte(OneChar 256)
‘右移8位,得到高字節
Else
GetCharByte = CByte((OneChar
And &H7FFF) 256) Or &H80
End If
Exit Function
Else
GetCharByte = CByte(OneChar And &HFF)
‘屏蔽掉高字節,得到低字節
Exit Function
End If
End Function

Sub StrToByte(StrToChange As String, ByteArray() As Byte)
‘該函數將一個(gè)字符串轉換成字節數組
Dim LowBound, UpBound As Integer
Dim i, count, length As Integer
Dim OneChar As Integer

count = 0
length = Len(StrToChange)
LowBound = LBound(ByteArray)
UpBound = UBound(ByteArray)

For i = LowBound To UpBound
ByteArray(i) = 0 ‘初始化字節數組
Next

For i = LowBound To UpBound
count = count + 1
If count <= length Then
OneChar = Asc(Mid(StrToChange, count, 1))

If (OneChar > 255) Or (OneChar < 0) Then
‘該字符是非ASCII字符
ByteArray(i) = GetCharByte(OneChar, True) ‘得到高字節
i = i + 1
If i <= UpBound Then ByteArray(i)
= GetCharByte(OneChar, False)
‘得到低字節
Else
‘該字符是ASCII字符
ByteArray(i) = OneChar
End If
Else
Exit For
End If
Next
End Sub

Sub ChangeStrAryToByte(StrAry()
As String, ByteAry() As Byte)
‘將字符串數組轉換成字節數組
Dim LowBound, UpBound As Integer
Dim i, count, StartPos, MaxLen As Integer
Dim TmpByte() As Byte

LowBound = LBound(StrAry)
UpBound = UBound(StrAry)
count = 0
ReDim ByteAry(0)

For i = LowBound To UpBound
MaxLen = LenB(StrAry(i))
ReDim TmpByte(MaxLen + 1)
ReDim Preserve ByteAry(count + MaxLen + 1)
Call StrToByte(StrAry(i), TmpByte) ‘轉換一個(gè)字符串
StartPos = count
Do
ByteAry(count) = TmpByte(count - StartPos)
count = count + 1
If ByteAry(count - 1) = 0 Then Exit Do
Loop ‘將每一個(gè)字符串對應
的字節數組按順序填入結果數組中
ReDim Preserve ByteAry(count - 1)
Next i
End Sub

---- 下 面 看 一 個(gè) 轉 換 的 例 子:

Dim ResultAry() as Byte
Dim SomeStr(2) as String
SomeStr(0) = " 測 試1"
SomeStr(1) = " 測 試222"
SomeStr(2) = " 測 試33"
Call ChangeStrAryToByte
(SomeStr,ResultAry) ‘ 轉 換 字 符 串 數 組

---- 當 轉 換 完 成 以 后, 查 看 字 節 數 組ResultAry, 其 中 包 含 了21 個(gè) 元 素, 依 次 是:178,226,202,212,49,0,178,226,202,212,50,50,50,0,178,226,202,212,51,51,0。 其 中,[178,226] 是" 測" 的 字 節 碼,[202,112] 是" 試" 的 字 節 碼,49,50,51 分 別 為 字 符1、2、3 的ASCII 碼。 可 見(jiàn), 經(jīng) 過(guò) 轉 換 后, 字 符 串 數 組 中 的 各 個(gè) 元 素 按 順 序 放 在 了 字 節 數 組 中, 相 互 間 以 終 止 符0 分 隔。

---- 這 樣, 字 符 串 數 組 就 全 部 轉 換 成 了 字 節 數 組, 然 后 只 要 將 字 節 數 組 的 第 一 個(gè) 元 素 以 傳 址 的 方 式 傳 入 動(dòng) 態(tài) 連 接 庫,DLL 過(guò) 程 就 可 以 正 確 地 訪(fǎng) 問(wèn) 數 組 中 的 所 有 字 符 串 了。 但 是, 使 用 這 種 方 法, 當DLL 過(guò) 程 處 理 結 束 返 回VB 時(shí),VB 得 到 的 仍 然 是 字 節 數 組。 如 果 需 要 在VB 中 再 次 得 到 該 字 節 數 組 表 示 的 字 符 串, 還 要 把 整 個(gè) 字 節 數 組 重 新 以0 為 分 割 符 分 成 多 個(gè) 子 數 組( 每 個(gè) 子 數 組 都 對 應 原 來(lái) 字 符 串 數 組 中 的 一 個(gè) 元 素), 然 后 使 用VB 函 數StrConv 將 每 個(gè) 子 數 組 轉 換 成 字 符 串( 轉 換 時(shí) 第 二 個(gè) 參 數 選vbUnicode), 就 可 以 顯 示 或 進(jìn) 行 其 它 操 作 了。 例 如, 其 中 一 個(gè) 子 數 組 的 名 字 是SubAry, 則 函 數StrConv(SubAry,vbUnicode) 就 返 回 了 它 所 對 應 的 字 符 串。

---- 總 之,VB 應 用 程 序 和 動(dòng) 態(tài) 庫 間 字 符 串 參 數 的 傳 遞 是 一 個(gè) 比 較 復 雜 的 過(guò) 程, 使 用 時(shí) 要 非 常 謹 慎。 同 時(shí) 應 盡 可 能 避 免 傳 遞 字 符 串 數 組 類(lèi) 型 的 參 數, 因 為 這 很 容 易 引 起 下 標 越 界、 堆 棧 溢 出 等 嚴 重 錯 誤。

---- 3、 用 戶(hù) 自 定 義 類(lèi) 型(User-defined Type) 參 數 的 傳 遞

---- 用 戶(hù) 自 定 義 類(lèi) 型 在VB 中 是 一 種 重 要 的 數 據 類(lèi) 型, 它 為 編 程 者 提 供 了 很 大 的 靈 活 性, 使 開(kāi) 發(fā) 人 員 可 以 根 據 需 要 構 造 自 己 的 數 據 結 構。 它 相 當 于C/C++ 中 的 結 構 類(lèi) 型(structure)。 在VB 中, 允 許 程 序 員 以 傳 址 的 方 式 將 自 定 義 數 據 類(lèi) 型 參 數 傳 入 動(dòng) 態(tài) 庫,DLL 過(guò) 程 也 可 以 將 修 改 后 的 參 數 返 回VB 程 序。 但 是, 在VB 中 仍 然 不 支 持 以 傳 值 的 方 式 傳 遞 用 戶(hù) 自 定 義 類(lèi) 型 參 數。

---- 傳 遞 用 戶(hù) 自 定 義 類(lèi) 型 參 數 時(shí), 必 須 確 保VB 中 的 數 據 類(lèi) 型 的 成 員 與 動(dòng) 態(tài) 庫 中 的 結 構 成 員 是 一 一 對 應 的, 所 占 空 間 也 必 須 嚴 格 一 致。 這 里 所 說(shuō) 的 一 一 對 應, 不 僅 是 指VB 中 的 所 有 結 構 成 員 在 動(dòng) 態(tài) 庫 的 結 構 中 都 必 須 有 對 應 的 元 素, 而 且 它 們 在 數 據 結 構 中 定 義 的 順 序 也 必 須 嚴 格 一 致, 這 是VB 中 使 用 的" 數 據 結 構 成 員 對 齊 方 式" 決 定 的。 在VB 中, 數 據 結 構 使 用 雙 字 對 齊 方 式(4-byte alignment), 因 此, 在 用 戶(hù) 自 己 生 成 用 于VB 調 用 的 動(dòng) 態(tài) 連 接 庫 時(shí), 也 必 須 把 編 譯 選 項"structure member alignment" 設 為4 字 節( 如 前 文 所 述)。

---- 所 謂 結 構 成 員 對 齊 方 式 是 指 一 個(gè) 數 據 結 構 內 部, 其 成 員 的 排 列 方 式。 譬 如, 在VB 中, 其 對 齊 方 式 是4 字 節, 這 就 好 象 在 一 個(gè) 數 據 結 構 內 部 分 成 了 很 多 個(gè)4 字 節 大 小 的 小 單 元, 如 果 相 鄰 兩 個(gè) 或 多 個(gè) 數 據 成 員 的 大 小 可 以 放 在 一 個(gè) 單 元 中, 那 么 就 放 在 一 起; 否 則 這 些 小 單 元 中 可 能 會(huì ) 出 現 未 用 的 空 字 節。 我 們 來(lái) 看 下 面 一 個(gè) 數 據 類(lèi) 型:

Type TestType
m1 as Integer
m2 as Byte
m3 as Long
End Type

---- 它 的 三 個(gè) 成 員 的 大 小 加 起 來(lái) 是2+1+4=7。 但 是, 由 于m1 和m2 的 字 節 總 長(cháng) 度 是3, 小 于4, 它 們 就 存 放 于 一 個(gè) 單 元 中; 但 該 單 元 剩 下 的 一 個(gè) 字 節 不 足 以 放 下 一 個(gè)Long 型 的 成 員m3, 于 是m3 就 被 放 在 下 一 個(gè) 單 元 中, 它 們 之 間 就 有 了 一 個(gè) 未 用 的 空 字 節; 因 此, 整 個(gè) 結 構 所 占 實(shí) 際 長(cháng) 度 是8 字 節。 同 理, 如 果 將m3 和m2 的 位 置 交 換 一 下, 它 所 占 的 尺 寸 就 變 成 了9 字 節。 可 見(jiàn), 成 員 在 結 構 中 的 聲 明 順 序 也 是 非 常 重 要 的。

---- 通 常, 當 一 個(gè) 用 戶(hù) 自 定 義 類(lèi) 型 中 不 包 含 字 符 串 時(shí), 向 動(dòng) 態(tài) 連 接 庫 中 傳 遞 該 類(lèi) 型 的 參 數 是 沒(méi) 有 什 么 問(wèn) 題 的。 如 果 只 傳 遞 一 個(gè) 自 定 義 類(lèi) 型 變 量, 則 既 可 以 傳 遞 該 變 量 名, 也 可 以 傳 遞 該 變 量 的 第 一 個(gè) 成 員, 它 們 的 效 果 是 一 樣 的, 都 是 將 該 變 量 的 地 址 傳 進(jìn) 了 動(dòng) 態(tài) 庫; 同 樣, 如 果 要 傳 遞 一 個(gè) 自 定 義 類(lèi) 型 的 數 組, 則 既 可 以 傳 遞 該 數 組 的 第 一 個(gè) 元 素, 也 可 以 傳 遞 第 一 個(gè) 元 素 的 第 一 個(gè) 成 員。 但 是, 如 果 用 戶(hù) 自 定 義 類(lèi) 型 中 包 含 字 符 串 類(lèi) 型 時(shí), 又 該 如 何 與 動(dòng) 態(tài) 連 接 庫 傳 遞 參 數 呢 ? 答 案 是 令 人 遺 憾 的: 在VB 中, 你 無(wú) 法 將 一 個(gè) 包 含 字 符 串 成 員 的 用 戶(hù) 自 定 義 類(lèi) 型 變 量 或 數 組 安 全、 正 確 地 傳 入 動(dòng) 態(tài) 庫 中。 如 果 你 這 樣 做 了, 即 使 某 次 僥 幸 得 到 了 正 確 的 結 果, 在 其 背 后 也 隱 藏 著(zhù) 許 多 致 命 的 危 險。 因 此, 如 果 一 定 要 在 用 戶(hù) 自 定 義 類(lèi) 型 中 包 含 字 符 串 變 量, 并 且 該 類(lèi) 型 的 變 量 又 要 作 為 參 數 傳 入 動(dòng) 態(tài) 庫 時(shí), 你 最 好 修 改 類(lèi) 型 定 義, 把 其 中 的 字 符 串 成 員 用 相 應 的 字 節 數 組 類(lèi) 型 替 換 掉( 轉 換 方 法 可 參 見(jiàn) 前 文), 這 樣 就 可 以 在VB 和 動(dòng) 態(tài) 庫 間 傳 遞 這 種 類(lèi) 型 的 參 數 了。

---- 另 外, 在VB 中 還 可 以 把 一 個(gè) 函 數 的 指 針 傳 遞 到 動(dòng) 態(tài) 庫 中, 方 法 也 并 不 復 雜。 但 筆 者 強 烈 建 議 最 好 不 要 這 么 做, 因 為 這 樣 一 來(lái)VB 應 用 程 序 就 幾 乎 完 全 喪 失 了 它 所 應 有 的 安 全 性。 如 果 確 實(shí) 需 要 傳 遞 函 數 指 針 的 話(huà), 那 么 還 是 編 一 個(gè)C/C++ 的 程 序 來(lái) 完 成 這 項 工 作 吧。

---- 總 之, 在VB 中 調 用DLL 過(guò) 程 是 一 個(gè) 比 較 復 雜 的 問(wèn) 題, 編 程 人 員 必 須 很 好 地 把 握, 才 能 達 到 既 提 高 了 程 序 效 率, 開(kāi) 拓 了 程 序 功 能, 又 不 降 低 程 序 安 全 性 的 目 的。 另 外 需 要 特 別 指 出 的 一 點(diǎn) 是, 在 本 文 中 提 到 的 所 有 動(dòng) 態(tài) 連 接 庫, 都 是 指 沒(méi) 有 使 用 自 動(dòng) 化(OLE Automation) 技 術(shù) 的 動(dòng) 態(tài) 庫,Windows API 和 大 多 數 用 戶(hù) 自 編 的 動(dòng) 態(tài) 連 接 庫 都 是 這 種 類(lèi) 型 的。 對 于 使 用 了OLE Automation 技 術(shù) 的 動(dòng) 態(tài) 連 接 庫, 其 參 數 傳 遞 的 方 式 有 所 不 同, 讀 者 可 以 參 閱 有 關(guān)OLE 技 術(shù) 的 書(shū) 籍, 在 此 不 再 涉 及。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
在VB中使用API函數詳解
VB編外掛的一些基礎知識
什么是API
C語(yǔ)言的DLL怎么給VB返回String(char*)呢
vc vb dll 參數傳遞
c-vb Type
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久