ホーム ATL/WTL
ファイル選択ダイアログ
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2007/04/08
PR
 WTLではコモンダイアログのファイル選択ダイアログを CFileDialogImplというクラステンプレートでカプセル化しています。 これはATLのCDialogImplクラステンプレートのように基底クラスとしてのみ使用します。 atldlgs.hヘッダではCFileDialogImplから派生したCFileDialogクラスが定義されています。

// atldlgs.h
class CFileDialog : public CFileDialogImpl<CFileDialog>
{
    ...
    ...
			

CFileDialogクラスは、[ファイルを開く]ダイアログと、 [名前を付けて保存]ダイアログをサポートしています。

 WTLのCFileDialogクラスは、MFCの同名のクラスと同等の機能を備えています。 以下に示すのは、CFileDialogクラスを使用する例です。


// [ファイルを開く]ダイアログ
CFileDialog dlg(TRUE, _T("txt"), NULL, OFN_HIDEREADONLY | OFN_CREATEPROMPT,
    _T("テキスト ファイル (*.txt)\0*.txt\0すべてのファイル (*.*)\0*.*\0\0"));

if(dlg.DoModal() == IDOK){
    CString strMsg;
    strMsg.Format(_T("ファイル名:%s\nパス:%s"), dlg.m_szFileTitle, dlg.m_szFileName);
    MessageBox(strMsg);
}
			


// [名前を付けて保存]ダイアログ
CFileDialog dlg(FALSE, _T("txt"), _T("無題"), OFN_OVERWRITEPROMPT,
    _T("テキスト ファイル (*.txt)\0*.txt\0すべてのファイル (*.*)\0*.*\0\0"));

if(dlg.DoModal() == IDOK){
    CString strMsg;
    strMsg.Format(_T("ファイル名:%s\nパス:%s"), dlg.m_szFileTitle, dlg.m_szFileName);
    MessageBox(strMsg);
}
			

CFileDialogクラスのコンストラクタの第1引数にはBOOL値を指定します。 TRUEの場合は[ファイルを開く]ダイアログを作成し、FALSEの場合は[名前を付けて保存]ダイアログを作成します。 残りの引数は省略可能で、順にデフォルト拡張子、デフォルトファイル名、フラグ、フィルタ、 親ウィンドウのハンドルです。

ファイル選択ダイアログを表示するためにはCFileDialogクラスのメンバ関数であるDoModal()を呼び出します。 [開く](または[保存])ボタンを押してファイル選択ダイアログを閉じた場合は、 戻り値としてIDOKが、 [キャンセル]ボタンを押して閉じた場合はIDCANCELが返ります。

戻り値がIDOKの場合は、CFileDialogクラスのメンバ変数である m_szFileTitlem_szFileNameに、 それぞれファイル名とファイルパスが設定されます。

CFileDialogクラスの基底クラスであるCFileDialogImplはメッセージマップを用意しており、 ファイル選択ダイアログ用のWM_NOTIFYメッセージをマッピングします。 メッセージマップは、WM_NOTIFYメッセージの通知コードによって間接的に次のようなメンバ関数を呼び出します。

通知コード メンバ関数名
CDN_FILEOK OnFileOK
CDN_FOLDERCHANGE OnFolderChange
CDN_HELP OnHelp
CDN_INITDONE OnInitDone
CDN_SELCHANGE OnSelChange
CDN_SHAREVIOLATION OnShareViolation
CDN_TYPECHANGE OnTypeChange

CFileDialogImplの派生クラスは、これらのメンバ関数をオーバーライドすることによって、 ファイル選択ダイアログの動作をカスタマイズすることができます。

次に示すのは、OnInitDone()OnHelp()をオーバーライドして、 独自のファイル選択ダイアログを作成する例です。 プロジェクトにCustomDlg.hというヘッダファイルを追加し、 そこにCCustomDlgというクラスを定義します。 このファイル選択ダイアログには[ヘルプ]ボタンが追加され、親ウィンドウの中央に表示されます。


// CustomDlg.h
#pragma once

class CCustomDlg : public CFileDialogImpl<CCustomDlg>
{
public:
    // コンストラクタ
    CCustomDlg(BOOL bOpenFileDialog,
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        LPCTSTR lpszFilter = NULL,
        HWND hWndParent = NULL)
        : CFileDialogImpl<CCustomDlg>(bOpenFileDialog,
            lpszDefExt, lpszFileName, dwFlags, lpszFilter, hWndParent)
    {
        // [ヘルプ]ボタンを表示するためにOFN_SHOWHELPフラグ追加
        m_ofn.Flags |= OFN_SHOWHELP;
    }

    void OnInitDone(LPOFNOTIFY lpon){
        // ファイル選択ダイアログを親ウィンドウの中心に表示
        GetFileDialogWindow().CenterWindow();
    }

    void OnHelp(LPOFNOTIFY lpon){
        // 現在開いているフォルダパスを取得
        TCHAR szPath[_MAX_PATH];
        GetFolderPath(szPath, sizeof(szPath)/sizeof(TCHAR));

        CString strMsg;
        strMsg.Format(_T("現在のフォルダは %s です。"), szPath);

        MessageBox(strMsg);
    }
};
			

CCustomDlgクラスのコンストラクタ引数は、 CFileDialogクラスのコンストラクタ引数を参考にしています。 コンストラクタでは、ファイル選択ダイアログに[ヘルプ]ボタンを追加するために OFN_SHOWHELPフラグを追加します。 OnInitDone()ではGetFileDialogWindow()を呼び出してファイル選択ダイアログのウィンドウオブジェクトを取得し、 CenterWindow()を呼び出してダイアログを中央に表示します。 OnHelp()は[ヘルプ]ボタンを押した時に呼び出されます。 今回の例では現在開いているフォルダパスをメッセージボックスで表示します。

 次に示すのは、CCustomDlgクラスを使用する例です。

プロジェクトファイル ダウンロード
// stdafx.h
#pragma once

#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

#include <atlcrack.h>
#include <atlmisc.h>
#include <atldlgs.h>  // コモンダイアログ用クラスを使用するため
			

// MainDlg.h
#pragma once

class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
    enum { IDD = IDD_MAINDLG };

    BEGIN_MSG_MAP(CMainDlg)
        MSG_WM_INITDIALOG(OnInitDialog)
        COMMAND_ID_HANDLER_EX(IDC_BUTTON_OPENDLG, OnButtonOpenDlg)
        COMMAND_ID_HANDLER_EX(IDOK, OnOK)
        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
    END_MSG_MAP()

    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam){
        // スクリーンの中央に配置
        CenterWindow();

        // 大きいアイコン設定
        HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
        SetIcon(hIcon, TRUE);
        
        // 小さいアイコン設定
        HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
        SetIcon(hIconSmall, FALSE);

        return TRUE;
    }

    void OnButtonOpenDlg(UINT uNotifyCode, int nID, CWindow wndCtl){
        CCustomDlg dlg(FALSE, _T("txt"), _T("無題"), OFN_OVERWRITEPROMPT,
            _T("テキスト ファイル (*.txt)\0*.txt\0すべてのファイル (*.*)\0*.*\0\0"));

        if(dlg.DoModal() == IDOK){
            CString strMsg;
            strMsg.Format(_T("ファイル名:%s\nパス:%s"),
                dlg.m_szFileTitle, dlg.m_szFileName);
            MessageBox(strMsg);
        }
    }

    void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl){
        EndDialog(nID);
    }

    void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl){
        EndDialog(nID);
    }
};
			

// SampleProject.cpp
#include "stdafx.h"
#include "resource.h"
#include "CustomDlg.h"
#include "MainDlg.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance, 
    HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
{
    HRESULT hRes = ::CoInitialize(NULL);
    ATLASSERT(SUCCEEDED(hRes));

    ::DefWindowProc(NULL, 0, 0, 0L);

    AtlInitCommonControls(ICC_BAR_CLASSES);

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    CMainDlg dlg;
    int nRet = (int) dlg.DoModal();

    _Module.Term();
    ::CoUninitialize();

    return nRet;
}
			

 まず、リソースを作成します。ダイアログにボタンコントロールを配置し、 [ID]と[Caption]を次のように設定します。

コントロール名 ID Caption
ボタン IDC_BUTTON_OPENDLG ダイアログを開く

 次に、stdafx.hヘッダでは、コモンダイアログを使用するためにatldlgs.hヘッダをインクルードします。

 CMainDlgクラスでは、リソースIDがIDC_BUTTON_OPENDLGWM_COMMANDメッセージハンドラとして OnButtonOpenDlg()を追加します。 このハンドラ関数ではCCustomDlgクラスのインスタンスを作成し、 DoModal()を呼び出して独自のファイル選択ダイアログを表示します。

 最後に、SampleProject.cppファイルでMainDlg.hヘッダの前にCustomDlg.hヘッダをインクルードします。