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

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

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

 WTLのCFileDialogクラスは、MFCの同名のクラスと同等の機能を備えています。 以下に示すのは、CFileDialogクラスを使用する例です。 なお、WTLのコモンダイアログクラスを使用するためにはatldlgs.hヘッダをインクルードする必要があります。


// [ファイルを開く]ダイアログ
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の場合は[名前を付けて保存]ダイアログを作成します。 残りの引数は省略可能で、順にデフォルト拡張子、デフォルトファイル名、フラグ、フィルタ、 親ウィンドウのハンドルです。

ファイル選択ダイアログを表示するためには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内
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内
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

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

// maindlg.h内
class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
    enum { IDD = IDD_MAINDLG };

    // メッセージマップ
    BEGIN_MSG_MAP_EX(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()

    LRESULT OnInitDialog(HWND hWnd, LPARAM lParam){
        // スクリーンの中央に配置
        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, HWND hWndCtl){
        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, HWND hWndCtl){
        EndDialog(nID);
    }

    void OnCancel(UINT uNotifyCode, int nID, HWND hWndCtl){
        EndDialog(nID);
    }
};
			

// CommDlg.cpp内
#include "stdafx.h"

#include "resource.h"

#include "CustomDlg.h"
#include "maindlg.h"

CAppModule _Module;

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

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

    AtlInitCommonControls(ICC_COOL_CLASSES | ICC_WIN95_CLASSES);

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

    int nRet = 0;
    // BLOCK: アプリケーション実行
    {
        CMainDlg dlgMain;
        nRet = dlgMain.DoModal();
    }

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

    return nRet;
}
			

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

コントロール名 リソースID
プッシュボタン IDC_BUTTON_OPENDLG

 次に、stdafx.h内では、atldlgs.hヘッダをインクルードします。 atldlgs.hヘッダにはコモンダイアログ用クラスが定義されています。

 CMainDlgクラスでは、ボタン用のコマンドメッセージハンドラ OnButtonOpenDlg()を追加し、 そこでCCustomDlgクラスのインスタンスを作成して DoModal()によって独自のファイル選択ダイアログを表示します。

 最後に、CommDlg.cpp内でmaindlg.hヘッダの前にCustomDlg.hヘッダをインクルードします。