チュートリアル : Windows API の呼び出し

更新 : 2007 年 11 月

Windows API は、Windows オペレーティング システムの一部であるダイナミック リンク ライブラリ (DLL: Dynamic Link Library) です。同等のプロシージャを独自に作成するのが困難なときに、Windows API を利用してタスクを実行します。たとえば、Windows には FlashWindowEx という名前の関数があります。この関数を使用すると、アプリケーションのタイトル バーを明るい網かけと暗い網かけに交互に変化させることができます。

コードで Windows API を使用する利点は、開発時間を短縮できることです。Windows API には、作成済みの、すぐに利用できる便利な関数が数多く用意されているため、開発時間を短縮できます。Windows API の短所としては、操作が難しい場合があることや、適切に動作しないときに修正できない場合があることが挙げられます。

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

過去において Windows API 呼び出しは Visual Basic プログラミングの重要な部分を占めていましたが、Visual Basic 2005 ではほとんど必要がなくなりました。Windows API 呼び出しを使用する代わりに、できる限り .NET Framework からマネージ コードを使用してタスクを実行する必要があります。このチュートリアルでは、Windows API を使用する必要のある状況についての情報を提供します。

172wfck9.alert_note(ja-jp,VS.90).gifメモ :

使用している設定またはエディションによっては、表示されるダイアログ ボックスやメニュー コマンドがヘルプに記載されている内容と異なる場合があります。設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。詳細については、「Visual Studio の設定」を参照してください。

Declare による API 呼び出し

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

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

  1. 呼び出しの対象となる関数の名前、引数、引数の型、戻り値、およびその関数を含む DLL の名前と場所を確認します。

    172wfck9.alert_note(ja-jp,VS.90).gifメモ :

    Windows API の詳細については、プラットフォーム SDK の「Windows API」で、Win32 SDK に関する記述を参照してください。Windows API で使用される定数の詳細については、プラットフォーム SDK に組み込まれている Windows.h などのヘッダー ファイルを参照してください。

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

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

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

    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 修飾子

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

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

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

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

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

引数とデータ型の宣言

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

172wfck9.alert_note(ja-jp,VS.90).gifメモ :

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 キーを押してプロジェクトを実行します。[はい] 応答ボタンと [いいえ] 応答ボタンのあるメッセージ ボックスが表示されます。いずれかのボタンをクリックします。

データのマーシャリング

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 属性では、もう 1 つの方法でタイプ ライブラリを持たない DLL 内の関数を呼び出すことができます。DllImport は、Declare ステートメントを使用する場合とほぼ同じ働きをしますが、関数の呼び出し方をより細かく制御できます。

呼び出しが共有 (static と呼ばれる場合もあります) メソッドを参照している限り、ほとんどの 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] をクリックします。ファイルを移動できる場合は、"The file was moved successfully" というメッセージが表示されます。

参照

概念

マネージ コードでのプロトタイプの作成

Callback のサンプル

参照

Declare ステートメント

DllImportAttribute

MarshalAsAttribute

Auto

Alias

Lib

その他の技術情報

COM 相互運用