いつも勉強させて頂いています。
CFileDialogを用いて、ユーザーにファイル名を入力してもらっています。
今まで気づかなかったのですが、ユーザーが使用していて不思議な現象が出ました。
開発環境
Windows2000Sp4 + VC6Sp5(MFC使用)
現象
例えば、C:\tempにAAA.CSVが保存されています。
下記に提示するコードを用いてファイル保存ダイアログを表示します。
(以下単にダイアログと記述します)
ダイアログのリストからAAA.CSVを選択します。
(テキストボックスにAAA.CSVが設定されますよね。)
保存をせずに、リスト、コンボボックスを操作してデスクトップを選択します。
(デスクトップにはAAA.CSVは存在しません。)
ここで、保存ボタンをクリックすると、なんと上書き確認のメッセージが
表示されてしまいます。 ←これが問題!!!
ソース抜粋
// ファイル保存ダイアログ
CFileDialog FileDlg( false, CSV,NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,
CSV File (*.CSV)|*.CSV||,
NULL );
if( FileDlg.DoModal() == IDOK ){
ちょっと文章では伝えにくいのですが、理解していただけたでしょうか?
私がデバッグしたところによると、
直接テキストボックスに入力しても現象は確認できません。
デスクトップのパス(C:\defaults and....)を指定したときは発生しません。
APIのGetSaveFileNameも試してみましたが、同じ現象を確認しました。
何か使い方が間違えていますか?それともMicrosoftの…
対応法をご存知の方がいらっしゃったら、お力をお貸しください。
よろしくお願いします。
あらん、そんなん起こるんやん……と試してみるものの再現せず。
XP+VC6 で現象確認できずというあまり役に立たない情報まで
> 保存をせずに、リスト、コンボボックスを操作してデスクトップを選択します。
> (デスクトップにはAAA.CSVは存在しません。)
> ここで、保存ボタンをクリックすると、なんと上書き確認のメッセージが
> 表示されてしまいます。 ←これが問題!!!
> デスクトップのパス(C:\defaults and....)を指定したときは発生しません。
どっち?
なんかおかしくない?
マイドキュメントやマイコンピュータの上位にあるデスクトップでは発生するけれど、
C:\Documents and Settings\... のデスクトップフォルダでは発生しないということか
な。
うわぁ!本当だ!
因みに私の環境ではGetSaveFileName()で左横にOutLookショートカットバー(って言うんでし
たっけ?)出ていましたので、ソコのデスクトップを押すと上書き確認はされません。
う~ん、怪しい....。
↑解決になってませんが
Win2000 SP4 VC++6 SP5
秋衛門 様、シャノン 様、ひろぴー 様 情報ありがとうございます。
>秋衛門 様
>XP+VC6 で現象確認できずというあまり役に立たない情報まで
手近にXP(というか他のOS)が無いので、他のOSでは確認できていないのです。
情報ありがとうございました。
>シャノン 様
>マイドキュメントやマイコンピュータの上位にあるデスクトップでは発生するけれど、
>C:\Documents and Settings\... のデスクトップフォルダでは発生しないということか
>な。
はい。そういうことです。ちょっとわかりにくい文章でしたね。
>ひろぴー 様
>うわぁ!本当だ!
>因みに私の環境ではGetSaveFileName()で左横にOutLookショートカットバー
>(って言うんでしたっけ?)出ていましたので、ソコのデスクトッ
>プを押すと上書き確認はされません。
「APIを使用しても同じだ~」という事しか確認していなかったので、
後ほど試してみます。
う~ん…どのように対処したら良いかわからない…。
「どうやらMicrosoftの…」という事で終わりにしてしまおうか…
以前、どかの掲示板でみたような記憶があります。
その時に試しましたが……
Windows98SE(COMDLG32.DLL Ver4.72.3510.2300)では再現せず…でした。<さっきまた試し
た。
APIのレベルで発生しているので、バグと思われますが……
ちなみにWindows2000 SP4(COMDLG32.DLL Ver5.00.3315.3727)では発生しました。
プレースバーは無しの状態…です。
いろはです。
瀬戸っぷ様、情報ありがとうございました。
現在GetSaveFileNameの方で、再度確認中です。
すると、GetSaveFileNameを使用すると現象が出ないようです。
(最初に質問したときに、同様の現象が出るというのは嘘だったようです…)
という事で、CFileDialogを使用するのをあきらめて、APIを使用するように
方針転換することにしました。
一応、解決といたします。ありがとうございました。
> 現在GetSaveFileNameの方で、再度確認中です。
> すると、GetSaveFileNameを使用すると現象が出ないようです。
> (最初に質問したときに、同様の現象が出るというのは嘘だったようです…)
> という事で、CFileDialogを使用するのをあきらめて、APIを使用するように
> 方針転換することにしました。
私の方ではGetSaveileName()API使用でも出ましたが。(Windows2000の方で)
CFileDialogでも最終的にGetOpenFileName()/GetSaveFileName()が使用されるので、
APIに切り替えても同じハズです。
(どちらが使用されるかは、CFileDialogのコンストラクタのbOpenFileDialog引数によります)
詳しくは…MFCのソース(DLGFILE.CPPのCFileDialog::DoModal())を見て下さい。
いろはです。
瀬戸っぷ 様、情報ありがとうございます。
>私の方ではGetSaveileName()API使用でも出ましたが。(Windows2000の方で)
おや、そうですか?
昨日は私がデバッグした限りではAPIを使用すれば、現象は出ませんでした。
こんなソースです。
(抜粋)
TCHAR strFile[MAX_PATH];
::memset( strFile, 0, sizeof(strFile) );
OPENFILENAME ofn;
::memset( &ofn, 0, sizeof(OPENFILENAME) );
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
ofn.lpstrFilter = CSV File(*.CSV)\0*.CSV\0\0;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFile = strFile;
ofn.lpstrDefExt = CSV;
::GetSaveFileName( &ofn );
>CFileDialogでも最終的にGetOpenFileName()/GetSaveFileName()が使用されるので、
> 以下略
MFCのソースは追っていましたので、これはわかっていました。
Windows2000からOPENFILENAME構造体が拡張されましたよね。
今回の問題は、これが絡んでいるのではないかと思っています。
> Windows2000からOPENFILENAME構造体が拡張されましたよね。
> 今回の問題は、これが絡んでいるのではないかと思っています。
プレースバー…でしたか、拡張されていますね。
私は使っていませんが…
#ifndef OPENFILENAME_SIZE_VERSION_400
stGofn.lStructSize = sizeof(OPENFILENAME);
#else
stGofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#endif
こんなコトして強制使用しています。
ちなみに、その辺の関係かMFC7.0(VC++.net)では
CFileDialogのコンストラクタで引数が1つ増えていたりします。
MFC6.0環境からのソースをコンパイルした場合に、条件によっては問題が出るらしいです。
(Googleで検索すると、その問題を調べたページがみつかるかと)
ちなみに、テストした時のOPENFILENAME構造体の設定は…
OPENFILENAME stGofn;
char szTemp[MAX_PATH];
ZeroMemory(szTemp, MAX_PATH);
ZeroMemory(&stGofn, sizeof(OPENFILENAME));
#ifndef OPENFILENAME_SIZE_VERSION_400
stGofn.lStructSize = sizeof(OPENFILENAME);
#else
stGofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#endif
stGofn.hwndOwner = hwnd;
stGofn.lpstrFilter = 全てのファイル(*.*)\0*.*\0;
stGofn.nFilterIndex = 1;
stGofn.lpstrTitle = 名前を付けて保存・てすと;
stGofn.lpstrFile = szTemp;
stGofn.nMaxFile = (MAX_PATH-3);
stGofn.Flags = OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK |
OFN_EXPLORER | OFN_PATHMUSTEXIST;
stGofn.lpstrDefExt = TXT;
stGofn.lpfnHook = (LPOFNHOOKPROC)OFNHookProc;
GetSaveFileName(&stGofn);
です。(VC++6.0 SDKです。)
フックを使用していますが、各状態での内容を調べる為…なので、今回の問題には無関係です。
私が提示したソースに嘘がありました。
>ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
保存なのにOFN_FILEMUSTEXISTって…
正解はこちらです。
ofn.Flags = OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
このように修正した結果、やはり出ました。現象が…
プレースバーのデスクトップを選ぶと大丈夫なのですがね。
結局、バグという事ですかね。
ありがとうございました。
UINT CALLBACK OFNHookProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam) {
OFNOTIFY* lpOFNotify = (OFNOTIFY*)lParam;
switch( message ) {
case WM_NOTIFY:
if( lpOFNotify->hdr.code == CDN_SELCHANGE ) {
HWND hEdit = GetDlgItem( GetParent( hwnd ), edt1 );
if( hEdit ) {
char FileName[32000];
GetWindowText( hEdit, FileName, 32000 );
SetWindowText( hEdit, FileName );
}
}
break;
}
return 0;
}
こんな感じで CDN_SELCHANGE 通知時にエディットボックスの内容を
上書きしたら、不要な上書き確認は表示されなくなりました。
# フックを使ったらプレースバーが表示されなくなりましたけど、
# 自前でダイアログを書き換えないとダメなのでしょうか。
> 自作のアプリをXP上で起動し、起動した状態でデスクトップ
> テーマの変更を行うと、フォントをいじっている
> スタティックコントロールが汚く表示されてしまいます。
> なにか解決策はないのでしょうか?
XPは使ったことないですが…
デーマを変更した時になにかメッセージが飛んできませんか?
それらに応答する処理を追加してみてはどうでしょうか?
画面のプロパティのデザインで変更すると、
WM_SYSCOLORCHANGEやWM_SETTINGCHANGEが飛んできたりとかしますが。
Spy++で監視していると関連するメッセージがわかるかも知れません。
> こんな感じで CDN_SELCHANGE 通知時にエディットボックスの内容を
> 上書きしたら、不要な上書き確認は表示されなくなりました。
ソレをヒントにいぢってみました。
エディトボックスにEM_SETMODIFYで更新フラグを設定してみる……失敗。
親ウィンドウにEN_CHANGEとEN_UPDATEを送ってみる……成功。
親ウィンドウにEN_UPDATEを送ってみる……失敗。
親ウィンドウにEN_CHANGEを送ってみる……成功。
というコトで…
case WM_NOTIFY:
if( lpOFNotify->hdr.code == CDN_SELCHANGE ) {
HWND hEdit = GetDlgItem( GetParent( hwnd ), edt1 );
if( hEdit ) {
SendMessage(GetParent( hwnd ), WM_COMMAND, MAKEWPARAM(edt1,
EN_CHANGE), (LPARAM)hEdit);
}
}
で行けました。
まぁ、EN_CHANGEのあとにEN_UPDATEも送っておいた方がよさそうですけど。
> # フックを使ったらプレースバーが表示されなくなりましたけど、
> # 自前でダイアログを書き換えないとダメなのでしょうか。
消えますね。
なんらかの方法で可能なハズ(秀丸では表示させている)と思われますが…
ちょっと調べきれなかったです。
(秀丸のテンプレートではプレースバーは入っていませんでした…)
げ……
テキストファイルで編集してから貼り付けていますが……
要らないモノまで貼り付けてしまいました(^_^;)
> 自作のアプリをXP上で起動し、起動した状態でデスクトップ
から
Spy++で監視していると関連するメッセージがわかるかも知れません。
までは無視して下さい(汗)