SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Windowsアプリケーションで「処理中」を表現する

時間のかかる処理で「処理中」を表現する(前編)

Windowsアプリケーションで処理中を表現する様々な方法

  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード WaitSample.zip (46.5 KB)

処理してほしくないメッセージまで処理されてしまう

 ビジーループV2動作中に、いろいろなウィンドウ操作を試してみたでしょうか? では、ビジーループV2の動作中にウィンドウを閉じてみてください。閉じた後どうなるかを目視できるよう、タスクマネージャでWaitSample.exeの実行状況も監視してください。時間が経つとCPUの利用率が0になり、処理が終了します。しかし、プログラムは終了しません。これはどういうことなのでしょうか。

 プログラムが終了しないということは、WinMainにあるメッセージループから抜け出せない状態であることを意味します。メッセージループから抜け出す条件はなんでしょうか。メッセージループは、次のようになっています。

メインメッセージループ(抜粋)
// メイン メッセージ ループ:
while (GetMessage(&msg, NULL, 0, 0))
{
  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

 GetMessageがFALSEを返すまでひたすらループするということがここから分かります。リファレンスによると、GetMessageは、WM_QUITメッセージを取得すると0を返すとあります。要するにWM_QUITがメインメッセージループで取得されないされない限り、プログラムが終了しないということになります。

 サンプルアプリは、ウィンドウが破棄されるタイミング(WM_DESTORYを受け取ったタイミング)で、WM_QUITメッセージを発行します。ビジーループV2動作中にウィンドウを閉じてしまうため、WM_QUITがメインメッセージループではない場所で処理されてしまい、結果的にWM_QUITメッセージを検出することができず、プログラムが終了できなくなってしまったようです。

ウィンドウを閉じさせないためには?

 ビジーループ中にウィンドウの操作ができるのは嬉しい副作用ですが、ウィンドウが閉じられてしまうのは不本意です。対応策はいくつか考えられますが、実務の場合、時間のかかる処理中だからと言って、アプリを終わるタイミングで、ということはあまり考えられません。むしろウィンドウを閉じられる必要がないほうが多いのではないでしょうか。

 では、ウィンドウを閉じることができないようにするにはどうすればいいのでしょうか。ウィンドウを閉じることができないようにするということは、ウィンドウを操作できないようにするということと同じ意味を持ちます。最初のBusyLoopは意図していないとはいえ、一切操作ができていませんでした。それと同じような状況を擬似的にでも実現できれば、問題は解決できそうです。ウィンドウを操作できないようにするには、EnableWindow APIを利用してウィンドウの有効・無効を切り替えることで実現できます。プログラム的にはいたって単純で、ループの最初でEnableWindow( hwnd, FALSE );を呼び、ループから抜けたところでEnableWindow( hwnd, TRUE );を呼び出すだけです。さっそくコードを見て試してみましょう(体験メニュービジーループV3)。

ビジーループV3
void BusyLoop3( HWND hwnd, DWORD dwTime )
{
  if( hwnd != NULL ){
    EnableWindow( hwnd, FALSE );
  }
  while( dwTime > 0 ){
    PumpMessage();
    // メッセージを処理してから待機カーソルにする
    DWORD	dwWait = ( dwTime > 1000 ) ? 1000 : dwTime ;
    CSimpleWaitCursor	waitCursor;
    DWORD dwStart = GetTickCount();
    while( (GetTickCount()-dwStart) < dwWait );
    dwTime -= dwWait;
  }
  if( hwnd != NULL ){
    EnableWindow( hwnd, TRUE );
  }
}

 いかがでしょうか。一見するとあまり問題は感じないかもしれません。ユーザーからみても、何やら作業を行っているということが認識できる状況になっています。しかし、まずメイン画面が無効状態であるにもかかわらず、ダイアログも何も出ていないのは何だか妙な感じです。まるでXPまでの頃の、応答なしになり始めた状態のような感じで、得体のしれない不安感がぬぐえません。数秒程度ならこれでもいいかもしれませんが、あまりお勧めできる状況とは言えないようです。

次のページ
作業中というメッセージを表示する

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Windowsアプリケーションで「処理中」を表現する連載記事一覧
この記事の著者

とっちゃん(トッチャン)

Microsoft MVP for Development Tools Visual C++Windows Installer 系を中心にオンライン/オフラインで活動しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5332 2010/07/30 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング