Version 5.35
レジストリにいっぱい書き込もう!
「というわけで前回最後は、リストの中身を出力するっていうのでした」
『これをレジストリに書き込むようにするんだよね』
「その前に、 iNo の値を文字列に変換してみた方がいいんじゃない?」
『…… TRACE( "%d: %s\n", iNo, cDataStr ); 』
「そうじゃなくって。あ、でも近いか」
『そっか、 sprintf() 使えばいいんだよね』
「 Ver 5.07 ( No.072 ) でやってるね。あれと同じ」
『だから……』
void CFileTestDlg::OnDestroy()
{
CString cDataStr;
char chNo[10];
for( int iNo = 0; iNo < m_cFileCmbBox.GetCount(); iNo++ )
{
m_cFileCmbBox.GetLBText( iNo, cDataStr );
sprintf( chNo, "%d", iNo );
TRACE( "%s: %s\n", chNo, cDataStr );
}
CDialog::OnDestroy();
}
『数字を入れる配列を外に作って、 sprinf() で iNo を文字列化してその
配列に書き込みビルドして実行! うん、大丈夫そう』
「じゃ、最後はレジストリへの書き込み」
『えーっと、この前ので、"B" が chNo になるんだから……あ、 "A" はど
うしよ』
「履歴は英語だと History って言うことが多いかな」
『じゃ、 CWinApp::WriteProfileString() の第1引数は "History" 、第2
引数は chNo で。あ、今度は const 使おっと』
void CFileTestDlg::OnDestroy()
{
const int iCount = m_cFileCmbBox.GetCount();
const char chSection[] = "History";
CWinApp *pcWinApp = AfxGetApp();
CString cDataStr;
char chNo[10];
for( int iNo = 0; iNo < iCount; iNo++ )
{
m_cFileCmbBox.GetLBText( iNo, cDataStr );
sprintf( chNo, "%d", iNo );
pcWinApp->WriteProfileString( chSection, chNo, cDataStr );
}
CDialog::OnDestroy();
}
『えっと、リストの数と、 "History" に const 使ってみました。あ、でも
"History" は、もしかしてストリングテーブルに書いた方が良かったのかな』
「書き込む項目が増えたら特にね」
『あとは、さっきのと前回のと組み合わせただけだから大丈夫でしょ。ビル
ドしてテストして……レジストリ見て……おおっ、ちゃんと名前が 0 とか
1 とかでデータがリストの中身になってる!』
「じゃ、最後の仕上げにかかりましょう」
『? あと何かあったっけ』
「今書き込んだのを読み込まなきゃ意味ないでしょう!!」
『あ、そうだった。えーっとまず…… CFileTestDlg::OnDestroy() と逆に
ダイアログが作られるとき呼ばれるメンバ関数を見つけないと。計算機の時
は OnInitDialog() だったけど』
「今回もそれでいいよ。 CFileTestDlg::OnInitDialog() が呼ばれたときに
はもうダイアログができてるから」
『コンボボックスにアクセスできるのね。 CFileTestDlg::OnInitDialog()
の // TODO: のあとに書けばいいんだから、とりあえずさっきのをまんま貼
り付けて……』
「……」
『まず、最初なんだからリストは空、だから GetCount() の行はいらないで
しょ。他はそのままで…… GetLBText() は InsertString() かなんかに、
WriteProfileString() もたぶん ReadProfileString() とかあると思うから
それにして……あ! どうやって for を止めればいいんだろ』
「 ReadProfileString() ……じゃなくて、 CWinApp::GetProfileString()
っていうメンバ関数があるからそれ見てみて」
『えーっと、あ、見つからなかったら空の文字列が返るって書いてある!
これで for を止めればいいんじゃないかな。でも……』
「でしょう」
『なにが?』
「こういう風に、いっぺんにやろうとするから難しいわけ」
『少しずつ少しずつ! だね。えーっと、じゃあ for を取っ払ってひとつ
だけ読み込んでリストに追加してみよっと』
// TODO: 特別な初期化を行う時はこの場所に追加してください。
const char chSection[] = "History";
CWinApp *pcWinApp = AfxGetApp();
CString cDataStr;
char chNo[10];
sprintf( chNo, "%d", 0 );
cDataStr = pcWinApp->GetProfileString( chSection, chNo, NULL );
m_cFileCmbBox.AddString( cDataStr );
『さっきとだいたい同じ。 for を取っ払って WriteProfileString() に置
き換えて、よく考えたら後ろに追加してけばいいんだから GetLBText() は
AddString() に置き換え』
「うん、これでリストひとつだけ読み込むね」
『質問! GetProfileString() の戻り値が CString だったからそのまんま
CString で受けちゃったけど』
「うん、これでちゃんと受けられるよ。 CString は文字配列とかポインタ
みたいに難しいこと考えなくても使えるから」
『あと第3引数の LPCTSTR lpszDefault = NULL 、 = ってどういう意味?』
「これは〈デフォルト引数〉って言って、この引数を省略すると、 = の右
側が自動的に渡されます、ってこと」
『じゃ、 NULL はいらないんだ。それと…… CString が空だっていうのは、
あ、メンバ関数にあるのかな』
「あるよ、 IsEmpty() っていうのが」
『ホントだ! じゃこれを…… for ? iNo で止めるわけじゃないから
while の方がいいのかな』
「とりあえず試行錯誤してみて」
『うん、がんばる!』
10分経過……。
『はーっ、やっとうまくいくようになった!』
const char chSection[] = "History";
CWinApp *pcWinApp = AfxGetApp();
CString cDataStr;
char chNo[10];
int iNo = 0;
sprintf( chNo, "%d", iNo );
cDataStr = pcWinApp->GetProfileString( chSection, chNo );
while( !cDataStr.IsEmpty() )
{
m_cFileCmbBox.AddString( cDataStr );
++iNo;
sprintf( chNo, "%d", iNo );
cDataStr = pcWinApp->GetProfileString( chSection, chNo );
}
「うん、ちゃんとうまく動いてるね」
『そうでしょ。なんかさ、 while の前と中に同じのがしかも2行もあるっ
ていうのが私的には不満なのよね。それになんか難しかったし』
「難しかった?」
『そうなのよ! 最初、リストの一番上の行がふたつになっちゃって、
while の中の順番色々変えてやっとできたの!』
「 GetProfileString() が iNo の前に来てるとそうなっちゃうんだね。こ
れは while の前にも呼んでるから複雑になっちゃってるんだね」
『ね〜、水希ちゃんだったらどうするの?』
「僕だったら……」
BOOL CFileTestDlg::OnInitDialog()
{
// 略。
// TODO: 特別な初期化を行う時はこの場所に追加してください。
const char chSection[] = "History";
CWinApp *pcWinApp = AfxGetApp();
CString cDataStr;
char chNo[10];
int iNo = 0;
while( 1 )
{
sprintf( chNo, "%d", iNo );
cDataStr = pcWinApp->GetProfileString( chSection, chNo );
if( cDataStr.IsEmpty() )
{
break;
}
m_cFileCmbBox.AddString( cDataStr );
++iNo;
}
return TRUE;
}
『 while( 1 ) って、これじゃ無限ループ……あ、中の break で抜けるよ
うにしてるんだ』
「この方が分かりやすいかな。でも〈無限ループと break の組み合わせ〉
って嫌いな人も多いから多用するものじゃないかも」
『この辺って、なんかやり方いっぱいありそうだしね』
「さて、 Ver 5 は今回で最終回!」
『おお!! 35回って4分の3年よ!? 長すぎない?』
「それだけ中身が濃かったってことで。まず前半は、文字列とポインタにつ
いてじっくり見てみました」
『メモリの中身見て、どんな風になってるか調べたんだよね』
「文字列の後、ランタイムにちょっと触れてから、ファイル入出力」
『っつーかそれ、 iostream とランタイムと MFC と API って見て、結局
API を使ってるんだって話なんだよね』
「そこの部分は重要だからねー。 iostream とかのライブラリ使ってると、
なんか意味不明のもの使ってるみたいだけど」
『ライブラリだってちゃんとしたプログラム! 誰かが作ったものってこと
だよね』
「そゆこと。そのあとファイル読み込み関係のブラッシュアップ」
『細かい部分だよね。コツってゆーか』
「僕としては、こういうのの方が大事かも。本にあまり載ってないからね」
『それ強調するねー』
「そ、そう? で、 Ver 5 の後半はウィンドウについて」
『メッセージ送ったり、ボタン作ったり! このボタン作ったのってやっぱ
驚きかも』
「この辺も、プログラムってものを怖がらないって点で重要かもね。あと全
体的には、コンボボックスの使い方とかかな」
『 AddString が CComboBox にも CList にもあって、なんか MFC って結構
単純なのかなとか。さて、 Ver 6 はどうなるの?』
「 Ver 6 では、デバッグについて」
『うお、これまた難しそう!』
「火美ちゃんも自分でどんどんプログラム組むようになったみたいだけど、
どうしてもうまくいかない! とかあるでしょ」
『うんある。なんか謎のエラーが出ちゃったり』
「そういう部分をどうクリアしていくのかってことを紹介していきます!」
/*
Preview Next Story!
*/
『バグってゲーム用語だと思ってた』
「元々プログラミング用語だったのが一般に広まったんだね」
『そうだ! ゲーム教えてよ、ゲームの作り方!』
「げ、ゲーム!?(僕も作ったことないよ……)」
『ね〜教えてぇん?』
「というわけで次回」
< Version 6.01 バグってなに? >
『につづく!』
「い、 if と MessageBox() だけでできるでしょ?」
『そんな文章だけのなんかじゃなくって!』