CFileDialogの派生クラスについて

解決


kanagawa  2006-06-08 09:48:39  No: 62083

CFileDialogの派生について質問です。

【背景】
CFileDialogを派生させ、自分で上書き確認のポップアップを表示させる処理をつくっています。その為、OnFileNameOK関数の中で、自前の上書き確認処理を入れていました。

【問題点】
ところがオープンしたファイルを再び指定して開きなおそうとした所、OnFileNameOK関数が2度CALLされてしまい、上書き確認のポップアップが2度表示されてしまいます。

【環境】
VisualStudio  C++6.0(EnterpriseEdition)
WindowsXP

【コード】
そこで下記のように単純なコードを作ってみました。
        CFileDialog lFileDialog( FALSE );
        CString lstrFileName;

        if( lFileDialog.DoModal() == IDOK )
        {
                lstrFileName = lFileDialog.GetPathName();
        
                if( m_File.m_pStream != NULL )
                {
                        m_File.Close();
                }
                m_File.Open( lstrFileName, CFile::modeCreate| CFile::modeWrite | CFile::typeText );
        }

上記のコードにおいて、一度ファイルダイアログよりファイルをオープンし、もう一度、上記コードを用いて、同一ファイルを指定した場合、上書き確認のポップアップが出て、OnFileNameOK関数が2度CALLされてしまいます。違うファイルを指定した場合はOnFileNameOK関数は一度しかCALLされません。また、最初のポップアップでOK、キャンセルしたとしても、もう一度OnFileNameOK関数が呼ばれてしまいます。どのようにすれば、ポップアップを一度だけ表示させる事が出来るでしょうか?

どうかご回答いただけますようよろしくお願いいたします。


kanagawa  2006-06-11 06:35:11  No: 62084

何らかの情報でもいいのでわかる方がいらっしゃいましたらご回答下さい。


iijima  2006-06-11 10:25:36  No: 62085

本当にOnFileNameOK関数が2回呼ばれているのならば、その派生クラスの定義に問題があると思います。
現象が再現される最小限の定義を示していただければ、なにか分かるかも知れません。

なお、デフォルトの上書き確認処理をしないようにするには、CFileDialogコンストラクタの第4引数に渡すフラグから「OFN_OVERWRITEPROMPT」をはずせば良いです(これをはずしてもOnFileNameOKは呼ばれます)。


kanagawa  2006-06-12 06:22:23  No: 62086

ご返事ありがとうございます。
すいません、書き方がややこしかったかもしれません。

私も派生クラスに何か問題があると思って、上記の【コード】にもあるように、標準のCFileDialogで試してみたのですが、やはり標準のCFileDialogでも同様にOnFileNameOK関数が2回CALLされています。

ちなみに派生クラスで試したときは、自前で上書き確認処理を入れていた為、OFN_OVERWRITEPROMPTははずしてあります。

CFileDialog自体がそのようなもの?あるいはMicroSoftの・・・なのでしょうか?


dairygoods  2006-06-12 18:31:26  No: 62087

WinXP, VC++6.0 で試してみましたが、一度しか呼ばれませんでした。


kanagawa  2006-06-14 10:37:28  No: 62088

こちらでは下記の環境にて、再現しております。

WindousXP VC++.NET 2003
WindousXP VC++6.0

ちなみに念のためもう一度再現手順を記述致します。

【コード】
ダイアログベースのアプリケーションを作成
ダイアログにボタンを配置

ダイアログのボタン押下時のイベント処理に下記のコードを記述
CFileDialog lFileDialog( FALSE );
CString lstrFileName;

if( lFileDialog.DoModal() == IDOK )
{
lstrFileName = lFileDialog.GetPathName();

if( m_File.m_pStream != NULL )
{
m_File.Close();
}
m_File.Open( lstrFileName, CFile::modeCreate| CFile::modeWrite | CFile::typeText );
}

【再現手順】
1、アプリケーション起動
2、アプリケーションのボタン押下
3、[名前を付けて保存]ダイアログ起動
4、ファイルを指定し、保存ボタンの押下
5、OnFileNameOK関数がここでは1度CALLされる
    (アプリケーションは終了させない。)
6、もう一度アプリケーションのボタン押下
7、先ほどと同じファイルを指定
8、標準の処理にて、上書き確認のポップアップ表示
9、ポップアップにて[はい]/[いいえ]ボタンの押下
    (どちらでも再現します)
8、OnFileNameOK関数が2度CALLされる


kanagawa  2006-06-14 11:01:55  No: 62089

すいません一部間違えがありました。

【再現手順】
1、アプリケーション起動
2、アプリケーションのボタン押下
3、[名前を付けて保存]ダイアログ起動
4、ファイルを指定し、保存ボタンの押下
5、OnFileNameOK関数がここでは1度CALLされる
    (アプリケーションは終了させない。)
6、もう一度アプリケーションのボタン押下
7、[名前を付けて保存]ダイアログ起動
8、先ほどと同じファイルを指定
9、上書き確認のポップアップ表示
    (このポップアップは標準処理を通っています)
10、ポップアップにて[はい]/[いいえ]ボタンの押下
    (どちらでも再現します)
11、OnFileNameOK関数が2度CALLされる


kanagawa  2006-06-14 11:08:44  No: 62090

大事な点が一点抜けていました。

[名前を付けて保存]ダイアログより、ファイルの指定はファイル名を必ず入力し、[保存]ボタンを押下しなければ、現象が再現しません。

[名前を付けて保存]ダイアログにて、ファイルを選択し、[保存]ボタンを押下するだけでは再現しません。


dairygoods  2006-06-14 19:07:56  No: 62091

二度呼ばれることを確認しました。

これは、対象ファイルが開けっ放しの場合に発生するようです。
GetSaveFileName を直接呼び出しても発生します。
次のいずれかの方法で回避しては。

1. lFileDialog.DoModal() の前にファイルを閉じる。
2. ファイルを共有読取許可(CFile::shareDenyWrite)で開く。
3. フラグを使って二度目の呼び出しを無視する。

他のアプリケーションが排他オープンしている
可能性も考慮するのでしたら、
3. の方法で回避するのが確実だと思います。


kanagawa  2006-06-15 09:52:10  No: 62092

ご回答ありがとうございます。

1. lFileDialog.DoModal() の前にファイルを閉じる。
今回はファイルを開いたまま次のファイルを指定したい為、今回についてはこの方法は使えません。

2. ファイルを共有読取許可(CFile::shareDenyWrite)で開く。
ファイルを共有読取許可で開けば問題ありませんでした。

3. フラグを使って二度目の呼び出しを無視する。
フラグは私も試したのですが、1度だけCALLされる場合や、上書き確認のポップアップで[はい]/[いいえ]が押される事を考慮すると、ファイル名を入力ではなくて、選択した場合等、考慮される条件が多々ある為、フラグだけでは厳しいと思われます。

上記の事を考慮し、今回は2のファイルを共有読取許可で開く事とします。
dairygoodsさん、iijimaさんありがとうございました。本当に助かりました。また、ややこしくなってしまい申し訳ございませんでした。
また、


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

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






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