1

I am trying to mimic the behavior of CString::LoadString(HINSTANCE hInst, DWORD id, WORD langID) without introducing a dependency on MFC into my app. So I walked through the source. The first thing it does is to immediately call AtlGetStringResourceImage(hInst, id, langID), and then this in turn contains the following line of code:

    hResource = ::FindResourceExW(hInst, (LPWSTR)RT_STRING, MAKEINTRESOURCEW((id>>4)+1), langID);

(It's not verbatim like this, but I trimmed out some unimportant stuff).

What is the meaning of shifting the ID by 4 and adding 1? According to the documentation of FindResourceEx, you should pass in MAKEINTRESOURCE(id), and I can't find any example code that is manipulating the id before passing it to MAKEINTRESOURCE. At the same time, if I make my code call MAKEINTRESOURCE(id) then it doesn't work and FindResourceEx returns null, whereas if I use the above shift + add, then it does work.

Can anyone explain this?

Zachary Turner
  • 738
  • 4
  • 24
  • 3
    String table resources are stored in groups of 16 based on the string ID. Shifting by 4 bits is essentially the same as dividing by 16. Raymond Chen has a great explanation on his blog. https://devblogs.microsoft.com/oldnewthing/20040130-00/?p=40813 – TheSteve Mar 25 '20 at 01:08
  • 3
    You don't need to fiddle with raw resources. [LoadString](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadstringw) does this for you already, as illustrated in [this](https://stackoverflow.com/a/33336980/1889329) answer. – IInspectable Mar 25 '20 at 06:34
  • 1
    Except LoadString doesn't take a language id, which I specifically need for my use case. LoadString instead uses the current thread locale. – Zachary Turner Mar 25 '20 at 19:12

1 Answers1

1

From the STRINGTABLE resource documentation:

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.

The code you are curious about locates the section a given string identifier is stored in by ignoring the low 4 bits.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23