settimer() killtimer() WindowsAPIである時間にWindowsがVBAの関数(TimerProc)を呼び出す

ExcelのVBAでもWordのVBAでもできます。

以下を標準モジュールに書く。

Option Explicit

#If VBA7 And Win64 Then
'64bit版
   Private Declare PtrSafe Function SetTimer Lib "user32" _
   (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As LongPtr
#Else
 '32bit版
  Private Declare Function SetTimer Lib "user32" _
  (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
#End If
#If VBA7 And Win64 Then
 '64bit版
  Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
 '32bit版
  Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
#End If

'Windowsが呼び出す関数。引数や戻り値は決まっている。TimerProcで検索すると見つかる
Public Sub TimerProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal TimerID As Long, ByVal TickCount As Long)
  Debug.Print hwnd, Msg, TimerID, TickCount
  KillTimer 0, TimerID 'タイマーを止める。Windowsに教える。
'ここにやりたことを書く
End Sub

Sub main()
  SetTimer 0, 0, 1000 * 2, AddressOf TimerProc '1000で1秒。2秒後にTimeProcを呼び出す
End Sub

二秒後にイミディエイトウィンドウに出力する。イミディエイトは下の方の図の下の方。

もし、二秒にしたいならTimeProc関数のKillTimerの行をコメントアウトか削除する。

1列目はウィンドウハンドル、2列目は275はWM_TIMER = &H113 のこと。3列目は、タイマーID。4列目はWindowsの起動からの経過時間(ミリ秒単位)

これやって何がうれしいのかというと、一定時間後に実行する関数が作れる。
呼び出しを実行するのはWindowsのOS。だからVBAのリソースは使わない。Excelのプロセスとは違う。WordとExcelが動いていて、Wordが固まってもExcelまで影響を受けないのと同じ。ただし、WordとExcel間で通信?していると少し違うが、基本的にWordを閉じたらExcelは普通に使える。これはWindowsOSとExcel間でも同じです。ただ、WordとExcelは同等のアプリですが、WindowsとExcelはWindows管理下にある。このイメージ、メモリ空間かな。常にWindowsは動いている。「windows メモり 空間  64」で検索するといろいろ図が見えるが、仮想のメモリ状態、物理的/実際のメモりアドレスはありません。仮想のメモリ上は常にOS(Windows)が常駐してアプリが切り替わる。

で、

一定時間後に実行する関数は、TimerProc関数。
TimerProcの関数名はaaa関数でも何でもいいが、戻り値や引数の数、型は決まっている。

だって、

Windowsが呼び出すのでその決まり引数の数や型、順番も、あとは戻り値の型に従う。WindowsがExcelのプロセスの関数を呼び出す。
TimerProcの関数名をSettimerの第四引数に指定。
関数名を渡すのではなく、関数があるアドレスを渡すためAddressOf演算子を使う(メモリ上のアドレス/番地を渡すので関数名は関係ない。だからaaa関数でもいい)。

ExcelWordのApplication.OnTimeと同等のことができる。こっちは時間の間隔では無く実行する時間を指定する。5秒後にするには「今の時間+5分」。VBAのコードならNow() + TimeValue(“0:0:5”)。

(Visited 1,815 times, 1 visits today)

「settimer() killtimer() WindowsAPIである時間にWindowsがVBAの関数(TimerProc)を呼び出す」への2件のフィードバック

  1. Excel VBA でようやく繰り返しタイマーが実現出来ました。
    ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です