Declare ステートメントの構造

Microsoft Office 2000/Visual Basic プログラマーズ ガイド   

次に、GetTempPath 関数の Declare ステートメントの例を示します。このステートメントは、Windows の一時フォルダへのパス (既定では C:\Windows\Temp) を返します。

Private Declare Function GetTempPath Lib "kernel32" _
         Alias "GetTempPathA" (ByVal nBufferLength As Long, _
         ByVal lpBuffer As String) As Long

Declare キーワードは、プロジェクトに DLL 関数の定義を含めることを VBA に対して警告します。標準モジュールの Declare ステートメントは、API 関数を単一モジュールでのみ使用するかプロジェクト全体で使用するかにより、パブリックまたはプライベートに設定します。クラス モジュールでは、Declare ステートメントはプライベートに設定する必要があります。

Function キーワードの後の関数名は、VBA から関数を呼び出す際に使用します。この名前は、API 関数名と同一にするか、Declare ステートメント内の Alias キーワードを使用して、VBA では異なる名前 ("エイリアス") で関数を呼び出すことを示します。

上記の例で、DLL の API 関数の名前は GetTempPathA であり、VBA からの呼び出しに使用する名前は GetTempPath です。DLL 関数の実際の名前は、Alias キーワードの後ろに表示されます。また、GetTempPath は、Win32API.txt ファイルが関数にエイリアスを指定する際に使用される名前であり、任意の名前に変更することが可能です。

Declare ステートメント内でエイリアスを使用する理由は以下のとおりです。

  • アンダースコア (_) で始まる API 関数名は VBA では使用できません。この関数を VBA から呼び出すには、エイリアス名を使用する必要があります。

  • エイリアスを使用すると DLL 関数に任意の名前を付けることができるため、VBA における独自の規則に従って関数名を作成することが可能になります。

  • API 関数では大文字と小文字が区別されますが VBA 関数では区別されないため、エイリアスを使用して関数名の大文字と小文字を変更することができます。

  • DLL 関数によっては、異なるデータ型を取得する引数を含む場合があります。このような関数の VBA Declare ステートメントは、引数のデータ型を Any と定義します。ただし、Any と宣言された引数で DLL 関数を呼び出すと、VBA ではデータ型の確認が行われないため危険性が伴います。引数を Any として渡さないようにするには、単一の DLL 関数の複数のバージョンを宣言し、各バージョンに異なる名前と異なるデータ型を指定します。

  • Windows API には、文字列の引数を取得するすべての関数について、ANSI と Unicode の 2 種類のバージョンがあります。ANSI バージョンのサフィックスは上記の例に表示されているとおり "A" ですが、Unicode バージョンのサフィックスは "W" です。VBA の内部処理では Unicode が使用されますが、DLL の関数を呼び出す前に、Unicode の文字列はすべて ANSI に変換されます。つまり、VBA から Windows API 関数を呼び出すときは、通常は ANSI 型を使用することになります。API ビューア アドインでは、文字列の引数を取得するすべての関数に対してエイリアスが自動的に作成されるので、サフィックスに "A" を追加せずに関数を呼び出すことができます。

Lib キーワードは、関数が含まれる DLL を指定します。DLL 名は、Declare ステートメント内の文字列に含まれます。Lib キーワードの後ろに指定されている DLL がシステムにない場合、関数を呼び出すと、実行時エラー番号 48 の "DLL 読み込み時のエラーです。" というエラー メッセージが表示されます。このエラーは VBA コードで処理できるため、安全なコードを記述してエラーに対処することが可能です。

メモ   基本的な Windows DLL はアプリケーションのロードに必要なため、これらの関数を呼び出す場合にこの問題は発生しません。

次の表には、Windows API に含まれ、頻繁に使用される DLL が示されています。

DLL 内容
Kernel32.dll メモリ管理およびリソース処理に使用する低レベル オペレーティング システム関数
User32.dll メッセージ処理、タイマー、メニュー、および通信に使用する Windows 管理関数
GDI32.dll 描画、画面コンテキスト、およびフォント管理などのデバイス出力に使用する関数が含まれる Graphics Device Interface (GDI) ライブラリ

Windows API の DLL など、ほとんどの DLL は C/C++ 言語で記述されています。C/C++ 関数で使用される引数とデータ型は、VBA 関数で使用されるものとは異なる点があるため、引数を DLL 関数に渡す際には、C/C++ 関数で使用される引数とデータ型について開発者が理解している必要があります。引数を渡す方法については、次の「DLL 関数を呼び出す」を参照してください。

また、多くの引数は値によって DLL 関数に渡されます。既定では、VBA の引数は参照によって渡されるため、DLL 関数に引数を値で渡す必要がある場合は、関数の定義に ByVal キーワードを含める必要があります。関数の定義から ByVal キーワードを削除すると、アプリケーションで無効なページ エラーが発生するか、VBA 実行時エラー番号 49 の "DLL が正しく呼び出せません。" というエラー メッセージが表示されます。

参照で引数を渡すと、その引数のメモリ位置が、呼び出されているプロシージャに渡されます。プロシージャがその引数値を変更するとそのコピーのみが変更されるので、呼び出しプロシージャが実行される際は、引数には変更された値が含まれます。

一方、値で引数を DLL 関数に渡す場合は引数のコピーが渡され、このコピーを使用して関数が動作します。したがって、実際の引数に含まれる値が関数によって変更されることはありません。呼び出し元のプロシージャが実行されるとき、引数には、別のプロシージャが呼び出された以前と同じ値が含まれます。

参照で引数を渡すとメモリ内での引数の修正が可能になるため、誤った引数を参照で渡した場合、DLL 関数によって不適切にメモリが上書きされ、エラーが発生したり、予期せぬ動作が起こる場合があります。Windows は、上書きされるべきではない値を多数管理しています。たとえば、Windows では、"ハンドル" と呼ばれる 32 ビットの固有の識別子が各ウィンドウに割り当てられています。Windows ではウィンドウのハンドルが変更されるとそのウィンドウを管理できなくなるため、ハンドルは必ず値で API 関数に渡されます。

メモ   ByVal キーワードは、文字列型 (String) の引数の前に表示されますが、文字列は必ず参照で Windows API 関数に渡されます。文字列を渡す際の詳細については、この章の「DLL 関数から文字列を返す」を参照してください。

引数を値または参照で渡す際の詳細については、第 7 章「引数を値または参照により渡す」、および「Visual Basic for Applications を最大限に活用する」を参照してください。

表示: