首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Win32 API 句柄參數類型選擇:int 與 IntPtr 的區別

     編輯:程式設計綜合問答

直接回答

`SendMessage` 等 Win32 API 有**多個重載簽名**,參數類型根據消息類型(`wParam`/`lParam` 含義)而異:

  • 部分消息的 `wParam`/`lParam` 是**整數值**(如 `WM_SETTEXT` 的 `lParam` 是字符串指針,但 `WM_CLOSE` 兩參數均為 0)→ 簽名用 `int`/`uint`。
  • 部分消息的參數是**指針/句柄**(如 `WM_GETTEXT` 的 `lParam` 是緩衝區指針,`HWND` 類型)→ 簽名用 `IntPtr`/`HandleRef`。

C# P/Invoke 正確簽名模式

// 通用簽名:使用 IntPtr 兼容所有指針/句柄/整數(推薦)
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

// 特定消息重載:針對 wParam/lParam 為整數值的場景
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

// 字符串專用重載(lParam 為 StringBuilder)
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

為什麼不能隨意用 int?

最佳實踐

  1. **優先使用 `IntPtr` 通用簽名**,調用時傳入 `IntPtr.Zero`、`(IntPtr)intValue`、`handle.DangerousGetHandle()`、`Marshal.StringToHGlobalAuto(str)` 等。
  2. 針對高頻消息(如 `WM_SETTEXT`、`WM_GETTEXTLENGTH`)提供**特化重載**(`int`/`StringBuilder`),提升可讀性與性能(避免裝箱)。
  3. 參考 pinvoke.net 獲取標準簽名,勿自行猜測。

總結

「同一句柄參數,有的用 `int` 有的用 `IntPtr`」是因為 **API 重載** 針對不同消息的參數語義優化。**64 位安全**請統一用 `IntPtr`,特定整數值消息可用 `int` 重載。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景用 int 後果正確類型
64 位進程傳遞指針/句柄截斷高 32 位 → 訪問違規/崩潰IntPtr (隨平台 32/64 位)
傳遞 32 位整數值正常工作int / uint 均可
傳遞 64 位整數 (LONG_PTR)截斷IntPtr / long