一時停止中のウィンドウ再描画 <TOP>
CreateWaitableTimer 「待機可能」タイマオブジェクトを作成
OpenWaitableTimer 既存の名前付き「待機可能」タイマオブジェクトのハンドルを取得
SetWaitableTimer 指定した「待機可能」タイマをアクティブにする
CancelWaitableTimer 指定した「待機可能」タイマをアクティブでない状態に設定
CloseHandle オープンされているオブジェクトハンドルをクローズ
MsgWaitForMultipleObjects シグナル状態になったとき、またはタイムアウト時間が経過したとき制御を戻す
Sleep カレントスレッドの実行を指定の時間だけ中断
例では、どちらも約10秒間一時停止させています。
「Sleep」で一時停止中に他のウィンドウが被った場合は再描画されません。「SetWaitableTimer」で一時停止中は再描画されます。
参照
http://support.microsoft.com/kb/231298/ja
Visual BasicでSetWaitableTimerを使用する方法
'================================================================ '= 一時停止中のウィンドウ再描画
'= (SetWaitableTimer.bas) '================================================================ #include "Windows.bi" Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type #define WAIT_ABANDONED &H80 'オブジェクトがmutexの場合だけ #define WAIT_ABANDONED_0 &H80 'オブジェクトがシグナル状態 #define WAIT_FAILED -1 'エラーが発生したことを示す #define WAIT_IO_COMPLETION &HC0 'I/O完了コールバック関数の呼び出しによって戻った #define WAIT_OBJECT_0 &H0 'オブジェクトがシグナル状態になったことを示す #define WAIT_OBJECT_1 1 ' #define WAIT_TIMEOUT &H102 'タイムアウト時間が経過したことを示す #define INFINITE &HFFFF '無限に中断 #define ERROR_ALREADY_EXISTS 183 '既に存在している #define QS_HOTKEY &H80 'WM_HOTKEY #define QS_KEY &H1 'WM_KEYUP・WM_KEYDOWN・WM_SYSKEYUP・WM_SYSKEYDOWN #define QS_MOUSEBUTTON &H4 'WM_LBUTTONUP・WM_RBUTTONDOWN #define QS_MOUSEMOVE &H2 'WM_MOUSEMOVE #define QS_PAINT &H20 'WM_PAINT #define QS_POSTMESSAGE &H8 'キューに何らかのメッセージが入った #define QS_SENDMESSAGE &H40 '他のスレッドから送られたメッセージがある #define QS_TIMER &H10 'WM_TIMER #define QS_MOUSE (&H2 Or &H4) '(QS_MOUSEMOVE Or QS_MOUSEBUTTON) #define QS_INPUT (&H2 Or &H4 Or &H1) '(QS_MOUSE Or QS_KEY) #define QS_ALLEVENTS (&H2 Or &H4 Or &H1 Or &H8 Or &H10 Or &H20 Or &H80) '(QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY) #define QS_ALLINPUT (&H40 Or &H20 Or &H10 Or &H8 Or &H4 Or &H2 Or &H80 Or &H1) '(QS_SENDMESSAGE Or QS_PAINT Or QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON Or QS_MOUSEMOVE Or QS_HOTKEY Or QS_KEY) ' 「待機可能」タイマオブジェクトを作成 Declare Function Api_CreateWaitableTimer& Lib "kernel32" Alias "CreateWaitableTimerA" (ByVal lpSemaphoreAttributes&, ByVal bManualReset&, ByVal lpName$) ' 既存の名前付き「待機可能」タイマオブジェクトのハンドルを取得 Declare Function Api_OpenWaitableTimer& Lib "kernel32" Alias "OpenWaitableTimerA" (ByVal dwDesiredAccess&, ByVal bInheritHandle&, ByVal lpName$) ' 指定した「待機可能」タイマをアクティブにする Declare Function Api_SetWaitableTimer& Lib "kernel32" Alias "SetWaitableTimer" (ByVal hTimer&, lpDueTime As FILETIME, ByVal lPeriod&, ByVal pfnCompletionRoutine&, ByVal lpArgToCompletionRoutine&, ByVal fResume&) ' 指定した「待機可能」タイマをアクティブでない状態に設定 Declare Function Api_CancelWaitableTimer& Lib "kernel32" Alias "CancelWaitableTimer" (ByVal hTimer&) ' オープンされているオブジェクトハンドルをクローズ Declare Function Api_CloseHandle& Lib "Kernel32" Alias "CloseHandle" (ByVal hObject&) ' 指定したオブジェクトのいずれか1つまたはすべてがシグナル状態になったとき、またはタイムアウト時間が経過したとき制御を戻す Declare Function Api_MsgWaitForMultipleObjects& Lib "user32" Alias "MsgWaitForMultipleObjects" (ByVal nCount&, pHandles&, ByVal fWaitAll&, ByVal dwMilliseconds&, ByVal dwWakeMask&) ' カレントスレッドの実行を指定の時間だけ中断 Declare Sub Api_Sleep Lib "Kernel32" Alias "Sleep" (ByVal dwMilliseconds&) Var Shared Button1 As Object Var Shared Button2 As Object Button1.Attach GetDlgItem("Button1") : Button1.SetFontSize 14 Button2.Attach GetDlgItem("Button2") : Button2.SetFontSize 14 '================================================================ '= '================================================================ Declare Sub sWait(lNumberOfSeconds As Long) Sub sWait(lNumberOfSeconds As Long) Var ft As FILETIME Var Busy As Long Var Delay As Double Var DelayLow As Double Var Units As Double Var hTimer As Long Var Ret As Long hTimer = Api_CreateWaitableTimer(0, True, "TestTimer") ft.dwLowDateTime = -1 ft.dwHighDateTime = -1 '「待機可能」タイマをアクティブ Ret = Api_SetWaitableTimer(hTimer, ft, 0, 0, 0, 0) 'ユニットをナノ秒に変換 Units = CDbl(&H10000) * CDbl(&H10000) Delay = CDbl(lNumberOfSeconds) * 1000 * 10000 ft.dwHighDateTime = -CLng(Delay / Units) - 1 DelayLow = -Units * (Delay / Units - Fix(Delay / Units)) If DelayLow < CDbl(-2147483648) Then DelayLow = Units + DelayLow ft.dwHighDateTime = ft.dwHighDateTime + 1 End If ft.dwLowDateTime = CLng(DelayLow) '「待機可能」タイマをアクティブ Ret = Api_SetWaitableTimer(hTimer, ft, 0, 0, 0, False) Do Busy = Api_MsgWaitForMultipleObjects(1, hTimer, False, INFINITE, QS_ALLINPUT) CallEvent Loop Until Busy = WAIT_OBJECT_0 Ret = Api_CloseHandle(hTimer) End Sub '================================================================ '= SetWaitableTimerを使用した一時停止 '================================================================ Declare Sub Button1_on edecl () Sub Button1_on() Var Ret As Long Button1.EnableWindow 0 sWait 10 Button1.EnableWindow -1 End Sub '================================================================ '= Sleepを使用した一時停止 '================================================================ Declare Sub Button2_on edecl () Sub Button2_on() Var Ret As Long Button2.EnableWindow 0 Api_Sleep 10000 Button2.EnableWindow -1 End Sub '================================================================ '= '================================================================ While 1 WaitEvent Wend Stop End