MS Visual Studio 2015 Enterprise; C ++。
在我的控制台项目中,我添加了RC文件(即资源)并在其中添加了两个字符串:
我为获取字符串编写了这样的函数:
PCTSTR LoadString(HMODULE h, DWORD id) {
h = NULL == h ? GetModuleHandle(NULL) : h;
PTSTR copyright = NULL;
LoadString(h, id, (PTSTR)©right, 0); // This is WinAPI function
return copyright;
}
现在我尝试在我的代码中使用它:
// Set necessary locale
PCTSTR lang = LoadString(NULL, IDS_STRING_LOCALE);
_wsetlocale(LC_ALL, lang);
// Print copyright info
PCTSTR copyright = LoadString(NULL, IDS_STRING_COPYRIGHT);
if (NULL != copyright) {
// TODO: unexpected string output is here!
wcout << copyright << endl;
}
else {
DWORD errorCode = GetLastError();
lang
变量的值为Russian_Russia.1251
,但copyright
变量的Hello, World!Russian_Russia.1251
代替Hello World!
。
为什么会这样?
答案 0 :(得分:3)
PTSTR copyright = NULL; LoadString(h, id, (PTSTR)©right, 0); // This is WinAPI function
您正在调用传递LoadString()
的Win32 0
函数作为最后一个参数的值。您可以从MSDN documentation of LoadString()
读取,当最后一个参数为0时:
[...]如果此参数为0,则lpBuffer接收指向资源本身的只读指针。
因此,从LoadString()
成功返回后,代码中的copyright
指针由LoadString()
设置为指向字符串资源本身。
但是,字符串资源默认 NUL终止;它们的长度是前缀。
因此,由于您的字符串未终止NUL,因此当您使用wcout
进行打印时,也会打印版权字符串后面的字符。所以你得到了整个Hello, World!Russian_Russia.1251
字符串。
要解决这个问题,您可以从资源加载的字符串中构建std::wstring
,而不是使用原始的类C字符串指针,只需将其与wcout
一起使用即可。请注意,资源字符串的长度是LoadString()
的返回值
For example:
std::wstring LoadStringFromResource(
_In_ UINT stringID,
_In_opt_ HINSTANCE instance = nullptr )
{
WCHAR * pBuf = nullptr;
int len = LoadStringW(
instance,
stringID,
reinterpret_cast< LPWSTR >( &pBuf ),
0 );
if( len )
return std::wstring( pBuf, len );
else
return std::wstring();
}
或者您可以使用ATL / MFC中的 CString
类及其方便的方法(CString::LoadString()
overloads)或proper constructor overload从资源加载字符串。
在这种情况下,LoadString()
调用的复杂性隐藏在CString
的实现之下。
答案 1 :(得分:0)
如果显式空终止资源字符串,则资源字符串仅以空值终止。为了使您的代码(假定为null终止)起作用,您应该对字符串进行空终止。在.rc文件中,而不是
"Hello, World!"
写
"Hello, World!\0"
答案 2 :(得分:-2)
哦,我修好了我的代码。现在它工作正常:
PTSTR LoadString(HMODULE h, DWORD id) {
h = NULL == h ? GetModuleHandle(NULL) : h;
PTSTR ptr = NULL;
// it returns really length instead of concatenated
// string length, therefore I can use it for malloc.
int i = LoadString(h, id, (PTSTR)&ptr, 0);
if (0 == i) {
return NULL;
}
PTSTR string = (PTSTR)malloc((i + 1) * sizeof(TCHAR));
LoadString(h, id, string, i + 1);
return string; // don't forget free resource in the outer code.
}
资源中的字符串不会像我预期的那样通过\0
字符分隔。