このページをはてなブックマークに追加このページを含むはてなブックマーク このページをlivedoor クリップに追加このページを含むlivedoor クリップ

目次

API関数の定義

 VB.NETでAPI関数を定義する方法を2通りある。

Declare構文による定義

[関数スコープ] Declare [文字セット] Function(Sub) API関数名 _
	Lib "DLLファイル名" _
	[Alias "エイリアス名"](引数) _
	[As 戻り値のデータ型]

例:GetWindowText API関数の宣言

Public Shared Declare Auto Function GetWindowText Lib "user32" ( _
	ByVal hWnd As IntPtr, _
	ByVal lpString As StringBuilder, _
	ByVal nMaxCount As Integer) _
	As Integer

[補講]他のクラスから呼び出される可能性があるときは、Shared修飾子を付ける。 ◇

関数スコープ

 Private,Publicなどの関数のスコープを決める修飾子を指定する。

文字セット

 APIに文字列を渡す際の文字コードを指定する。

  1. Auto
    • 関数名またはエイリアス名から文字コードを自動的に判断して変換する。
    • 省略するとAutoが選択されたことになる。
  2. Ansi
    • 文字コードをANSI(シフトJIS)を変換して表す。
  3. Unicode
    • 文字コードをUnicodeに変換して渡す。

API関数名

 API関数の名称を記述する。DLL内で定義されているAPI関数名と異なる名称を指定することもできるが、その場合はエイリアス名でDLL内での関数の名称を指定する必要がある。

DLLファイル名

 宣言するAPI関数を提供しているDLLのファイル名を記述する。

 システムフォルダや呼び出す実行ファイルと同じフォルダに存在しないDLLの場合は、フルパスで指定する必要がある。

エイリアス名

 呼び出すAPI関数のエイリアス名を記述する。

 API名とエイリアス名が同じ場合には省略可能である。

引数

 VB.NETではデフォルトの引数の参照方法がByValの値渡しなので、参照渡しをしたい場合はByRefを指定する。

戻り値のデータ型

 API実行後の戻り値のデータ型を記述する。

DllImport属性による定義

 VB.NETの機能の1つである属性とは、クラスのメンバ・メソッド・関数などに追加情報を持たせる機能のことである。ここで使うDllImport属性は、定義するAPIに合わせた引数を持つ空の関数に適用することで、外部のDLLで定義された関数を呼び出す。

 書式は次の通りである。

<DllImport("'''DLL名'''", EntryPoint:="'''API関数名'''", CharSet:='''Charset''', ExactSpelling:='''boolean''')> '''関数定義'''

例:GetWindowText API関数の宣言

Imports System.Runtime.InteropServices

<DllImport("user32", EntryPoint:="GetWindowText", CharSet:=CharSet.Auto)> _
    Public Shared Function GetWindowText( _
        ByVal hWnd As IntPtr, _
        ByVal lpString As StringBuilder, _
        ByVal nMaxCount As Integer) _
        As Integer
    End Function

CharSet

 APIに文字列を渡す際の文字コードを指定する。

  • Charset.Auto
  • Charset.Ansi
  • Charset.Unicode

ExactSpelling

 EntryPointで指定したAPI関数のみを呼び出すかどうかを指定する。

 Falseの場合、CharSetで指定した文字コードにしたがい、○○A,○○Wを呼び出そうと試みる。省略した場合にはFalse扱いになる。

API関数の定義における注意点

 VB.NETでAPI関数を定義する際には、引数や戻り値の型、構造体やポインタの扱いに注意が必要である。

 次にSDKの型とVB.NETの型の対応表を示す。

SDKVB.NET
INTInteger
BYTEByte
BOOLBoolean
UNITUnit32
SHORTShort
WORDShort
DWORDUnit32
FLOATSingle
CHARChar
WCHARChar
LPWSTRString(StringBuilder)
LPTWSTRString(StringBuilder)
LPSTRString(StringBuilder)
LPCSTRString(StringBuilder)
LPCWSTRString(StringBuilder)
LPCTSTRString(StringBuilder)
HINSTANCEIntPtr
HANDLEIntPrt
HWNDIntPtr(Form.Handle)
HDCIntPtr
HGDIOBJIntPtr
GDIオブジェクトIntPtr
WPARAMInteger
LPARAMInteger
LRESULTInteger

 文字列の扱いで注意すべき点がある。VB.NETからAPIへ文字列を渡す場合はString型を使えばよい。なぜならば内部ではUnicodeとして処理されるが、VB.NETでは関数の呼び出し時に文字コードを自動的に変換してくれるからである。

 一方、VB.NETがAPIから文字列を受け取る場合はString型でもうまくいかない。なぜならば、.NET FrameworkのStytem.Stringクラスは一度初期化した文字列は変更されないという性質を持つからである。そこで、String型ではなく、System.Text.StringBuilderクラスを使う。このクラスはString型と同様に文字列を扱うことができ、宣言後にも値を変更できるので、APIから文字列を受け取ることができるのである。

Dim s As System.Text.StringBuilder = New System.Text.StringBuilder(1024)

 もし、String型の変数やコントロールのTextプロパティにStringBuilder型の値(文字列)を代入させたい場合は、ToStringメソッドを使えばよい。

Form1.Text = s.ToString

構造体

 VB.NETでの構造体は、最適化のためにメンバの並びが変わることがある。一方、APIではメンバの並びは定義した順に並んでいる必要がある。そのため、単純に構造体を渡してしまうとエラーになってしまうことがある。

 そこで、構造体の定義において、<StructLayout>属性を付けてメンバの並びを固定化する必要がある。

クラス

 構造体の代わりにクラスを用いることもできる。例えば、構造体は値型であり、構造体をNothingに指定すると、そのメンバがデフォルト値に初期化される。

参考文献

  • 『Win32 APIのしくみ』