VisualBasicのDllImportを使ってWindowsAPIを呼び出す

|

前回に続いて、DLLに実装されたアンマネージド関数をマネージドコードから呼び出すことが出来る「プラットフォーム呼出し(PInvoke)」を使って、VBからWin32APIを呼び出してみます。

取り敢えず、DllImport 属性を使用して MessageBox を呼び出すだけのサンプルを作ってみました。

DllImport 属性でDLL内の名前を指定する事によって、引数と戻り値の相互運用マーシャリングも行われます。

ExactSpelling 項目は CharSet 項目の設定内容に影響を与えます。ExactSpelling を省略すると ExactSpelling:=False として扱われるよです。

ExactSpelling:=False の場合、CharSet の Auto、Ansi、Unicode 設定は柔軟に作用しますが、ExactSpelling:=True の場合は厳格に適用されます。

CharSet と EntryPoint と ExactSpelling 項目間の設定内容に不一致などがあると、メッセージボックス内で文字化けが起きたり、例外が発生したりします。


<注意点>

・DllImport はクラスのインスタンスを必要とするメソッドは使用できません。呼出しで共有(静的)メソッドを参照している場合にのみ、Windows API を呼び出せます。

・Visual Basic のデフォルトの文字セットは、UNICODE です。


お試し環境
  WindowsXP 32bit Edition、Windows7 64bit Edition
  Visual Basic 2008


/*-------------------------------- お試し結果 ------------------------------*/

・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBox", ExactSpelling:=False, ...)> _ の場合

auto&false メッセージボックス表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBox", ExactSpelling:=False, ...)> _ の場合

ansi&false メッセージボックス表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBox", ExactSpelling:=False, ...)> _ の場合

unicode&false メッセージボックス表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合

auto&true-1 例外エラー表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合

ansi&true-1 例外エラー表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合

unicode&true-1 例外エラー表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxA", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合

auto&false, true メッセージボックス文字化け表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxW", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合

ansi&false, true メッセージボックス文字化け表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxA", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合

unicode&false, true メッセージボックス文字化け表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合

auto&true-2 メッセージボックス表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合

ansi&true-2 メッセージボックス表示


・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合

unicode&true-2 メッセージボックス表示


/*----------------------------------------------------------------------------*/


/*-------------------------------- お試しソース ----------------------------*/

Imports System.Runtime.InteropServices

Public Class Form1

    Const MB_ICONQUESTION As Integer = &H20
    Const MB_YESNO As Integer = &H4
    Const ID_YES As Integer = 6
    Const ID_NO As Integer = 7

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ' Stores the return value.
        Dim RetVal As Integer

        Try
            RetVal = MBox5(0, "DllImport-exactspelling & unmanaged Windows API Test", "MBox5 charset auto", MB_ICONQUESTION Or MB_YESNO)

            ' Check the return value.
            If RetVal = ID_YES Then
                MsgBox("choice Yes", , "MBox5")
            Else
                MsgBox("choice No", , "MBox5")
            End If

        Catch ex As EntryPointNotFoundException
            MessageBox.Show(ex.Message, "MBox5の例外エラーを捕捉しました")
        Catch ex As Exception
            MessageBox.Show(ex.Message, "その他の例外エラーを捕捉しました")
        End Try

        Try
            RetVal = MBox6(0, "DllImport-exactspelling & unmanaged Windows API Test", "MBox6 charset ansi", MB_ICONQUESTION Or MB_YESNO)

            ' Check the return value.
            If RetVal = ID_YES Then
                MsgBox("choice Yes", , "MBox6")
            Else
                MsgBox("choice No", , "MBox6")
            End If

        Catch ex As EntryPointNotFoundException
            MessageBox.Show(ErrorToString(), "MBox6の例外エラーを捕捉しました")
        Catch ex As Exception
            MessageBox.Show(ErrorToString(), "その他の例外エラーを捕捉しました")
        End Try

        Try
            RetVal = MBox7(0, "DllImport-exactspelling & unmanaged Windows API Test", "MBox7 charset unicode", MB_ICONQUESTION Or MB_YESNO)

            ' Check the return value.
            If RetVal = ID_YES Then
                MsgBox("choice Yes", , "MBox7")
            Else
                MsgBox("choice No", , "MBox7")
            End If

        Catch ex As EntryPointNotFoundException
            MessageBox.Show(ex.Message, "MBox7の例外エラーを捕捉しました")
        Catch ex As Exception
            MessageBox.Show(ex.Message, "その他の例外エラーを捕捉しました")
        End Try

    End Sub

    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto, EntryPoint:="MessageBoxW", ExactSpelling:=True, SetLastError:=True)> _
    Public Shared Function MBox5(ByVal hWnd As Integer, ByVal text As String, ByVal caption As String, ByVal type As Integer) As Integer
    End Function

    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxA", ExactSpelling:=True, SetLastError:=True)> _
    Public Shared Function MBox6(ByVal hWnd As Integer, ByVal text As String, ByVal caption As String, ByVal type As Integer) As Integer
    End Function

    <DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxW", ExactSpelling:=True, SetLastError:=True)> _
    Public Shared Function MBox7(ByVal hWnd As Integer, ByVal text As String, ByVal caption As String, ByVal type As Integer) As Integer
    End Function

End Class

/*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/*============================================================================*/