他アプリが応答可能になるのを待つ(95/98 only)

時間のかかる処理を行っっているときに押されたキーイベントを破棄しているアプリケーションをよく見かけます。そうすることで「おかしいな、何も起きないぞ」と何度も押されたキー入力を無効にしているのです。

しかし、そのような処理を行っているアプリに対してkeybd_eventでキーボードイベントを発射して操作しようとすると、そのキーイベント中に時間のかかる処理が始まると思うように操作できなくなってしまいます。

そうならないようにするためには、キーイベントを受け付けてくれるようになるまで待つしかありません。それではどういう状態になればキーイベントを受け付けてくれるのでしょうか?

キーイベントはメッセージキューにつまれて処理されますから、PostMessage等でキューにつまれたメッセージが処理されるようならばキーイベント等も処理するだけの余裕があると考えて良いでしょう。

また、他スレッドからのSendMessageは一旦メッセージキューにつまれ、そのメッセージキューが処理されてから戻ってくる、というWindows95/98の仕様が有ります(情報源は忘れました^^;)。
という訳でこのTIPSは95/98用です。NT用のいい方法があれば教えてください。

上記二つの条件からSendMessageをそのウィンドウに対して行い、戻ってくればキーイベントを処理できる状態であると考えられます。送るメッセージは何でもよいので、この場合何もしないメッセージであるWM_NULLがいいでしょう。

void WaitInputIdle(HWND hWnd)
{
// キーボードイベントに対して応答可能になるまで待つ
::SendMessage(hTarget, WM_NULL, 0, 0);
}

ただし、これではアプリケーションがなかなか終らない、もしくはハングアップしてしまっている場合にこちらのアプリまでハングアップしてしまいます。そこでSendMessageCallbackを使うことにより、待ち時間にも他の処理を行えるようにしておいた方がいいでしょう。

void CALLBACK SAP_WaitInputIdle(HWND hWnd, UINT uMsg, DWORD dwData, LRESULT lResult)
{
// フラグをリセットする
*((LPBOOL)dwData) = FALSE;
}
void WaitInputIdle(HWND hWnd)
{
BOOL bContinue = TRUE;
SendMessageCallback(hWnd, WM_NULL, 0, 0, SAP_WaitInputIdle, (DWORD) &bContinue);
MSG msg;
while (bContinue){
// PeekMessageを呼ばないとSAP_WaitInputIdleも呼ばれない
PostMessage(NULL, WM_USER, 0, 0);
PeekMessage(&msg, (HWND) -1, WM_USER, WM_USER, PM_REMOVE);
}
}

戻る