WindowsAPIの関数をラップするクラスを作ったらメッチャ便利だった
タイトル通り。
そもそもは、
コチラの『VBA Developer's Handbook』で紹介されていたテクニックで、ちょっとやってみたら便利だったというだけの話。
ちなみに、コチラの書籍は、VBA四天王の一人、id:t-hom さんも
紹介しておられる。
WindowsAPIの関数をクラスに封印する
クラスモジュールを挿入して、テキトーな名前をつける。
私は「WindowsAPI」という何のひねりもないそのままやんけなネーミングにしている。
WindowsAPIの関数をラップしたいだけ、すなわちプロパティやフィールドを持つ必要がないので、Attribute VB_PredeclaredIdの値をTrueにしておく。
「Attribute VB_PredeclaredId」については、
コチラをどうぞ。
たとえば
最近、IE操作関係でWindowsAPI関数を使うことが多いので、手始めにGetTickCountとSleepをクラスモジュールに封印してみる。
リスト1 クラスモジュール
オブジェクト名は「WindowsAPI」、「Attribute VB_PredeclaredId」の値はTrue。
Option Explicit
'(1)WindowsAPI関数の宣言'
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'(2)GetTickCount関数呼び出しメソッド'
Public Function callGetTickCount() As Long
callGetTickCount = GetTickCount
End Function
'(3)Sleep関数呼び出しメソッド'
Public Sub callSleep(ByVal milliSeconds As Long)
Call Sleep(milliSeconds)
End Sub
'(4)GetTickCountとSleepを組み合わせた待機用メソッド'
Public Sub waitFor(ByVal milliSeconds As Long)
Dim startTime As Long
startTime = GetTickCount
Dim endTime As Long
Do
Sleep (1)
DoEvents
endTime = GetTickCount
Loop Until endTime - startTime > milliSeconds
End Sub
それぞれコード中の(1)~(4)に記した通り。
(1)の
Private Declare Function GetTickCount Lib "kernel32" () As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
はおなじみのアレ。
ただし、いづれもPrivate指定にして、直接外から呼び出すことができないようにクラス内に封印している。
そして、(2)、(3)は、GetTickCount、Sleepを呼び出すためのメソッド。
あと、(4)は、コメント通りGetTickCountとSleepを組み合わせて、引数で渡した時間だけ待機するメソッド。
単純にDo~Whileでループさせるだけでなく、ループ中にSleepをかましているところがミソ。
こんなふうに複数のWindowsAPIを組み合わせた処理を簡単に利用できるようにすることができる。
使ってみる
次のコードで実行してみる。
リスト2 標準モジュール
Public Sub disposableMacro01()
Dim n As Long
n = 1
Do
Call WindowsAPI.waitFor(1000) '……(1)'
Debug.Print "待機 " & n & " 回目"
Debug.Print "ち~んw"
n = n + 1
Loop Until n > 10
Call WindowsAPI.waitFor(2000)
Debug.Print "おしまい"
End Sub
上にも書いたように、WindowsAPIクラスは、「Attribute VB_PredeclaredId」の値をTrueにしているので、インスタンス化せずに、(1)のように
Call WindowsAPI.waitFor(1000)
と書けばメソッドの利用ができる。
ここでは、GetTickCountとSleepを組み合わせた自作のwaitForメソッドを使っている。
Doループの中でこのメソッドを呼び出すことにより、1000ミリ秒(メソッド内でSleepを引数1で実行しているので、正確には1001ミリ秒+α)ごとにイミディエイト・ウインドウに、文字列を出力し、ループを抜けたところで再度しばらく時間をおいて文字列を出力することになる。

こんな感じ。
おわりに
めんどくさいWindowsAPI関数の利用が、非常に簡単になると思った。
