指定字元集

DllImportAttribute.CharSet 欄位會控制字串封送處理,並決定平台叫用如何在 DLL 中尋找函式名稱。 這個主題將描述這兩種行為。

某些 API 匯出兩個版本的函式,接受字串引數:窄 (ANSI) 和寬 (Unicode)。 例如,Win32 API 包括 MessageBox 函式的下列進入點名稱:

  • MessageBoxA

    提供 1 個位元組字元 ANSI 格式化,區別方式是在進入點名稱附加 "A"。 MessageBoxA 呼叫一律以 ANSI 格式的字串封送處理。

  • MessageBoxW

    提供 2 個位元組字元 Unicode 格式化,區別方式是在進入點名稱附加 "W"。 MessageBoxW 呼叫一律以 Unicode 格式的字串封送處理。

字串封送處理與名稱比對

CharSet 欄位可接受下列值:

Ansi (預設值)

  • 字串封送處理

    平台叫用會將字串從其受管理的格式 (Unicode) 封送處理為 ANSI 格式。

  • 名稱比對

    DllImportAttribute.ExactSpelling 欄位是 true 時,如同 Visual Basic 中的預設值,平台叫用僅會搜尋您指定的名稱。 例如,如果您指定 MessageBox,平台叫用會搜尋 MessageBox,並在找不到正確的拼字時失敗。

    ExactSpelling 欄位是 false 時,如同在 C++ 和 C# 中的預設值,平台叫用會先搜尋未損壞別名 (MessageBox),然後如果找不到未損壞別名則搜尋損壞名稱 (MessageBoxA)。 請注意,ANSI 名稱比對行為不同於 Unicode 名稱比對行為。

Unicode

  • 字串封送處理

    平台叫用會將字串從其受管理的格式 (Unicode) 複製為 Unicode 格式。

  • 名稱比對

    ExactSpelling 欄位是 true 時,如同 Visual Basic 中的預設值,平台叫用僅會搜尋您指定的名稱。 例如,如果您指定 MessageBox,則平台叫用會搜尋 MessageBox,並在找不到正確的拼字時失敗。

    ExactSpelling 欄位是 false 時,如同在 C++ 和 C# 中的預設值,平台叫用會先搜尋損壞名稱 (MessageBoxW),然後如果找不到損壞名稱則搜尋未損壞別名 (MessageBox)。 請注意,Unicode 名稱比對行為不同於 ANSI 名稱比對行為。

Auto

  • 平台叫用會在執行階段,根據在目標平台,在 ANSI 和 Unicode 格式之間選擇。

在 Visual Basic 中指定字元集

在 Visual Basic 中,您可以透過在宣告陳述式中新增 AnsiUnicodeAuto 關鍵字,來指定字元集行為。 如果您省略字元集關鍵字,DllImportAttribute.CharSet 欄位會預設為 ANSI 字元集。

下列範例會宣告 MessageBox 函式三次,每次都有不同的字元集行為。 第一個陳述式會省略字元集關鍵字,因此字元集會預設為 ANSI。 第二個和第三個陳述式會明確地以關鍵字指定字元集。

Friend Class NativeMethods
    Friend Declare Function MessageBoxA Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer

    Friend Declare Unicode Function MessageBoxW Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer

    Friend Declare Auto Function MessageBox Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
End Class

在 C# 和 C++ 中指定字元集

DllImportAttribute.CharSet 欄位將基礎字元集識別為 ANSI 或 Unicode。 字元集可控制應該如何封送處理方法的字串引數。 您可以使用下列格式之一來表示字元集:

[DllImport("DllName", CharSet = CharSet.Ansi)]
[DllImport("DllName", CharSet = CharSet.Unicode)]
[DllImport("DllName", CharSet = CharSet.Auto)]
[DllImport("DllName", CharSet = CharSet::Ansi)]
[DllImport("DllName", CharSet = CharSet::Unicode)]
[DllImport("DllName", CharSet = CharSet::Auto)]

下列範例示範 MessageBox 函式的三個 Managed 定義,其已屬性化以指定字元集。 在第一個定義中,根據其省略,CharSet 欄位預設為 ANSI 字元集。

using System;
using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    internal static extern int MessageBoxA(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    internal static extern int MessageBoxW(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    internal static extern int MessageBox(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
typedef void* HWND;

// Can use MessageBox or MessageBoxA.
[DllImport("user32")]
extern "C" int MessageBox(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

// Can use MessageBox or MessageBoxW.
[DllImport("user32", CharSet = CharSet::Unicode)]
extern "C" int MessageBoxW(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

// Must use MessageBox.
[DllImport("user32", CharSet = CharSet::Auto)]
extern "C" int MessageBox(
    HWND hWnd, String* lpText, String* lpCaption, unsigned int uType);

另請參閱