前回に続いて、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, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBox", ExactSpelling:=False, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBox", ExactSpelling:=False, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBox", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxA", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxW", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxA", ExactSpelling:=False, ...)> _
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Auto, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Ansi, EntryPoint:="MessageBoxA", ExactSpelling:=True, ...)> _ の場合
・<DllImport("user32.dll", ... CharSet:=CharSet.Unicode, EntryPoint:="MessageBoxW", ExactSpelling:=True, ...)> _ の場合
/*----------------------------------------------------------------------------*/
/*-------------------------------- お試しソース ----------------------------*/
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
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/*============================================================================*/