たびたびお世話になります。yellowと申します。
■質問
VisualC++/MFCで、ダイアログベースのWindowsアプリケーションを作成しています。
ダイアログボックス上で以下の機能を実現したいと考えていますが、
MFCで簡単に(手軽に?)実現できる方法はあるでしょうか?
ダイアログボックスに、以下の機能を持つコントロールを実装できますでしょうか。
【コントロール】
1.コンボボックスで、ドライブを選択できるコントロール。
(VB6でいうところの「ドライブリストボックス」の機能)
2.リストボックスで、フォルダを選択できるコントロール。
(VB6でいうところの、「ディレクトリリストボックス」の機能)
3.リストボックスで、ファイルを表示できるコントロール。
(VB6でいうところの、「ファイルリストボックス」の機能)
【機能】
これら1~3を、ひとつのダイアログボックス上に表示しておき、
1のコンボボックスでドライブ(c:とかd:等)を選択すると、
2のリストボックスにそのドライブをルートとするディレクトリツリーを表示し、
2のリストボックス中で開いているディレクトリに入っているファイル一覧が
3のリストボックスに表示される、という動作をさせたいです。
調査してみたところ、一般的なコモンダイアログでは出来なさそうだという事はわかり
ました。
Windowsでよく見る機能なので、比較的簡単に実装できるのではないか?とは予想してい
るのですが、取っ掛かりが見つかりません。
知っている方にとっては、あまりに当たり前・・・という感じの事なのかも知れません
が、入門書レベルから少しずつ勉強して、やっとMFCの基本的な使い方を試しているよう
な状態なので、困っています。
方法をご存知の方、ヒントをいただけませんでしょうか・・・?
■環境
開発OS:Windows XP Pro
動作対象OS:Windows 98、2000、XP
開発言語:VC++/MFC
開発環境:VisualStudio2005(.NETFrameworkは不使用)
どうぞよろしくお願いいたします。
古いタイプのファイル選択ダイアログのことでしょうか?
CFileDialog dlg(TRUE);
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
最近のソフトなら多分、ファイル選択ダイアログで済ましてしまう所ですね。
新しいタイプのファイル選択ダイアログでも機能的には不自由は無いように感じますが、
古いタイプのファイル選択ダイアログを使いたい理由は何なんでしょう?
単にデザイン的な話だけなんでしょうか。
デザイン的なものに凝るのであれば、自分でコンボボックスを並べて
制御すれば、同等のものは可能だと思います。
但し、お手軽にと言うわけには行きませんけれど。
うまく作成すれば、再利用も可能だと思うので拘るのであれば、
チャレンジしてみても悪くないかもしれません。
CWnd::DlgDirListComboBox
CWnd::DlgDirList
あたりのことかな?
皆様、いろいろとご助言ありがとうございます。
現時点で、まだ解決はしていないのですが、以下の方法を試してみている最中です。
(試すための知識が足りず、試行錯誤を繰り返しているところです)
【現状】
1.実現したい機能について
dairygoods様のおっしゃるとおり、私が実現したいのは、
「古いタイプのファイル選択ダイアログ」のようなものです。
------------------------------------------------------------
CFileDialog dlg(TRUE);
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
------------------------------------------------------------
このコードで表示される「ファイルを開く」ダイアログ上の部品のうち、
以下の物のみ残したいと考えています。
・[ドライブ]コンボボックス
・[フォルダ]ツリービュー
・[OK]ボタン
・[キャンセル]ボタン
・[ファイル名]テキストボックスの下にあるリストボックス
これらの部品を、デフォルトの状態とは配置を変えて表示し、
さらに独自のコントロールを幾つか追加した画面としたいです。
2.実現方法
CFileDialogクラスを継承した独自クラスを作成し、カスタマイズする
方法を検討しています。
多分できそうかな?と思っているんですが、継承したクラスの作成方法から
勉強しないと・・・という状況ですので、時間はかかりそうです。
皆様にご意見をいただいたものの、試すにも時間がかかりそうでしたので、
中間報告をさせていただきました。
> 古いタイプのファイル選択ダイアログを使いたい理由は何なんでしょう?
> 単にデザイン的な話だけなんでしょうか。
はい。デザイン的な話だけです。
既存のソフトウェアがありまして、それと同様のデザインを実装したいんです。
> CWnd::DlgDirListComboBox
> CWnd::DlgDirList
> あたりのことかな?
名前からすると、なんとなく、目的の機能に近そうなイメージがありますが、
まだちょっと調べられていません。
有力なヒント、ありがとうございます。
MFC、奥が深いですね。
CFileDialog,カスタマイズ
で検索するといろいろ出てきますよ
ただし、既存のコントロールの位置は変えれないような・・・
非表示にはできたと思いますが・・・
どうしても、デザインにこだわるのであれば、すべて独自のダイアログとして実装したほ
うが簡単なのではないでしょうか?
ドライブ、フォルダ、ファイルを自分で検索してコントロールに表示するだけですし
たしか古いタイプのコモンダイアログの場合、
リソースを丸ごとカスタマイズできたはずです。
以下を参照。
http://msdn.microsoft.com/library/en-
us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/aboutcommon
dialogboxes/customizingcommondialogboxes.asp
自前でダイアログを作成するなら
http://hp.vector.co.jp/authors/VA007799/tips/tips11.htm
で、丁寧に解説されてますね。
有効な情報はそろってそうです。
だいぶ時間を置いてしまい申し訳ありません。
多くの皆さんのご意見を頂戴でき、大変ありがたく思っています。
お教えいただきました方法を検討させていただきましたが、
「CFileDialogのカスタマイズ」で実現する方向にすることにしました。
しかし、本件、まだ解決できていません。
【現状】
以前、以下のように書きましたが、
> 1.実現したい機能について
> dairygoods様のおっしゃるとおり、私が実現したいのは、
> 「古いタイプのファイル選択ダイアログ」のようなものです。
> ------------------------------------------------------------
> CFileDialog dlg(TRUE);
> dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
> dlg.DoModal();
> ------------------------------------------------------------
> このコードで表示される「ファイルを開く」ダイアログ上の部品のうち、
> 以下の物のみ残したいと考えています。
> ・[ドライブ]コンボボックス
> ・[フォルダ]ツリービュー
> ・[OK]ボタン
> ・[キャンセル]ボタン
> ・[ファイル名]テキストボックスの下にあるリストボックス
CFileDialogのカスタマイズによって、見た目だけは上記のようにすることが
できました。(その方法は、この発言に続けて記載いたします。)
しかし、機能が正常に動作しません。
問題点を切り分けるため、カスタマイズの手順を最初からさかの
ぼって確認したところ、そもそもカスタマイズ前のコモンダイア
ログが動いていませんでした。
コモンダイアログの使い方を間違えているのだと思います。
新しい「エクスプローラタイプ」の使い方はあちこちのサイトに
ありますが、「古いタイプ」はわかりやすい解説が見つけられません。
大変恐縮ですが、以下の問題の解決方法をご教授いただけませんか?
(たぶん非常に単純なことなのではないかと予想しています・・・)
【問題】
以下の方法でファイル選択ダイアログ「古いタイプ」を起動した
際、ダイアログの右側にある[ドライブ]コンボボックスおよび
[フォルダ]リストボックスは使える状態ですが、
[フォルダ]リストボックスで選択状態になっているフォルダ内の
ファイル一覧を、ダイアログ左側のリストボックスに一覧表示
できません。
------------------------------------------------------------
CFileDialog dlg(TRUE);
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
------------------------------------------------------------
「古いタイプ」のファイル選択ダイアログで、ファイルを選択できる
ようにするにはどうしたらよいのでしょうか?
(「エクスプローラタイプ」だと、
if (dlg.DoModal() ==IDOK)
{
FilePath =dlg.GetPathName();
}
これだけ書けばファイル名を取得できるのですが・・・)
一つ前の発言で書きましたように、現時点でまだ問題解決はしてい
ませんが、途中まではできた状態です。
現状までの手順を記載いたします。
【CFileDialogのカスタマイズ方法】
(1)コモンダイアログボックスのテンプレート(英語版)を
自分のリソースファイルにコピー。
・VisualStudioのインストールフォルダにある「FileOpen.Dlg」
の、「Old File Open and Save As Dialogs.」をコピーし、
自分のリソースファイルにコピペしました。
そして、フォントの種類を「MS UI Gothic」に変更しました。
(この作業はテキストエディタにて行いました)
------------------------------------------------------------
FILEOPENORD DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 268, 134
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME |
DS_CONTEXTHELP | DS_3DLOOK
CAPTION Open
FONT 8, MS UI Gothic
BEGIN
(中略)
END
------------------------------------------------------------
(2)resource.hにDlgs.hをインクルード。
・VisualStudioのインストールフォルダにある「Dlgs.h」という
ヘッダファイルを、自分のプロジェクトの「resource.h」に
インクルードしました。
(この作業はテキストエディタにて行いました)
------------------------------------------------------------
#include <Dlgs.h>
------------------------------------------------------------
(3)VisualStudioのリソースエディタで見た目を編集。
・普通にソリューションファイルを開き、リソースビューで
上記ダイアログを編集。
(とりあえず、スタティックテキストを貼り付けたり、不要
部分を削除してみました。)
この時点では、ダイアログIDは「FILEOPENORD」となっています。
後で好きなIDに変更もできそうですが、今はいじっていません。
(4)ダイアログに対応したMFCクラスの追加。
・VisualStudioのクラスビューで、MFCクラスを追加します。
設定は以下のようにしました。
クラス名:CCustomFileDialog
基本クラス:CFileDialog
ダイアログID:FILEOPENORD
(5)クラスのコンストラクタに以下のコードを追加。
・CCustomFileDialogクラスのコンストラクタに以下のコードを追加。
m_ofn.hInstance = AfxGetResourceHandle(); // よくわからない・・
m_ofn.Flags &= ~OFN_EXPLORER; // 古いタイプにするため
SetTemplate(FILEOPENORD, FILEOPENORD); // この指定はちょっと変?
(6)呼び出し元ダイアログからカスタマイズされたファイル
ダイアログを呼び出す。
・呼び出し元ダイアログのクラスに以下のコードを追加。
------------------------------------------------------------
#include CustomFileDialog.h
・
・
・
(ボタンクリックなどのイベントハンドラ関数の中で)
CCustomFileDialog dlg(TRUE);
dlg.DoModal();
------------------------------------------------------------
以上の手順で、見た目をカスタマイズした「ファイル選択ダイアログ」
を表示できます。
※先の発言で書きましたように、これだけだと、ダイアログの右側の
機能しか使えません。
------------------------------------------------------------
CFileDialog dlg(TRUE);
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
------------------------------------------------------------
を以下のように変更してみてください。
↓
------------------------------------------------------------
static char BASED_CODE szFilter[] = *.txt|*.txt|;
CFileDialog dlg(TRUE, txt, *.txt,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
szFilter, this);
------------------------------------------------------------
恐らくフィルタの設定がされていないのが問題だと思います。
(上記サンプルはリスト表示するのは*.txtのみを対象としています)
MSDNのCFileDialog::CFileDialogの下の方に解説が載っているので
それを見ると分かりやすいかもです。
外してたらごめんなさいm(_ _)m
おっと失礼。
------------------------------------------------------------
CFileDialog dlg(TRUE);
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
------------------------------------------------------------
を以下のように変更してみてください。
↓
------------------------------------------------------------
static char BASED_CODE szFilter[] = *.txt|*.txt|;
CFileDialog dlg(TRUE, txt, *.txt,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
szFilter, this);
dlg.m_ofn.lpstrInitialDir = 指定フォルダのパス;
dlg.m_ofn.Flags &= ~OFN_EXPLORER; // 新タイプフラグを外す
dlg.DoModal();
------------------------------------------------------------
> Fly様
ありがとうございました!ご指摘のとおりでした。
フィルタの設定をしないと、何も表示されないのですね。
(よく考えたら、当たり前の話ですね・・・)
Fly様に書いていただいたようにソースコードを修正した所、
「古いタイプ」のファイル選択ダイアログが使えるようになりました。
また、17:59:49に記載した手順で作成した、カスタマイズ後のファイル選択
ダイアログも動作するようになりました。
MSDNの「CFileDialog::CFileDialog」のページ(以下リンク)も
読みました。
http://msdn2.microsoft.com/ja-jp/library/wh5hz49d.aspx
Fly様の説明とあわせて読んだところ、やっと意味がわかりました!
Fly様、ならびに皆様、本当にありがとうございました!!
希望どおりの機能を実現できましたので、ステータスを「解決」とさせて戴きます。
※調査中に、本件に関連する便利なサイトを見つけましたので、
ご参考までに記載しておきます。
・OfnKingサンプル
http://support.microsoft.com/default.aspx?scid=kb%3Bja%3B195034
(CFileDialogカスタマイズに関してかなりドンピシャなサンプル。
しかし、私にはちょっと難しい内容でした。)
・Advanced MFC Programming(PDF)
http://piano.dsi.uminho.pt/~elisabet/lecomli4/material/c/Advanced%20MFC%
20Programming.pdf
(英語ですが、かなり詳しくCFileDialogの事が載っていました。)
以上です。