04.リストコントロールに行を追加する
今回は、リストコントロールに行を追加する方法です。具体的には、スライドパズルの問題として下記の内容の input.txt を用意し、それを読み込んでリストコントロールに表示します。
3,3,138046752 3,3,584370261 3,4,2941B3750A68 3,4,923160754A8B 4,4,41EC86709BA532FD 3,4,7BA3149=2650 3,4,91B6475=032A 3,5,=B0264A=5E3D9C7 3,5,=5BD7AE=4C90362
input.txtの各行は、スライドパズルの幅,高さ,初期状態を示します。初期状態は、0が空きパネル、1〜9, A〜Zの順に数字の1〜35を表します。ただし、通常のスライドパズルと違い移動できない壁があり=で表します。
それでは始めましょう。
1.スライドパズルの問題を保持するSPDataクラスを定義します。幅、高さ、初期状態を保持できるようにしました。
class SPData { public: SPData(int w, int h, const char *data) : m_Width(w), m_Height(h), m_Data(data) { } int GetWidth()const{return m_Width;} int GetHeight()const{return m_Height;} const std::string& GetData()const{return m_Data;} private: int m_Width; int m_Height; std::string m_Data; };
2.CSlidePuzzleDlg にinput.txtファイルを読み込むLoadInputFile関数と読み込んだ問題を保持するm_DataContainer変数を定義します。
// CSlidePuzzleDlg.h class CSlidePuzzleDlg { std::vector<SPData> m_DataContainer; BOOL LoadInputFile(const wchar_t *path); };
// CSlidePuzzleDlg.cpp BOOL CSlidePuzzleDlg::LoadInputFile(const wchar_t *path) { m_DataContainer.clear(); ifstream fi(path); if(!fi.is_open()){ return FALSE; } //input.txt の内容を読み込む vector<char> v(256); while(fi.getline(&v[0], v.size())){ const int w = atoi(&v[0]); const int h = atoi(&v[2]); const string s(&v[4]); SPData spd; if(!spd.Initialize(w,h,s)){ return FALSE; } m_DataContainer.push_back(spd); } return TRUE; }
3.m_DataContainerの内容をリストコントロールに反映するRefreshListCtrl関数を定義します。
void CSlidePuzzleDlg::RefreshListCtrl() { m_LC.SetRedraw(FALSE); m_LC.DeleteAllItems(); CString s; int num = 0; for(auto it = m_DataContainer.cbegin(); it != m_DataContainer.cend(); ++it, ++num){ s.Format(L"%d", num+1); const int nItem = m_LC.InsertItem(m_LC.GetItemCount(), s); s.Format(L"w=%d, h=%d, ", it->GetWidth(), it->GetHeight()); //文字コードを変換します。※1 { const string mbstr = it->GetData().c_str(); const int size = ::MultiByteToWideChar(CP_ACP, 0, mbstr.c_str(), -1, 0, 0); std::vector<wchar_t> buff(size+1, 0); ::MultiByteToWideChar(CP_ACP, 0, mbstr.c_str(), -1, &buff[0], (int)buff.size()); s += &buff[0]; } m_LC.SetItemText(nItem, 1, s); m_LC.SetItemText(nItem, 2, L""); } m_LC.SetRedraw(TRUE); }
※1 input.txtから読み込んだ文字列はマルチバイトの文字列です。MFC Feature Packは、wchar_t型のUTF-16の文字列を扱うので変換しています。
4.CSlidePuzzleDlgのOnInitDialog関数で、2と3で定義したメンバ関数を実行します。これでinput.txtを読み込んでからダイアログが表示されるようになります。
BOOL CSlidePuzzleDlg::OnInitDialog() { // ... 省略 //スライドパズルの問題を読み込みます。 LoadInputFile(L"input.txt"); //リストコントロールを更新します。 RefreshListCtrl(); return TRUE; }