iniファイルにはCWinApp::GetProfile系やWriteProfile系の関数を使って読み込んだり書き込んだりできますが、扱いたいデータが多くなると、似たようなコードを保存用と取得用に二種類書かないといけなくなって、面倒です。
そこで、これを1つにまとめる方法を考えてみました。
(読み書きしたい変数群を、一度しかコーディングしないところがミソ)
ここでは、ダイアログのデータをまとめてiniファイルにセーブ・ロードすることを目的とします。
ダイアログ上のエディットボックスやチェックボックス等のコントロールを、DDX(Dialog Data
eXchange)を使ってダイアログクラスのメンバー変数にすることは多いと思います。
そして その多くなった変数を扱うのが厄介なので…。
MyDlg.h:
class CMyDlg : public CDialog { 〜 void IniSave(){ IniSerialize(FALSE); } //iniファイルへ保存 void IniLoad(){ IniSerialize(TRUE); } //iniファイルから読み込み private: void IniSerialize(BOOL bLoad); 〜 }
MyDlg.cpp: [/2006-09-15]
#define INI_SECT "DATA" //CString読み書き用(オーバーロード) static void GetWriteProfile(CWinApp *pApp, CString &var, LPCTSTR name, BOOL bLoad) { if(bLoad){ var = pApp->GetProfileString(INI_SECT, name, ""); }else{ pApp->WriteProfileString(INI_SECT, name, var); } } //int読み書き用(オーバーロード) static void GetWriteProfile(CWinApp *pApp, int &var, LPCTSTR name, BOOL bLoad) { if(bLoad){ var = pApp->GetProfileInt(INI_SECT, name, 0); }else{ pApp->WriteProfileInt(INI_SECT, name, var); } } void CMyDlg::IniSerialize(BOOL bLoad) { CWinApp *pApp = AfxGetApp(); #define SERIALIZE(var) GetWriteProfile(pApp,var,#var,bLoad) SERIALIZE(m_edtData1); //エディットボックス(CString m_edtData1) SERIALIZE(m_edtData2); SERIALIZE(m_chkData1); //チェックボックス(BOOL m_chkData1) SERIALIZE(m_chkData2); #undef SERIALIZE }
iniファイルとの読み書き用にGetWriteProfileという関数を用意しました。
CStringやint用にオーバーロードされている(関数名は同じで引数の型だけ違う)のがポイントで、これにより、どういう型であっても呼び出す側は全く同じ形でコーディングできます。オーバーロード万歳!(笑)
また、CWinApp::GetProfile*やWriteProfile*では セクション(上記のINI_SECT)とエントリー(上記のname)が必要ですが、エントリー名についてはメンバー変数名をそのまま使っています。
SERIALIZEマクロの「#var」というのが、変数名を文字列に変換している箇所です。マクロの引数の先頭に「#」を付けると、変数ではなく文字列に展開されるのです。プリプロセッサ万歳!(笑)
SERIALIZE(m_edtData1)
↓
GetWriteProfile(pApp,m_edtData1,"m_edtData1",bLoad)
まあ、実際に書かれたiniファイルの中を見てしまうと、ちょっと変かもしれませんが…(苦笑)
なおかつ、GetWriteProfileへメンバー変数を渡すところは 参照渡し(引数の宣言で「&」を付けている)にしています。
これにより、関数の中で普通の変数に読み書きするのと同じコーディングで 呼び出し元の変数を読み書きできます。これはポインターを使っても実現できるけれど、こういう時は参照渡しの方が分かり易い。参照万歳!(笑)
上記の関数を実際に使うには、以下のようにします。
BOOL CMyDlg::OnInitDialog() { 〜 // TODO: 特別な初期化を行う時はこの場所に追加してください。 IniLoad(); //iniファイルからメンバー変数へ読み込み UpdateData(FALSE); //メンバー変数からダイアログのコントロールへ値をセット return TRUE; // TRUE を返すとコントロールに設定したフォーカスは失われません。 }
void CMyDlg::OnOK() { UpdateData(TRUE); //ダイアログのコントロールからメンバー変数へ値をセット IniSave(); //メンバー変数からiniファイルへ書き込み CDialog::OnOK(); }