(EDIT#2) // RC file:
STRINGTABLE
BEGIN
...
MY_ID "text text text"
...
END
Source:
hrsrc = FindResource(NULL, MAKEINTRESOURCE(MY_ID), RT_STRING);
// hrsrc is NULL on output`
I read this FindResource() function fails although resource exists and few other posts as well, but none gave me an answer.
My issue was FindResource of RT_STRING type (win32 api). Struggling with it 2nd day now. No matter what, it simply returns NULL for provided string resource IDs and following it, GetLastError returns 1814. Fun part is LoadStringW has nothing against and loads the strings. Head aching...
My test case. Set string resource id to 1 and make sure it's 1st in the stringtable (or #define MY_ID 1).
// RC file:
STRINGTABLE
BEGIN
1 "text text text"
...
END
Next call:
hrsrc = FindResource(NULL, MAKEINTRESOURCE(1), RT_STRING);
// hrsrc is 0xdeadbeef on output
Before editing I stated following strings should be 2..N which is wrong and will further lead FindResource to fail again.
I found (or actually overlooked) remarks section of STRINGTABLE resource man page. It states:
RC allocates 16 strings per section and uses the identifier value to determine which section is to contain the string. Strings whose identifiers differ only in the bottom 4 bits are placed in the same section.
So it appears to be "slotted".
MY_ID 1 = STRINGTABLE entry 1 // FindResource(NULL, MAKEINTRESOURCE(1), RT_STRING);
MY_ID 16 = STRINGTABLE entry 16 // FindResource(NULL, MAKEINTRESOURCE(2), RT_STRING);
MY_ID 32 = STRINGTABLE entry 32 // FindResource(NULL, MAKEINTRESOURCE(3), RT_STRING);
But how to reach the string with id 2?
(EDIT#3) Not a new land discovery but here's what I came up with, and what actually sums what Inspectable stated in own post.
const wchar_t * GetStringResource(int id){
union {
int slot;
int pick;
};
union {
HRSRC h;
wchar_t* entry;
};
slot = 1 + id / 16; // +1; FindResource(NULL, MAKEINTRESOURCE(0)... fails
h = FindResource(NULL, MAKEINTRESOURCE(slot), RT_STRING);
entry = (wchar_t*) LoadResource(NULL, h);
pick = id % 16;
for(int i=0 ; i < pick ; i++){
if(*entry==0) entry += 2; // 2 words, 1st size, 2nd empty string entry.
else entry += 1+ (unsigned short) *entry; // 1 word of length + length itself
}
return entry; // add +1 to skip the size...
}
Another issue is the string's are not NULL terminated. There's no direct use of them. Yes, LoadStringW is the answer. But...
Here is a rhetorical question. How is it any better than
std::map<unsigned short, const char *> myStringMap;
which already is cross-platform?
User contributions licensed under CC BY-SA 3.0