So-net無料ブログ作成

ファイル選択ダイアログのフリーズ対策 [プログラミング]

ファイル選択ダイアログがフリーズすることがあります。

発生条件は次の通り。

  • 開発環境は、Visual C++ 2008。MFC使用。32bitアプリとしてビルド。
  • 実行環境は、Windows 7。
  • ダイアログの形式は古い形式。(CFileDialogのコンストラクタでbVistaStyleFALSEを指定)
  • CFileDialog::SetTemplate()でテンプレートを指定。
  • CFileDialogを派生して、派生クラスでOnFileNameOK()をオーバーライド。
  • オーバーライドしたOnFileNameOK()の中でメッセージボックスを表示。

とすると、OnFileNameOK()のメッセージボックスを表示したところでフリーズします。

上に書いた発生条件は厳密なものではなく、不要な条件もありそうです。
例えば、Vistaでも発生しそうです(ちなみに、Win7は32bit/64bitの両方で発生。XPでは発生せず)。
SetTemplate()は必要ないかもしれません。


さて、

色々と調べたり試したりしたんですが、フリーズの原因は、良く分かりませんでした。

ただ、なんとなく、スレッドがデッドロックを起こしている様な雰囲気が漂っていたんですよね。なんとなく。

そんなわけで
(フリーズの発生箇所はOnFileNameOK()の中でメッセージボックスを表示している所(表示した直後)だと分かっているので)メッセージボックスの表示を別のところに移動したら良いんじゃないかな?と考えました。

実際、それでうまくいきました。


フリーズするコード(抜粋):
オーバーライドしたOnFileNameOK()でメッセージボックスを出すとフリーズ。

BOOL DerivedFileDialog::OnFileNameOK()
{
    if (何かの条件) {
        MessageBox(_T("メッセージ"));
        return TRUE;
    }
    return FALSE;
}

解決したコード(抜粋):
オーバーライドしたOnFileNameOK()のメッセージボックスを出したいところでユーザメッセージをポスト。そのハンドラでメッセージを表示。

class DerivedFileDialog : public CFileDialog
{
    afx_msg LRESULT OnShowMessageBox(WPARAM, LPARAM);
    DECLARE_MESSAGE_MAP()
};

const UINT WM_SHOW_MESSAGE_BOX = WM_USER + 100;

BEGIN_MESSAGE_MAP(DerivedFileDialog, CFileDialog)
    ON_MESSAGE(WM_SHOW_MESSAGE_BOX, OnShowMessageBox)
END_MESSAGE_MAP()

BOOL DerivedFileDialog::OnFileNameOK()
{
    if (何かの条件) {
        PostMessage(WM_SHOW_MESSAGE_BOX);
        return TRUE;
    }
    return FALSE;
}

LRESULT DerivedFileDialog::OnShowMessageBox(WPARAM, LPARAM)
{
    MessageBox(_T("メッセージ"));
}

ユーザメッセージはポストしてますけど、SendMessage()だとどうなるかは判りません。


タグ:MFC VisualC++
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。