Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Unicode Caption from Resource DLL String Table

I'm having trouble with Unicode characters being displayed incorrectly on my UI. I have a resource-only DLL containing a string table used for UI localization. I create the DLL in Delphi XE3 with a DLL-only project (just has {$R 'lang.res' 'lang.rc'} in the DPR file, and gives me lang.dll). I've verified that my lang.rc file is in UTF-8 format with Windows CRLF line breaks. When I load the strings from the DLL, Unicode characters are jumbled on the interface. Here are some details.

A snippet from the string table:

STRINGTABLE
{
59,"180˚"
60,"90˚ CW"
61,"90˚ CCW"
}

Here are code snippets that illustrate the problem I'm having with Unicode characters:

// explicitly assigning the degrees character shows 180˚ properly
ImageMenu180Action.Caption := '180˚'; 

// getting the resource from the DLL shows some weird two-character string for the degrees character
ImageMenu90CWAction.Caption := TLangHelper.LoadStr(IDS_ImageMenuRotationCW90);

// OutputDebugString shows the degrees character in the debugger output correctly
OutputDebugString(PChar('IDS_ImageMenuRotationCW90: '+TLangHelper.LoadStr(IDS_ImageMenuRotationCW90)));

Here is my Delphi function used for loading strings from the resource DLL:

class function TLangHelper.LoadStr(ResourceId: Integer):String;
var
   Buff: String;
   L: Integer;
begin
  Result := '';
  if LangDllHandle = 0 then begin
    LangDllHandle := LoadLibrary(LANGUAGE_DLL_LOCATION);
    if LangDllHandle = 0 then begin
      ShowMessage('Error loading language localization resources.');
    end;
  end;
  if LangDllHandle <> 0 then begin
    L := 1024;
    SetLength(Buff, L+1);
    LoadString(LangDllHandle, ResourceId, PChar(Buff), L);
    Result := String(PChar(Buff));
  end;
end;

Any suggestions?

FOLLOW-UP:

For Chinese characters, I had to add a preceding L to the string definitions in the .rc file so that the DLL compilation recognized them as Unicode. For example (English, Chinese Traditional, Chinese Simplified, French):

STRINGTABLE
{
35,"Status Bar"
1035,L"狀態欄"
2035,L"状态栏"
3035,"Barre d'état"
}
like image 934
spurgeon Avatar asked Nov 11 '14 20:11

spurgeon


1 Answers

I found a reference from 2002 indicating that you need to tell the resource compiler how the .rc file is encoded. For UTF-8, that's code page 65001, so you'd run this:

brcc32 -c65001 lang.rc

Then, of course, you'd remove the 'lang.rc' part from the $R directive in your code because you no longer want the IDE to invoke the resource compiler itself.

If your Delphi version is recent enough, then you can keep the full $R directive and instead set the -c65001 option in the resource-compiler configuration of your project options.

It's hard to know the encoding of a file just by looking at it. There can be many valid guesses. The -c option is documented, but the documentation doesn't mention when you'd need to use it, or what the IDE uses when it runs the resource compiler. The IDE probably just uses the default, the same as brcc32.exe, which is the system's default ANSI code page.

like image 105
Rob Kennedy Avatar answered Nov 12 '22 00:11

Rob Kennedy