如何在 Visual C++ 2010 中打开资源字符串?
Posted
技术标签:
【中文标题】如何在 Visual C++ 2010 中打开资源字符串?【英文标题】:How do you open a resource string in Visual C++ 2010? 【发布时间】:2011-07-16 21:12:15 【问题描述】:我在 Visual C++ 中创建了一个基本的字符串表资源。我正在尝试访问该资源。但是,我的程序似乎找不到资源。这里:
int main(int argc, char* argv[])
HRSRC hRsrc;
hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDS_STRING102), RT_STRING);
if (hRsrc == NULL)
printf("Not found\n");
else
printf("Found\n");
这个程序找不到资源并且总是返回 null。
我创建了一个简单的位图资源,这个新程序可以很好地识别它。这里:
int main(int argc, char* argv[])
HRSRC hRsrc;
hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
if (hRsrc == NULL)
printf("Not found\n");
else
printf("Found\n");
这会找到位图。
stringtable 资源的处理方式是否有所不同?
【问题讨论】:
Updating a string table with UpdateResource 解释了字符串表是如何实现的。 Win32 LoadString wrapper 提供了一个不需要您了解这些内部结构的解决方案。 【参考方案1】:假设您不想使用 LoadString() 这应该会有所帮助...
在使用 FindResource() 和 FindResourceEx() 时,字符串和字符串表的处理方式确实不同。来自this KB文章:
字符串资源存储为字符串块。每个块可以有 最多十六个字符串,代表最小粒度 可以加载/更新的字符串资源。每个块都被识别 通过标识符 (ID),从一 (1) 开始。我们使用此 ID 时 调用 FindResource、LoadResource 和 UpdateResource 函数。
具有 ID 的字符串 nStringID 位于具有 ID 的块中, nBlockID,由以下公式给出:
nBlockID = (nStringID / 16) + 1; // 注意整数除法。
nStringID 的低 4 位指示块中的哪个条目包含实际字符串。一旦你计算出要传递给 FindResource() 的块 ID 和存在字符串的块中的索引,你必须扫描它的内容以找到你正在寻找的字符串。
以下代码应该可以帮助您入门。
const WCHAR *stringPtr;
WCHAR stringLen;
// Get the id of the string table block containing the target string
const DWORD blockID = (nID >> 4) + 1;
// Get the offset of teh target string in the block
const DWORD itemID = nID % 0x10;
// Find the resource
HRSRC hRes = FindResourceEx(
hInst,
RT_STRING,
MAKEINTRESOURCE(blockID),
wLanguage);
if (hRes)
HGLOBAL hBlock = LoadResource(hInst, hRes);
const WCHAR *tableDataBlock = reinterpret_cast<LPCWSTR>(LockResource(hBlock));
const DWORD tableBlockSize = SizeofResource(hInst, hRes);
DWORD searchOffset = 0;
DWORD stringIndex = 0;
// Search through the section for the appropriate entry.
// The first two bytes of each entry is the length of the string
// followed by the Unicode string itself. All strings entries
// are stored one after another with no padding.
while(searchOffset < tableBlockSize)
if (stringIndex == itemID)
// If the string has size. use it!
if (tableDataBlock[searchOffset] != 0x0000)
stringPtr = &tableDataBlock[searchOffset + 1];
stringLen = tableDataBlock[searchOffset];
// Nothing there -
else
stringPtr = NULL;
stringLen = 0;
// Done
break;
// Go to the next string in the table
searchOffset += tableDataBlock[searchOffset] + 1;
// Bump the index
stringIndex++;
【讨论】:
知识库条目脱机。这是最新的archive.org snapshot。【参考方案2】:您可以直接使用LoadString
。这是 MSDN FindResource
文档中的一些文本...
应用程序可以使用 FindResource 来查找任何类型的资源,但仅当应用程序必须通过随后调用 LoadResource 然后调用 LockResource 来访问二进制资源数据时才应使用此函数。
立即使用资源...
...使用加载字符串!
【讨论】:
如果你必须使用FindResource
作为字符串,那么你需要传入ID MAKEINTRESOURCE((IDS_STRING102>>4)+1)
。 LoadString
更易于使用,然后... FindResource
不是为直观的字符串加载而设计的。 :(【参考方案3】:
经过 2 天的研究,我发现了这个(它有效!):
#include <atlstr.h>
......
ATL::CString str;
WORD LangID = MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT);
str.LoadString(NULL,IDS_STRING101, LangID);
【讨论】:
以上是关于如何在 Visual C++ 2010 中打开资源字符串?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual C++ 2010 中使用 C++ 库 [重复]
我用 Microsoft Visual Studio 2010 新建一个 C++ 的对话框窗口程序的时候 该如何设置它的窗口类名?谢谢!
visual studio 2010 一个解决方案里有多个c++源文件 怎么只执行其中一个?