ダイアログの表示、非表示に行う処理(少し時間のかかる)について

解決


マサダ  2009-06-17 19:43:59  No: 70344

MFCでダイアログアプリを作成しています。
ダイアログ内に子ダイアログを複数作成して
子ダイアログの表示を切り替え、画面の変更を行っています。

子ダイアログの表示(ShowWindow(SW_SHOW))時に、
ログデータを読み込み、それを表示する処理を行いたいと思います(一例)
ログのデータサイズが膨大のことを考え、今まではワーカースレッドで読み込み作業を行っていました。

これを、もう少し簡単に改良できないかと思い。
ダイアログ表示時のOnShowWindow()内でログを読み込み、
他のメッセージ処理を行いながら、ログの表示処理を行えないかと以下のイメージ(大まかな)で記述しました。

この場合、CDialog::OnShowWindow(bShow, nStatus) では、画面の表記が終わっていないのか、
CHogeDlg::OnShowWindow()が終わるまで、画面には何も表示されませんでした。

この処理(ログ読み込み)を行う適切な場所、OnShowWindow()の直後(画面表示後)に呼ばれるイベントハンドラなどがありましたら
教えていただけないでしょうか?
長文で失礼しました。

void CHogeDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
  CDialog::OnShowWindow(bShow, nStatus);

  //表示
  if( bShow ) {
    for(・・・・) {

      //ここに時間がかかる処理を分割して記述

      //その他メッセージ処理
      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
      {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
      }
    }
  }

  //その他処理
}


aetos  2009-06-17 19:54:42  No: 70345

データ量が膨大でも、一度に表示する量はわずかであれば、最初に表示する分だけ読み込んで、残りは表示する都度読み込むという方法が考えられます。


マサダ  2009-06-17 20:17:35  No: 70346

>>aetos
返信ありがとうございます。
表示量は可変で、どれぐらいの量になるのか使用者次第です。
今までは別スレッドで、読み込み。
そのパラメータを正確にはリストボックスに1行ずつ表示していました。

これを、スレッドを使わずに行う方法を探していたところPeekMessage()を使えばうまくできそうだったので、実行してみたのですが、上記の通りです。
もちろん、OnShowWindow()内部で読み込んだ場合は、ログ量が多ければ読み込み、表記が終わるまで、画面ははフリーズします。。

子ダイアログの切り替え時に毎回ファイルを読み込む必要があるので、いい方法が無いかと改善方法を探していたところです。


aetos  2009-06-17 22:33:39  No: 70347

うまく伝わらなかったでしょうか?

たとえばログであれば、数十万行、あるいはそれ以上あろうとも、画面の高さの制限がありますから、全てを一度に表示できるわけではありません。
ですから、スクロールせずに一度に表示可能な量だけ読み込み、残りはスクロールして表示するときに読み込むようにすればよいのではないか?  ということです。

いろいろと課題はあります。
エディットボックスやリストボックスでは、実際のデータはないのに、スクロールバーだけは、データがたくさんあるように見せかけるのは難しいかもしれません。
また、スクロールした時にどう表示するかも考えないといけません。
スクロールするたびに読み込むのではパフォーマンスが問題になるなら、上下1ページ分は先読みしてキャッシュしておくような工夫もいるかもしれません。

もし行ベースのデータであれば、仮想リストビューを使ってみてはいかがでしょうか。
上記のような諸問題の多くを OS が吸収してくれます。
やってみれば、どういうものか感覚的につかめるのではないでしょうか。


gak  2009-06-18 02:18:19  No: 70348

> スレッドを使わずに行う方法を探していたところPeekMessage()を使えばうまくできそう
これは『店員2人体制で廻してきた喫茶店を、これからは店員1人体制で廻す』ってのと同じ事をやろうとしている。
今までは接客(UI)、調理(データ読込)と分担して行っていた作業を1人で行う事になるのだから、当然パフォー
マンスは落ちる。接客中は調理を中断しなきゃならないし、逆もまた然りだから。

> 改良できないかと思い
前述の通り、何か対策を取らなければパフォーマンスが落ちる結果が予想される。一般的見地で言う改良とは
異なる結果になるかもしれない。
スレッド禁止等の特殊な事情があるならば止むを得ないが、↑行辺りの事はマサダさん的には了承済み?

> OnShowWindow()の直後(画面表示後)に呼ばれるイベントハンドラなどがありましたら
自分で機会を作ってやっても良いかと

BEGIN_MESSAGE_MAP
    ON_MESSAGE(WM_APP, OnWmApp)
END_MESSAGE_MAP

void CHogeDlg::OnShowWindow(BOOL bShow, UINT nStatus) {
    CDialog::OnShowWindow(bShow, nStatus);
    PostMessage(WM_APP);
}
LRESULT CHogeDlg::OnWmApp(WPARAM, LPARAM) {
    :
}


マサダ  2009-06-18 22:11:55  No: 70349

返信ありがとうございます。
データサイズはできても、数百行ほどです。 この事を記述していませんでした。申し訳ありません。

なので、パフォーマンスを気にするというより、どちらかといえばリストボックスに表示時に、一瞬フリーズする現象を防ぐために、読み取りようの別スレッドを作成していたぐらいです(^^;

gakさんの言われた、自作でメッセージを作成して行いたいと思います。
ありがとうございました。


マサダ  2009-06-19 03:39:27  No: 70350

ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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