首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

VC++ 代碼轉 VB 代碼完全指南:常量、結構、API 聲明

     編輯:VC++

前言:為什麼需要轉換?

VB6/VBA 開發者常需調用 Windows API 實現高級功能,而 MSDN、開源項目多提供 C/C++ 版本定義。掌握 VC++ → VB 核心類型映射、常量轉換、結構對齊、函數聲明規則,即可無障礙移植代碼。

一、常量定義轉換

1. 簡單宏 #define

// VC++
#define STD_COPY 1
#define LB_SELECTSTRING 0x018C

' VB
Public Const STD_COPY = 1
Public Const LB_SELECTSTRING = &H18C  ' 十六進制 0x -> &H

2. 表達式常量

// VC++
#define TCN_FIRST (0U - 550U)  ' U 表示 unsigned long

' VB
' VB 無 unsigned 類型,Long 為有符號 32 位,存儲位模式相同
Public Const TCN_FIRST = (0 - 550)  ' 直接去掉 U/L 後綴
' 同理:#define VAL 123L  ->  Public Const VAL = 123

3. 位運算組合

// VC++
#define CDDS_ITEMPOSTERASE (CDDS_ITEM | CDDS_POSTERASE)

' VB
' | (按位或) -> Or
Public Const CDDS_ITEMPOSTERASE = (CDDS_ITEM Or CDDS_POSTERASE)

二、結構體 (struct) 轉換 (Type)

類型映射核心表

VC++ 類型VB 類型說明
char / signed charByte1 字節
unsigned char / BYTEByte
short / SHORTInteger2 字節
int / long / LONG / INTLong4 字節 (Win32 下 int=long=4 字節)
unsigned int / UINT / DWORD / ULONGLongVB 無無符號,用 Long 存儲位模式
WPARAM / LPARAM / LRESULTLong32 位系統下均為 4 字節
HWND / HDC / HANDLE / HBRUSH / HKEY / HINSTANCELong句柄本質是指針/索引,32 位下用 Long
floatSingle4 字節
doubleDouble8 字節
BOOLLongVC++ 4 字節,VB Boolean 僅 2 字節,必須用 Long
LPSTR / LPCSTR / char*String傳遞給 API 時 VB 自動轉 ANSI 指針 (ByVal)
LPWSTR / LPCWSTR / wchar_t*StringVB6 內部 Unicode,傳遞時轉 ANSI;建議用 Byte 數組或 StrPtr 配合 Wide API
指針類型 (* / **)Long地址值存儲
VARIANTVariant直接對應

實戰轉換示例

// VC++ (commctrl.h)
typedef struct tagTBSAVEPARAMSA {
    HKEY hkr;
    LPCSTR pszSubKey;
    LPCSTR pszValueName;
} TBSAVEPARAMSA, *LPTBSAVEPARAMSA;

' VB
Public Type TBSAVEPARAMSA
    hkr As Long           ' HKEY -> Long
    pszSubKey As String   ' LPCSTR -> String
    pszValueName As String
End Type
' 注意:VB Type 不支持指針成員,結構大小固定。
' 若結構含可變長數組/指針,需拆分為定長部分 + 額外分配內存 (VarPtr/CopyMemory) 處理。

關鍵注意點

  • 對齊: VC++ 默認 8 字節對齊 (`#pragma pack(8)`),VB `Type` 成員按聲明順序緊湊排列 (1 字節對齊)。涉及 API 交互的結構,**必須在 VC++ 端用 `#pragma pack(1)` 或 `#pragma pack(4)` 確保一致**,或在 VB 端手動添加填充字節 (`Dummy As Byte` 等)。
  • 可變長數組: `DWORD dwReserved[10]` 易轉換;`BYTE data[1]` (柔性數組) 在 VB 中無法直接表示,需定義定長部分,運行時分配內存 `GlobalAlloc`,用 `CopyMemory` 讀寫數據區。
  • 嵌套結構: VB `Type` 支持嵌套,成員類型為另一個 `Public Type`。

三、函數/ API 聲明轉換

標準模板

// VC++
WINCOMMCTRLAPI HWND WINAPI CreateStatusWindowA(
    LONG style, LPCSTR lpszText, HWND hwndParent, UINT wID
);  // 來自 ComCtl32.dll

' VB
' 1. 確定 DLL 名 (MSDN 文檔底部或 Dependency Walker 查看)
' 2. 返回類型映射 (HWND -> Long)
' 3. 參數映射 (按類型表)
' 4. 字符串參數建議 ByVal ... As String (VB 自動 ANSI 轉換)
' 5. 其餘參數 ByVal 避免修改原值
Public Declare Function CreateStatusWindowA Lib "ComCtl32.dll" (
    ByVal style As Long,
    ByVal lpszText As String,
    ByVal hwndParent As Long,
    ByVal wID As Long
) As Long

調用約定與修飾符

VC++ 關鍵字含義VB 處理
WINAPI / __stdcall標準調用 (被調用者清棧)VB 默認即 StdCall,無需聲明
__cdeclC 調用 (調用者清棧)VB **不支持** 直接調用,需編寫 StdCall 包裝 DLL 中轉
__fastcall寄存器傳參VB 不支持,同需包裝
__declspec(dllimport)導入聲明VB `Declare` 隱含此意

字符串參數進階

  • LPSTR (輸出緩衝區):VB 傳 ByVal String 會導致崩潰。**正確做法**:定義固定長度字符串 `Dim buf As String * 256`,傳 `ByVal buf`,調用後用 `Left$(buf, InStr(buf, Chr$(0))-1)` 截取。
  • LPCSTR (只讀輸入):ByVal str As String 安全。
  • Unicode 版 API (以 `W` 結尾,如 `CreateWindowExW`):VB6 內部 Unicode,可用 `StrPtr(str)` 獲取指針,聲明參數為 `ByVal Long`,或使用類型庫 (TLB) 導入。

四、回調函數轉換

// VC++
typedef BOOL (CALLBACK* WNDENUMPROC)(HWND hwnd, LPARAM lParam);
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam);

' VB
' 1. 模塊中聲明 (必須在標準模塊,非類模塊)
Public Declare Function EnumWindows Lib "user32" (
    ByVal lpEnumFunc As Long,  ' 地址傳遞
    ByVal lParam As Long
) As Long

' 2. 回調函數 (標準模塊,Public)
Public Function MyEnumProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
    ' 處理邏輯
    MyEnumProc = 1 ' 繼續枚舉
End Function

' 3. 獲取函數地址調用 (VB6 無 AddressOf 運算符直接用於 API 參數)
' 技巧:使用 AddressOf 獲取地址傳給 Long 參數
Dim lpfn As Long: lpfn = AddressOf MyEnumProc
EnumWindows lpfn, 0
' 注意:VB6 AddressOf 僅在傳給 Long 參數時有效,回調函數必須在標準模塊,且項目屬性勾選 "Compile to Native Code" 且無 p-code 優化干擾。

五、常見陷阱總結

陷阱現象修正
BOOL vs BooleanVC++ 4 字節,VB Boolean 2 字節,棧錯位VB 用 Long 接收 BOOL
字符串輸出緩衝區傳 ByVal String 導致寫入只讀內存崩潰預分配固定長度 String * N,傳 ByVal
結構對齊不一致API 讀寫錯誤字段VC++ 加 `#pragma pack(4)` 或 VB 手動填充
__cdecl 函數調用後棧不平衡崩潰寫 C++ 包裝 DLL 轉為 __stdcall
64 位兼容Long 截斷指針/句柄VB7+ (VBA7) 用 `LongPtr` / `LongLong` + `PtrSafe`

工具推薦

  • API Viewer (VB6 自帶/增強版):內置海量 API 聲明,可直接複製
  • Pinvoke.net:雖針對 .NET,但類型映射表極具參考價值
  • Dependency Walker:查看 DLL 導出函數、參數個數、調用約定
  • VC++ 編譯器預處理輸出 (`/E`):展開宏、條件編譯,獲取最終結構定義

總結

VC++ 轉 VB 核心在於:**類型映射表內化、結構對齊對齊、調用約定 StdCall、字符串輸出預分配、回調地址 AddressOf**。掌握這五大鐵律,配合工具輔助,將 C/C++ SDK 文檔轉化為 VB 可用聲明不再是障礙,而是標準化的機械翻譯過程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved