Version 3.20
CString とストリングテーブル
「さて、前回はレジストリについて見てみました」
『レジストリにー、数字いれてー、取り出したんだよねー』
「その辺を書き出すと……」
// CCalcApp::InitInstance() の中。
SetRegistryKey( "KamichanFactory" );
dlg.m_iAns = GetProfileInt( "CalcDialog", "Ans", 0 );
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
WriteProfileInt( "CalcDialog", "Ans", dlg.m_iAns );
}
「となります」
『あれ、質問! SetRegistryKey() って WriteProfileInt() の前にもあっ
たと思うんだけど』
「 CWinApp::SetRegistryKey() でセットしたキーはちゃんと保存されてる
から、 CWinApp::WriteProfileInt() を呼んだときもちゃんと効いてるんで
す」
『つまり、最初に一度だけ呼んじゃえばいいってことね』
「そゆこと」
『もひとつ、 TODO のコメントのとこって消しちゃっていいの?』
「いいんじゃないかな。あのコメントの意味は分かるでしょ?」
『うん、 OK ボタンを押したら、戻り値がどーたらこーたらして、この中
カッコの中に入るってことだもんね、まー分かっちゃえばなくてもいっか』
「それじゃあ、今日の本題。もしうっかり」
WriteProfileInt( "CalcDialog", "Ams", dlg.m_iAns );
「なんてなったらどうしましょう」
『……どっか違うの?』
「 "Ams" になってるでしょ!」
『あ、ホントだ』
「こういうミスは、プログラムが大きくなればなるほど多くなるし、見つけ
るのも大変」
『というわけで?』
「今回は、このまえ見た〈ストリングテーブル〉の使い方について見てみま
しょう」
『あ、あれを使うんだ!』
「まずは CWinApp::SetRegistryKey() のから。リソースビューからストリ
ングテーブルを開いて」
『はーい。ワークスペースの ResourceView の String Table をダブルクリ
ック! はい開いたよー、あ、前の〈バージョン情報じゃ!〉のままだ』
「直しておいた方がいいかも……。で、 IDS_ABOUTBOX の下に点線で囲んで
るのがあるでしょ。それを」
『ダブルクリック! あ、プロパティ出た』
「まず【 ID 】から。今回は IDS_REG_COMPANY にしましょう」
『その意味は?』
「 ID で String で Registry で会社名だから」
『まんまねー』
「だからこーゆーのはまんまの方がいいんだって」
『そっか。で、キャプションは?』
「【キャプション】は KamichanFactory だってば」
『 SetRegistryKey() に渡すのなんだもんね』
「そういうこと。そしたらプログラムに戻って」
『えーっ!!』
「なんやねその非難ごーごーは」
『言ってみただけ。やっぱ SetRegistryKey() まわり書き換えるの?』
「そういうこと。 SetRegistryKey() の行と、その前2行を……」
CString cCompanyStr;
cCompanyStr.LoadString( IDS_REG_COMPANY );
SetRegistryKey( cCompanyStr );
「って感じに書き換えて」
『……やっぱむずかしーね』
「だから〈えーっ!!〉?」
『分かる人にはこの苦労分かんないわよっ!』
「……〈君は労せず理解できたんだよね〉って思われるのはやだな」
『うっ』
「はっきり言うよ。火美ちゃんは僕の100分の1の労力でマスターできる
はず!」
『ってそれ自慢してない?』
「かもね。じゃ、プログラム見ていきましょう。1行目は?」
『んー、 CString って前に見たよね、確か文字とか使うためのクラス』
「そうそう。頭文字が C でしょ、これは MFC のクラスのあかし」
『あ、 CDialog とか CWinApp とかもそうだもんね』
「 CString も MFC のクラスのひとつ、文字列を操作するためのクラス。1
行目はこの CString 型の変数を作ってます」
『変数を作る、っていうのがクラスには必ず必要なんだね』
「そういうこと。クラスは鋳型、変数は実物。文字列を格納するためには、
変数として作らなきゃいけないわけ」
『それが cCompanyStr なんだ。で、2行目は、 CString::LoadString() っ
てメンバ関数を使ってるんだよね。レッツMSDN!』
LoadString をダブルクリックし F1 キーを押す。【該当するトピック】
ダイアログが表示される。
『あ、 API にも LoadString() ってあるんだ』
「ストリングテーブルはウィンドウズのものだから、 MFC 使わなくてもも
ちろん操作できるわけ。でも」
『 CString 使った方が楽ってことねー。んじゃ CString::LoadString() を
ダブルクリック』
MSDNの CString::LoadString() のページが開く。
『なんか簡素。あ、使用例がある! でもなんか複雑?』
「エラー処理はあとに回して、引数は?」
『えーっと、文字列リソースの ID だって。文字列リソースってストリング
テーブルのこと?』
「そう。ってことは?」
『 ID ってことはさっきの……あ、だから IDS_REG_COMPANY なんだ』
「【解説】に書いてあるとおり、この ID で指定した文字列をさっき作った
cCompanyStr の中に書き込みます」
『ここに書いてある〈オブジェクト〉って?』
「これは〈変数〉って読み替えていいかな。ホントはもっと広い意味なんだ
けど」
『広いって?』
「たとえば、ウィンドウズ上のウィンドウとかも〈オブジェクト〉のひとつ」
『ウィンドウってことは HWND の変数のこと?』
「ううん、ウィンドウズの中に、ウィンドウの情報が入ってるの。それがオ
ブジェクト。 HWND はそのオブジェクトを操作するためのものってことだね」
『なんかむつかしいかも……』
「確かにね。ま、今のところは変数ってことで」
『はーい。で、 cCompanyStr に IDS_REG_COMPANY にあたる文字列が入るか
ら、それを SetRegistryKey() に渡してるってことねー3行目』
「そういうこと。んじゃチェックしてみて」
『はーい。ビルドして実行! あ、答にさっきの数字が入ってる。ってこと
はちゃんと会社名があってるってことだよね』
「あってるってこと。こういうチェックをちゃんとすることが大切だから」
『はーい。で、他のもするの?』
「もちろん。自分でしてみて」
『う”、難しそう……』
「こういうのは聞くだけじゃなくて、ちゃんと自分で試すことが大事」
『分かってますよーだ。えーっと、まずストリングテーブルを開いて……』
「……と、皆さんには答を見てもらいましょう。まずストリングテーブルは、
こんな感じになります」
IDS_REG_COMPANY KamichanFactory
IDS_REG_DIALOG CalcDialog
IDS_REG_ANS Ans
『そーいえば【値】ってどーでもいーの?』
「どうでもいいの。大事なのは IDS_REG_COMPANY とかの文字列の方だから」
『はーい』
「で、プログラムの方は」
// CCalcApp::InitInstance() の中。
CString cCompanyStr;
cCompanyStr.LoadString( IDS_REG_COMPANY );
CString cDialogStr;
cDialogStr.LoadString( IDS_REG_DIALOG );
CString cAnsStr;
cAnsStr.LoadString( IDS_REG_ANS );
SetRegistryKey( cCompanyStr );
dlg.m_iAns = GetProfileInt( cDialogStr, cAnsStr, 0 );
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
WriteProfileInt( cDialogStr, cAnsStr, dlg.m_iAns );
}
『うん、変数名違っちゃったけど、だいたい同じかな』
「ま、本当はもーっとシンプルにしたいんだけど、今の知識だとこれが限界
かな」
『シンプルって?』
「たとえば、今の状態だと cDialogStr と cAnsStr を逆に渡したりしかね
ないからね」
『そういうのも考えなきゃいけないんだ……。そういえばさ、こうやってす
れば、最初言ってた "Ams" な間違いってなくなるの?』
「もちろん。たとえば cAnsStr を cAmsStr にしたら……」
『あ、ビルドしたらエラーになっちゃった』
「 cAmsStr なんて変数作ってないからね。同じく IDS_REG_ANS を
IDS_REG_AMS にしても」
『エラー。ストリングテーブルに IDS_REG_AMS なんてないもんね』
「こうすることで、ミスの起きやすさを大幅に減らせた」
『けど限界はある、と』
「そういうこと。それにね、色々問題もあってね」
『どゆこと?』
「火美ちゃんから見て、この新しいプログラムと古い方のと、どっちが分か
りやすい?」
『そりゃ前のでしょ。レジストリのキーにする文をそのまま渡してるんだか
ら』
「そうなんだよね。安全策を採ろうとすると、どうしても【距離が離れる】
ことになるから」
『どゆこと?』
「上の例だと、文字列をストリングテーブルに置いて、 CString を間に挟
んだことで安全性を増したわけ。つまり安全性を上げるためには」
『間に何か入れなきゃいけないってことね。つまりアレみたいなもん?』
「……まあそうだけど……」
『そうなの?』
「つ、つまり、距離を置いたおかげで安全性は増したけど、プログラムとし
ては、 cCompanyStr には IDS_REG_COMPANY が入ってる、 IDS_REG_COMPANY
はストリングテーブルの KamichanFactory って追って見る必要があるわけ」
『じゃーアレとは違うじゃん』
「うー、まあそうだねぇ」
『ようするにさ、プログラムが見にくくなるってこと?』
「そういうことになるかな。直感的じゃなくなるんだね」
『あー、じゃあアレと同じかも』
「と、とにかくっ、こういうデメリットはあるけど、プログラムの安全性を
考えても、ストリングテーブルを使って処理しましょうってことで」
『みんなも使ってねー』
/*
Preview Next Story!
*/
「……」
『ほらそんな怒んないで。アメあげる』
「アメ?」
『ほら』
「……」
『というわけで次回』
< Version 3.21 イベントハンドラ >
「につづく!!」
『元気になった?』
「……」