In a Delphi XE7 project for building an ocx I have an rc-file with Russian strings for the company name, file description etc. When I open the Properties window of the resulting ocx the Russian strings are not displayed correctly (there are strings of garbage characters due to an incorrect encoding). I have tried to convert the rc-file to Windows-1251, UTF-8 and UTF-16 encodings, then tried to specified the corresponding file encoding via the #pragma code_page directive in the rc-file, then removed #pragma and specified the encoding in the project in the section of the resource compiler. In all cases I changed the VALUE "Translation" string accordingly. Nothing of the above worked for me. What is the correct way of writing and compiling an rc-file in Delphi XE7 such that the localized strings appear correctly in the Properties window?
Note 1. I build the ocx on a build server which Delphi XE7 was simply copied to (and BDS* environment variables set manually) rather than properly installed from a distributable.
Note 2. For information my rc-file follows (the #pragma version for Windows-1251).
#pragma code_page(1251)
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
1 VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 2,0,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
{
BLOCK "041904E3"
{
VALUE "CompanyName", "ИмяКомпании\000"
VALUE "FileDescription", "ИмяМодуля\000"
VALUE "FileVersion", "2.0.0.0\000"
VALUE "InternalName", "Tools\000"
VALUE "LegalCopyright", "Copyright\251 2010-2014\000"
VALUE "LegalTrademarks", "\000"
VALUE "OriginalFilename", "Tools.ocx\000"
VALUE "ProductName", "ИмяПродукта\000"
VALUE "ProductVersion", "2.0.0.0\000"
VALUE "Comments", "No Comments\000"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 1049, 1251
}
}
Related
I am migrating from an old version of Borland C++ to the newest. In my code I had used String (AnsiString). In the new compiler it does not recognize String or AnsiString as a valid type, so I put in vcl.h in the file where I use String. Now I get 103 errors, all saying "reference to byte is ambiguous" (various system .h files). Is vcl.h not the header for AnsiString?
thanks
The actual header file that defines AnsiString is dstring.h, and always has been (the header file that defines UnicodeString is ustring.h). The System::String alias is defined in sysmac.h.
vcl.h includes these headers for you. If you are getting errors, either you did not create a VCL project properly to begin with, or your project is misconfigured.
I'm using Delphi 10.0 Seattle on a machine with Windows 10.
We have a system that has several executables. We use the version information via .rc file:
1 VERSIONINFO
FILEVERSION 18,2,0,1660
PRODUCTVERSION 18,2,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS (VS_FF_SPECIALBUILD|VS_FF_PRERELEASE)
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041604E4"
BEGIN
VALUE "CompanyName", "BLA BLA BLA\0"
VALUE "FileDescription", "BLA BLABLA - DESCRICAO\0"
VALUE "FileVersion", "18.2.0.1660\0"
VALUE "InternalName", "nomexecutavel.exe\0"
VALUE "LegalCopyright", "Copyright 2018\0"
VALUE "LegalTrademarks", "BLA BLA BLA é marca registrada\0"
VALUE "OriginalFilename", "nomeexecutavel.exe\0"
VALUE "ProductName", "nomedoproduto\0"
VALUE "ProductVersion", "18.2.0\0"
VALUE "SpecialBuild", "Para Homologação\0"
VALUE "GitRevision", "790d79ee92af023d6beac953072c45b0385df17f\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0416, 1252
END
END
This .rc file is compiled through brcc32.exe.
In the project file the .RES file information generated by brcc32 is loaded.
{$R VersionInfoFactor.res}
After I do the build and install on a Windows machine in Portuguese, I can view the version information by right-clicking on the executable, selecting Properties, then Details.
So far, this is nothing new, it shows the data that is informed in the .rc file.
Now, if I install this same executable on a Windows machine in another language, I can no longer view this information.
Would anyone know the cause?
Your resource script provides version info for ONLY Portuguese and no other language. So, of course, a non-Portuguese machine won't display anything meaningful.
You need to provide multiple StringFileInfo blocks, one for each language you want to support. And you should have a block for US English, which is the fallback when a block for a specific language is not provided.
You should organize the blocks in this order, per Hierarchical Organization of Resources for Localization:
US English
Neutral cultures
Specific cultures
On a side note, you don't need to invoke brcc32.exe manually. The Delphi compiler can do that for you, if you include the .rc filename in the {$R} directive:
{$R VersionInfoFactor.res VersionInfoFactor.rc}
Some of resources from .RC file are not available in resulting .exe with the ID's given in .RC file.
I have and RC file with resourcestrings with id's 10000, 10100 etc. At some reason, when I load resource with id 10000 (LoadStr(10000)) it loads another string ('Invalid field type.' - which is declared in midas.rc from VCL and has the same id).
I assumed that resources with the same id should lead to "[Error] WARNING. Duplicate resource(s)" during the build. But there is no linker-related warnings.
p.s. I'm using Delphi 2010.
Update:
Workaround on that issue is to change id from 10000 to something else. 10050, e.g.
Question:
Why there's no warnings on duplicate resources?
What could be done to prevent that problem in future?
myproject.inc
const
offLanguages = 10000;
offCurrencies = 10100;
myproject.RC file
LANGUAGE LANG_LATVIAN, SUBLANG_NEUTRAL
#include "myproject.inc"
STRINGTABLE
{
offLanguages+0, "LV"
}
.. etc...
Rc file is compiled to myproject.res file. And the resulting .res files has correct string "LV" with ID 10000 (I checked that with resource editor).
In delphi coude resources are loaded in unit's initialization part, using LoadStr function.
likeThat.pas:
unit likeThat;
interface
{$I *.inc}
{$R *.res}
// skipped
initialization
Assert(LoadStr( offLanguages )= 'LV'); // <== fails here
I need to create a IdMessage with Unicode subject (eg "本語 - test")
I have tried setting it using
Msg.Subject := UTF8Encode(subject);
where subject is a WideString containing the text above
but when I look at the encoded subject (by saving the Message to file) it looks like this:
Subject: =?UTF-8?Q?=C3=A6=C5=93=C2=AC=C3=A8=C2=AA=C5=BE?= - test
instead of
Subject: =?UTF-8?Q?=E6=0C=AC=E8=AA=9E?= - test
and Outlook displays it as "本語 - test"
Any pointers as to where I am going wrong?
Delphi 2006 (pre-unicode), Indy 10 (fairly recent from source)
In pre-Unicode versions of Delphi, where everything is based on AnsiString, the value you assign to the TIdMessage.Subject property (and any other AnsiString property of TIdMessage, for that matter) MUST be encoded using the OS default character encoding. You are encoding it to UTF-8 instead, which will not work. This is because TIdMessage will first decode the Subject value to Unicode using the OS default encoding, then MIME-encode the Unicode data using the encoding parameters provided by the TIdMessage.OnInitializeISO event, or defaults if no event handler is assigned (in this case, those parameters are CharSet=UTF-8 and HeaderEncoding=QuotedPrintable). TIdMessage has no mechanism to allow you to specify the encoding used for any AnsiString data you assign to it. So the only possibility to send a value of '本語 - test' with the Subject property is to assign your source WideString as-is to the property and let the RTL convert the data to AnsiString using the OS default encoding:
Msg.Subject := subject;
However, if the OS does not support the Unicode characters being used, there will be data lost. There is no avoiding that in this scenario.
The alternative is to set the Subject property to a blank string and then use the TIdMessage.ExtraHeaders property instead so that you can provide your own header value that will be put into the email as-is. Using this approach, you can call Indy's EncodeHeader() function directly. In pre-Unicode versions of Delphi, it has an optional ASrcEncoding parameter that defaults to the OS default encoding (TIdMessage does not currently provide a value for that parameter when encoding headers):
uses
..., IdCoderHeader;
Msg.Subject := '';
Msg.ExtraHeaders.Values['Subject'] := EncodeHeader(UTF8Encode(subject), '', 'Q', 'UTF-8', IndyTextEncoding_UTF8);
This way, EncodeHeader() will be able to avoid a redundant conversion because it can detect that the source and target character encodings are both UTF-8, and thus just MIME-encode the source UTF-8 data as-is. Worse case, even if it did not detect the character encodings were the same, it would simply decode the source data to Unicode using UTF-8 and then re-encode it back to UTF-8. Those are lossless conversions, so no data is lost.
And FYI, the correct encoding for the Unicode characters you have shown would be:
Subject: =?UTF-8?Q?=E6=9C=AC=E8=AA=9E?= - test
Not
Subject: =?UTF-8?Q?=E6=0C=AC=E8=AA=9E?= - test
As you have shown. Notice the second encoded octet is 9C instead of 0C.
I am building Delphi Projects from the command line and am using brcc32.exe to build the .res files.
I have added a number of custom strings to my .RC so it looks like this. (There is a little Delphi5 app that prepares this .RC from a template)
1 VERSIONINFO
FILEVERSION 999,0,0,339
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904E4"
BEGIN
VALUE "FileDescription","Debug Build"
VALUE "FileVersion","999.0.0.339"
VALUE "LegalCopyright", "HuwCorp Finance Ltd"
VALUE "Revision","339"
VALUE "LastChangeRevision","335"
VALUE "LastChangeDate","2013-06-07"
VALUE "LastChangeTime","13:17:14"
VALUE "LastChangeAuthor","foo1234"
VALUE "BuildDate","12/06/2013"
VALUE "BuildTime","10:36:59"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 2057, 1252
END
END
All well and good so far, but the BRCC32 step produces a mangled .res file that looks like this (Viewed through a resource Builder)
VALUE "LastChangeDate", "2013-06-074\x08\x01LastChangeTime"
VALUE "LastChangeTime", "13:17:146\x07\x01LastChangeAuthor"
VALUE "LastChangeAuthor", "foo1234"
VALUE "BuildDate", "12/06/2013,\x08\x01BuildTime"
VALUE "BuildTime", "10:36:59D"
And indeed clicking properties/Version on the built .exe shows the garbage characters e.g. BuildTime is displayed as 10:36:59D
Can anyone suggest why ?
StringTable resources need to be C-style null-terminated (even when using the Borland Resource Compiler).
Try this instead:
VALUE "FileDescription","Debug Build\0"
VALUE "FileVersion","999.0.0.339\0"
VALUE "LegalCopyright", "HuwCorp Finance Ltd\0"
VALUE "Revision","339\0"
VALUE "LastChangeRevision","335\0"
VALUE "LastChangeDate","2013-06-07\0"
VALUE "LastChangeTime","13:17:14\0"
VALUE "LastChangeAuthor","foo1234\0"
VALUE "BuildDate","12/06/2013\0"
VALUE "BuildTime","10:36:59\0"