Win32APIの書き方を調べるには
Win32APIを使うにはDeclareステートメントで対象の関数を定義する必要があります。
じゃあ、Declareステートメントで何を書けばいいのか、という話になります。初心者の方には「上級者は全部それを覚えてて書いてるんだろうけど、そんなの無理・・・」とか思ってる方がいらっしゃいますが、どんな上級者でもWin32APIの定義を覚えている人なんかいません。
じゃあどうやってWin32APIの定義が分かるのかというと、それが書いてあるファイルがMicrosoftから提供されていてそれを見てます。Win32API自体はC言語のため、ヘルプに書いてあるC言語の定義からVBAに合わせて型変換をして、、、なんてことをやる人もいるでしょうけど、少なくとも私は面倒なのでしません。
過去にはWin32APIのDeclare宣言が書かれているWin32API.txtというファイルがMicrosoft Office 2000 DeveloperやMicrosoft Visual Basicに含まれていましたが、2018/9/24現在はWin32API_PtrSafe.TXTというファイルを含んだexeファイルを以下のサイトからダウンロードできます。
取得手順は以下になります。なお、手順が面倒なので同じファイルを直接ダウンロードできるように当サイトにも置いてますので、てっとり速く欲しい方はこれでもいいです。
ダウンロード「Win32API_PtrSafe.TXT(676KB)」
Microsoftからダウンロードしたい方は以下をどうぞ。
- 「https://www.microsoft.com/en-us/download/details.aspx?id=9970」を開きます。
- 赤い「Download」のリンクをクリックすると、Office2010Win32API_PtrSafe.exeがダウンロードされます。
- Office2010Win32API_PtrSafe.exeを実行すると以下のダイアログが表示されるため、それぞれ、はい、Yes、OK、を押します。
- 最後のOKを押すと「C:\Office 2010 Developer Resources\Documents\」に解凍されます。
VBAのバージョンとWin32API_PtrSafe.TXTの使い方
Win32APIを使いたい場合は、Win32API_PtrSafe.TXTの内容から必要な部分をVBAのモジュールに転記(コピペ)すれば使えるようになります。ただ、VBAにはバージョンがあり、Office 2007まではVBA6で32bit版、Office 2010からがVBA7で32bit版と64bit版になっています。
VBAのバージョンはVBA画面のヘルプメニューのバージョン情報で確認できます。
Win32API_PtrSafe.TXTの内容はVBAのバージョンが7.0からの記述になっています。もしVBA6で動かしたい場合はWin32API_PtrSafe.TXTのDeclare宣言の「LongPtr」を「Long」に書き換える必要があります。
1 2 3 4 |
'// VBA 7 Declare PtrSafe Function GetKeyboardLayout Lib "user32" Alias "GetKeyboardLayout" (ByVal dwLayout As Long) As LongPtr '// VBA 6 Declare PtrSafe Function GetKeyboardLayout Lib "user32" Alias "GetKeyboardLayout" (ByVal dwLayout As Long) As Long |
なお、PtrSafeは削除しなくても32bit版で動きます。
LongPtr型は32bit版の場合はLong型(-2,147,483,648 から 2,147,483,647)となり、64bit版の場合はLongLong型(-9,223,372,036,854,775,808 から 9,223,372,036,854,775,807)として扱われます。
Win32APIの定義一式のダウンロード
Microsoftのヘルプは度々URLが変わります。上記のURLも変わるかもしれません。
その度に探すのがわずらわしいので、当サイトからもダウンロードできるようにしています。上にあるものと同じです。
ダウンロード「Win32API_PtrSafe.TXT(676KB)」
もともとはそのままtxt内容を転記していましたがサイズが大きすぎてブラウザで読み込めない場合があったのでダウンロードに変えてます。
関数と構造体
Win32APIには関数の引数や戻り値に独自の構造体を利用していることがよくあります。
例えば、現在日時を取得するGetLocalTime()というWin32APIの関数がありますが、引数にSYSTEMTIME構造体型に現在日時をセットして返します。
このような場合、Declare宣言で関数だけを宣言するのではなく、使っている構造体も一緒にVBAにコードとして書いてあげる必要があります。具体的にはこのようになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
Type SYSTEMTIME wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As Integer End Type Declare PtrSafe Sub GetLocalTime Lib "kernel32" Alias "GetLocalTime" (lpSystemTime As SYSTEMTIME) |
なお、構造体の定義は関数の定義より上に書く方が一般的です。なのでSYSTEMTIME構造体はGetLocalTimeより上に書いてます。
あとは実際にVBAでGetLocalTime()を使うときですが、普通の関数と同じように書きます。引数にはSYSTEMTIME構造体型の変数を用意して渡します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Sub GetLocalTimeTest() Dim t As SYSTEMTIME Dim s '// 現在日時取得 Call GetLocalTime(t) '// yyyy/mm/dd hh:mm:ss.fffに整形 s = Format(t.wYear, "0000") s = s & "/" s = s & Format(t.wMonth, "00") s = s & "/" s = s & Format(t.wDay, "00") s = s & " " s = s & Format(t.wHour, "00") s = s & ":" s = s & Format(t.wMinute, "00") s = s & ":" s = s & Format(t.wSecond, "00") s = s & "." s = s & Format(t.wMilliseconds, "000") Debug.Print s End Sub |
実行結果
2018/09/24 00:06:15.138
見ての通りですが、VBA関数とWin32APIの関数の違いは、Declare宣言をするかしないかの違いだけで、あとは大体同じです。
ここではGetLocalTimeを見本にしましたが、他にも多数の関数が用意されており、場合によっては構造体だけでなくConst定義されている定数も一緒にVBAに転記する必要があります。関数ごとに何が必要なのかは異なりますので、まず関数の定義を見て、そこに構造体の定義があればそれを追加し、戻り値や構造体の定義に定数が使われていればそれも転記する、という作業が必要になります。