iooiau.net

LoadString() の便利な使い方

LoadString() 関数はリソースから文字列を読み込む関数ですが、あまり知られていない[要出典]使い方があります。

LoadString() で文字列を読み込む際、通常は以下のように固定長のバッファを確保して読み込むことが多いと思います。


TCHAR szText[256];
LoadString(hInstance, IDS_TEXT, szText, sizeof(szText) / sizeof(TCHAR));

この場合、読み込む文字列の最大長が予め分かっていることが前提になります。
では、任意の長さの文字列を読み込むにはどうすればいいでしょうか。
LoadString() は戻り値でコピーした長さ(終端ナル文字を含まない)を返すので、バッファが不足していた場合はバッファを増やして再度読み込んでみるという方法もあります(そのようなことをしている例)
しかし、そんなことをしなくても直接的に文字列を読み込む方法があります。
LoadString() の最後の引数(バッファ長)を0にすると、リソースのデータへのポインタを直接返してくれます。


LPCTSTR pText;
int Length = LoadString(hInstance, IDS_TEXT, (LPTSTR)&pText, 0);
/* pText に長さ Length の文字列へのポインタが返ってくる */

この仕様を利用する上で二つ注意点があります。

一つ目は、返されたバッファに書き込みを行ってはいけません。
const なポインタを渡すようにしましょう。

二つ目は、ここで返ってくる文字列はナル終端されていません。
正確にいえば、リソーススクリプトに書いた文字列がそのまま返されるので、リソーススクリプトで明示的にナル終端していればナル終端されているし、そうでなければナル終端されていないということです。


STRINGTABLE
BEGIN
    1 "ナル終端されていない"
    2 "ナル終端されている\0"
END

これを見ると使いづらい感じがしますが、LoadString() で読み込んだ文字列を std::string などに詰めたい場合には便利に使えます。


LPCTSTR pText;
int Length = LoadString(hInstance, IDS_TEXT, (LPTSTR)&pText, 0);
// string のコンストラクタで指定する
std::basic_string<TCHAR> String(pText, Length);
// もしくは assign で代入する
String.assign(pText, Length);
// string_view にも入れられる
std::basic_string_view<TCHAR> View(pText, Length);