次の方法で共有


チュートリアル: Windows API の呼び出し (Visual Basic)

Windows API は、Windows オペレーティング システムの一部であるダイナミック リンク ライブラリ (DLL) です。 独自の同等のプロシージャを記述することが困難な場合は、それらを使用してタスクを実行します。 たとえば、Windows には FlashWindowEx という名前の関数が用意されています。これにより、アプリケーションのタイトル バーを明るい網かけと濃色の間で交互に表示できます。

コードで Windows API を使用する利点は、既に記述され、使用されるのを待っている便利な関数が多数含まれているため、開発時間を節約できることです。 欠点は、Windows API の操作が難しく、問題が発生した場合に容赦できないことです。

Windows API は、相互運用性の特別なカテゴリを表します。 Windows API はマネージド コードを使用せず、組み込みのタイプ ライブラリも使用せず、Visual Studio で使用されているものとは異なるデータ型を使用します。 これらの違いがあり、Windows API が COM オブジェクトではないため、プラットフォーム呼び出し (PInvoke) を使用して Windows API と .NET Framework との相互運用性が実行されます。 プラットフォーム呼び出しは、マネージド コードが DLL に実装されているアンマネージ関数を呼び出すサービスです。 詳細については、「 アンマネージ DLL 関数の使用」を参照してください。 Declare ステートメントを使用するか、DllImport属性を空のプロシージャに適用することで、Visual Basic で PInvoke を使用できます。

Windows API 呼び出しは、以前は Visual Basic プログラミングの重要な部分でしたが、Visual Basic .NET ではめったに必要ありません。 可能な限り、Windows API 呼び出しではなく、.NET Framework のマネージド コードを使用してタスクを実行する必要があります。 このチュートリアルでは、Windows API の使用が必要な状況に関する情報を提供します。

次の手順では、一部の Visual Studio ユーザー インターフェイス要素の名前や場所がコンピューターに異なる場合があります。 これらの要素は、使用している Visual Studio エディションと使用する設定によって決まります。 詳細については、「IDEのカスタマイズ」を参照してください。

Declare を使用した API 呼び出し

Windows API を呼び出す最も一般的な方法は、 Declare ステートメントを使用することです。

DLL プロシージャを宣言するには

  1. 呼び出す関数の名前と、その引数、引数の型、戻り値、およびそれを含む DLL の名前と場所を決定します。

    Windows API の詳細については、プラットフォーム SDK Windows API の Win32 SDK ドキュメントを参照してください。 Windows API で使用される定数の詳細については、プラットフォーム SDK に含まれている Windows.h などのヘッダー ファイルを調べます。

  2. [ファイル] メニューの [新規作成] をクリックし、[プロジェクト] をクリックして、新しい Windows アプリケーション プロジェクトを開きます。 [新しいプロジェクト] ダイアログ ボックスが表示されます。

  3. Visual Basic プロジェクト テンプレートの一覧から [Windows アプリケーション ] を選択します。 新しいプロジェクトが表示されます。

  4. DLL を使用するクラスまたはモジュールに、次の Declare 関数を追加します。

    Declare Auto Function MBox Lib "user32.dll" Alias "MessageBox" (
        ByVal hWnd As Integer,
        ByVal txt As String,
        ByVal caption As String,
        ByVal Typ As Integer) As Integer
    

Declare ステートメントの一部

Declare ステートメントには、次の要素が含まれています。

自動修飾子

Auto修飾子は、共通言語ランタイム規則 (または指定されている場合はエイリアス名) に従って、メソッド名に基づいて文字列を変換するようにランタイムに指示します。

Lib キーワードと Alias キーワード

Function キーワードに続く名前は、インポートされた関数にアクセスするためにプログラムが使用する名前です。 呼び出す関数の実際の名前と同じにすることも、任意の有効なプロシージャ名を使用し、 Alias キーワードを使用して呼び出す関数の実名を指定することもできます。

Lib キーワードの後に、呼び出す関数を含む DLL の名前と場所を指定します。 Windows システム ディレクトリにあるファイルのパスを指定する必要はありません。

呼び出している関数の名前が有効な Visual Basic プロシージャ名ではない場合、またはアプリケーション内の他の項目の名前と競合する場合は、 Alias キーワードを使用します。 Alias は、呼び出される関数の真の名前を示します。

引数とデータ型の宣言

引数とそのデータ型を宣言します。 この部分は、Windows で使用されるデータ型が Visual Studio のデータ型に対応していないため、困難な場合があります。 Visual Basic では、引数を互換性のあるデータ型 ( マーシャリングと呼ばれるプロセス) に変換することで、多くの作業が行われます。 System.Runtime.InteropServices名前空間で定義されているMarshalAsAttribute属性を使用して、引数のマーシャリング方法を明示的に制御できます。

以前のバージョンの Visual Basic では、パラメーター As Any宣言できました。つまり、任意のデータ型のデータを使用できます。 Visual Basic では、すべての Declare ステートメントに特定のデータ型を使用する必要があります。

Windows API 定数

一部の引数は定数の組み合わせです。 たとえば、このチュートリアルに示す MessageBox API では、メッセージ ボックスの表示方法を制御する Typ という整数引数を受け取ります。 WinUser.h ファイル内の #define ステートメントを調べることで、これらの定数の数値を確認できます。 通常、数値は 16 進数で表示されるため、電卓を使用して数値を追加し、10 進数に変換することができます。 たとえば、感嘆符スタイル MB_ICONEXCLAMATION 0x00000030の定数と Yes/No スタイル MB_YESNO 0x00000004を組み合わせる場合は、数値を追加して、0x00000034の結果 (10 進数 52) を取得できます。 10 進数の結果は直接使用できますが、アプリケーションでこれらの値を定数として宣言し、 Or 演算子を使用して組み合わせることをお勧めします。

Windows API 呼び出しの定数を宣言するには
  1. 呼び出す Windows 関数のドキュメントを参照してください。 使用する定数の名前と、これらの定数の数値を含む .h ファイルの名前を決定します。

  2. メモ帳などのテキスト エディターを使用して、ヘッダー (.h) ファイルの内容を表示し、使用している定数に関連付けられている値を見つけます。 たとえば、 MessageBox API は定数 MB_ICONQUESTION を使用して、メッセージ ボックスに疑問符を表示します。 MB_ICONQUESTIONの定義は WinUser.h にあり、次のように表示されます。

    #define MB_ICONQUESTION 0x00000020L

  3. クラスまたはモジュールに同等の Const ステートメントを追加して、これらの定数をアプリケーションで使用できるようにします。 例えば次が挙げられます。

    Const MB_ICONQUESTION As Integer = &H20
    Const MB_YESNO As Integer = &H4
    Const IDYES As Integer = 6
    Const IDNO As Integer = 7
    
DLL プロシージャを呼び出すには
  1. プロジェクトのスタートアップ フォームに Button1 という名前のボタンを追加し、それをダブルクリックしてコードを表示します。 ボタンのイベント ハンドラーが表示されます。

  2. 追加したボタンの Click イベント ハンドラーにコードを追加して、プロシージャを呼び出し、適切な引数を指定します。

    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
        RetVal = MBox(0, "Declare DLL Test", "Windows API MessageBox",
            MB_ICONQUESTION Or MB_YESNO)
    
        ' Check the return value.
        If RetVal = IDYES Then
            MsgBox("You chose Yes")
        Else
            MsgBox("You chose No")
        End If
    End Sub
    
  3. F5 キーを押してプロジェクトを実行します。 メッセージ ボックスは、[ はい ] と [ いいえ ] の両方の応答ボタンと共に表示されます。 いずれか 1 つをクリックします。

データ マーシャリング

Visual Basic は、Windows API 呼び出しのパラメーターと戻り値のデータ型を自動的に変換しますが、 MarshalAs 属性を使用して、API で予期されるアンマネージ データ型を明示的に指定できます。 相互運用マーシャリングの詳細については、「 相互運用マーシャリング」を参照してください。

API 呼び出しで Declare と MarshalAs を使用するには
  1. 呼び出す関数の名前と、その引数、データ型、戻り値を決定します。

  2. MarshalAs属性へのアクセスを簡略化するには、次の例のように、Imports ステートメントをクラスまたはモジュールのコードの先頭に追加します。

    Imports System.Runtime.InteropServices
    
  3. インポートした関数の関数プロトタイプを使用しているクラスまたはモジュールに追加し、パラメーターまたは戻り値に MarshalAs 属性を適用します。 次の例では、 void* 型を想定した API 呼び出しが AsAnyとしてマーシャリングされます。

    Declare Sub SetData Lib "..\LIB\UnmgdLib.dll" (
        ByVal x As Short,
        <MarshalAsAttribute(UnmanagedType.AsAny)>
            ByVal o As Object)
    

DllImport を使用した API 呼び出し

DllImport属性は、タイプ ライブラリなしで DLL 内の関数を呼び出す 2 番目の方法を提供します。 DllImport は、 Declare ステートメントの使用とほぼ同じですが、関数の呼び出し方法をより詳細に制御できます。

呼び出しが共有 (静的) メソッドを参照している限り、ほとんどの Windows API 呼び出しでDllImportを使用できます。 クラスのインスタンスを必要とするメソッドは使用できません。 Declareステートメントとは異なり、DllImport呼び出しではMarshalAs属性を使用できません。

DllImport 属性を使用して Windows API を呼び出すには

  1. [ファイル] メニューの [新規作成] をクリックし、[プロジェクト] をクリックして、新しい Windows アプリケーション プロジェクトを開きます。 [新しいプロジェクト] ダイアログ ボックスが表示されます。

  2. Visual Basic プロジェクト テンプレートの一覧から [Windows アプリケーション ] を選択します。 新しいプロジェクトが表示されます。

  3. Button2という名前のボタンをスタートアップ フォームに追加します。

  4. Button2をダブルクリックして、フォームのコード ビューを開きます。

  5. DllImportへのアクセスを簡略化するには、スタートアップ フォーム クラスのコードの先頭に Imports ステートメントを追加します。

    Imports System.Runtime.InteropServices
    
  6. フォームの End Class ステートメントの前に空の関数を宣言し、関数に MoveFile名前を付けます。

  7. PublicおよびShared修飾子を関数宣言に適用し、Windows API 関数が使用する引数に基づいてMoveFileのパラメーターを設定します。

    Public Shared Function MoveFile(
        ByVal src As String,
        ByVal dst As String) As Boolean
        ' Leave the body of the function empty.
    End Function
    

    関数には任意の有効なプロシージャ名を指定できます。 DllImport 属性は、DLL 内の名前を指定します。 また、パラメーターと戻り値の相互運用性マーシャリングも処理されるため、API が使用するデータ型に似た Visual Studio データ型を選択できます。

  8. DllImport属性を空の関数に適用します。 最初のパラメーターは、呼び出す関数を含む DLL の名前と場所です。 Windows システム ディレクトリにあるファイルのパスを指定する必要はありません。 2 番目のパラメーターは、Windows API の関数の名前を指定する名前付き引数です。 この例では、 DllImport 属性により、 MoveFile への呼び出しが強制的にKERNEL32.DLLの MoveFileW に転送されます。 MoveFileW メソッドは、パス srcからパス dstにファイルをコピーします。

    <DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True,
        CharSet:=CharSet.Unicode, ExactSpelling:=True,
        CallingConvention:=CallingConvention.StdCall)>
    Public Shared Function MoveFile(
        ByVal src As String,
        ByVal dst As String) As Boolean
        ' Leave the body of the function empty.
    End Function
    
  9. Button2_Click イベント ハンドラーにコードを追加して、関数を呼び出します。

    Private Sub Button2_Click(ByVal sender As System.Object,
        ByVal e As System.EventArgs) Handles Button2.Click
    
        Dim RetVal As Boolean = MoveFile("c:\tmp\Test.txt", "c:\Test.txt")
        If RetVal = True Then
            MsgBox("The file was moved successfully.")
        Else
            MsgBox("The file could not be moved.")
        End If
    End Sub
    
  10. Test.txt という名前のファイルを作成し、ハード ドライブの C:\Tmp ディレクトリに配置します。 必要に応じて Tmp ディレクトリを作成します。

  11. F5 キーを押してアプリケーションを起動します。 メイン フォームが表示されます。

  12. Button2 をクリックします。 ファイルを移動できる場合は、「ファイルは正常に移動されました」というメッセージが表示されます。

こちらも参照ください