Tips of VC++ > ダイアログ > コモンダイアログボックスをカプセル化する
前へ戻る ★ 次へ進む ★


コモンダイアログボックスをカプセル化する

前回、MSDNの訳をやったら長く書きましたが、 コモンダイアログを使うにはやはりカプセル化してしまうのが便利です。 これを覚えるまでは関数を作っていましたが、値を取得とき不便でした。 クラスを作ってみると重宝で、今でもよく使います。
今回はその作ったクラスを中心に解説、というかクラスの紹介がメイン。

まず、ダイアログを表示するための関数ですが、次の二つの関数です。 パラメータにOPENFILENAME構造体を渡すだけ。 制御が返ってきたときに、構造体のメンバがいろいろ変更されているわけです。
戻り値が0であればキャンセルボタンが押さたことを示し、 0以外の場合がOKボタンの押されたことを示しています。

BOOL GetOpenFileName(
  LPOPENFILENAME lpofn   // 初期化データ
);

BOOL GetSaveFileName(
  LPOPENFILENAME lpofn   // 初期化データ
);

次に、あるととても便利なCCommDlgクラスの全貌を初公開。 クラスと言っても全部publicメンバで、 関数もコンストラクタを含めて二つしかないので 構造体と言ったほうが正しいかもしれませんが、一応クラスです。
誰かが作ったSTRLIBの中のCStringクラスを使っています。 STRLIBは ここからDLできるかもしれません。(忘れずにPR)

/*
 *  -------------
 *    commdlg.h
 *  -------------
 */


#ifndef __COMMDLG_H__
#define __COMMDLG_H__


class CCommDlg
{
public:
    strlib::CString m_Filter;
    DWORD           m_FilterIndex;
    strlib::CString m_File;
    strlib::CString m_FileTitle;
    strlib::CString m_InitialDir;
    DWORD           m_Flags;
    WORD            m_FileOffset;
    WORD            m_FileExtension;
    strlib::CString m_DefExt;

    CCommDlg();

    bool DoModal(int in_Type,HWND in_hParent);

};


#endif /* __COMMDLG_H__ */


/* * --------------- * commdlg.cpp * --------------- */ #include "stdafx.h" #include "commdlg.h" const int MAX_DLGTITLE = 30; const char title1[MAX_DLGTITLE] = "開く"; const char title2[MAX_DLGTITLE] = "名前をつけて保存"; CCommDlg::CCommDlg() :m_FilterIndex(0),m_Flags(0), m_FileOffset(0),m_FileExtension(0) { m_File.SetBufferSize(_MAX_PATH); m_FileTitle.SetBufferSize(_MAX_FNAME); } bool CCommDlg::DoModal(int in_Type,HWND in_hParent) { if ( in_Type!=1 && in_Type!=-1 ) return false; OPENFILENAME ofn; ::memset(&ofn,0,sizeof(OPENFILENAME)); strlib::CString filter(m_Filter); for ( int i=0 ; i<m_Filter.GetStrLength() ; ++i ) if ( filter[i]=='|' ) filter[i]='\0'; char title[MAX_DLGTITLE]; if ( in_Type==1 ) ::strcpy(title,title1); else ::strcpy(title,title2); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = in_hParent; ofn.hInstance = NULL; ofn.lpstrFilter = filter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = m_FilterIndex; ofn.lpstrFile = m_File; ofn.nMaxFile = _MAX_PATH; ofn.lpstrFileTitle = m_FileTitle; ofn.nMaxFileTitle = _MAX_FNAME; ofn.lpstrInitialDir = m_InitialDir; ofn.lpstrTitle = title; ofn.Flags = m_Flags; ofn.nFileOffset = m_FileOffset; ofn.nFileExtension = m_FileExtension; ofn.lpstrDefExt = m_DefExt; BOOL ret; if ( in_Type==1 ) ret=::GetOpenFileName(&ofn); else ret=::GetSaveFileName(&ofn); if ( ret ) { m_FilterIndex = ofn.nFilterIndex; m_InitialDir = m_File; m_FileOffset = ofn.nFileOffset; m_FileExtension = ofn.nFileExtension; } if ( ret ) return true; else return false; }

そんなに難しい関数ではないです。 DoModal関数を呼ぶことによってダイアログを表示します。 第一引数に1を渡すと[名前をつけて保存]ダイアログ、-1で[ファイルを開く]ダイアログが開きます。 ダイアログのタイトルのつけ方が謎ですね。 無意味なグローバル変数を使っていますが、このへんはパフォーマンスです。(何

大切なのはGetOpenFileNameなどの関数を呼び出した後に m_FilterIndexなど、ポインタでない構造体のメンバを クラスのメンバにコピーしないといけないことです。 忘れやすい点なので注意。