【问题标题】:What is the data type used for text properties?用于文本属性的数据类型是什么?
【发布时间】:2020-12-11 21:25:59
【问题描述】:

我正在从非常旧的 Builder 副本(> 15 年)中移植一些代码。在那些日子里,各种控件的 Text 属性都是AnsiString 类型的。似乎在最新版本的 C++Builder 中,情况不再如此。数据类型是什么?

我只能从帮助中得到TCaption,这是一种类型吗?

我的代码可以编译并运行,但在尝试使用简单的编辑框时,文本不是输入的内容,通常是“0”。 c_str() 有效,但给出了错误的值。

【问题讨论】:

  • 进一步寻求帮助是解决此类简单问题的正确做法。 Vcl.Controls.TCaption 清楚地告诉你:typedef System::UnicodeString TCaption;* 和 TCaption 是 Caption 属性的类型。 现在,你自己试试,查一下System.UnicodeString.c_str
  • 对于结果出乎意料的问题,您需要提供minimal reproducible example
  • 你不是说 AnsiString 吗?

标签: text properties c++builder vcl


【解决方案1】:

C++Builder 的 RTL 和 VCL 框架使用的默认字符串类型一直是当时 Delphi 的原生 String 类型。 TCaptionTFileName 等只是 String 的别名(但附加了不同的 RTTI,因此 IDE 的对象检查器可以区分它们)。

Delphi 的String 类型是Delphi 原生Char 类型元素的容器。

C++Builder 提供 System::CharSystem::String 别名来匹配 Delphi 的原生 CharString 类型:

  • 在 C++Builder 2007 和更早版本中,Delphi 的原生 Char 类型是 AnsiChar,因此 System::Char 是 C/C++ 的 char 的别名,System::StringSystem::AnsiString 的别名.因此,System::String 是一个 8 位 ANSI 字符串,String::c_str() 返回一个以 null 结尾的 char* 指针。

  • 在 C++Builder 2009 及更高版本中,Delphi 的原生 Char 类型是 WideChar,因此 System::Char 现在是 Windows 上 wchar_t 和 POSIX 上 char16_t 的别名,System::String 是现在是System::UnicodeString 的别名。因此,System::String 是一个 16 位 UTF-16 字符串,String::c_str() 分别返回一个以 null 结尾的 wchar_t*/char16_t* 指针。

因此,您拥有的任何在 C 样式字符串指针上运行的代码,而不是使用在 System::String 上运行的 RTL 功能,都必须进行相应的更新以从 ANSI 迁移到 UTF-16。

请参阅 Embarcadero 的 Unicode migration 在线资源。过渡对于 Delphi 用户大部分是透明的,但对于 C++ 用户来说往往需要更多的工作。

【讨论】:

  • 所有很好的答案,谢谢,看来我有一些研究要做。
【解决方案2】:

我认为您必须将代码迁移到 Unicode。 首先熟悉下一个资源:

  1. C++ 生成器和 Unicode https://community.embarcadero.com/index.php/blogs/entry/cbuilder-and-unicode-43342
  2. 将 C++Builder 项目迁移到 Unicode: https://www.youtube.com/watch?v=H-KFq5M0z0A&feature=emb_logo
  3. 迁移升级中心: https://www.embarcadero.com/rad-in-action/migration-upgrade-center

祝你好运

【讨论】:

【解决方案3】:

[免责声明]
所有“代码示例”均来自我的脑海,并未实际编译。

String 类型只是根据UNICODE 定义选择AnsiStringUnicodeString 类的宏。

之前,UNICODE 没有默认定义,所以使用了char,选择了AnsiString 类。今天UNICODE 是默认定义的,所以使用wchar_t,选择UnicodeString 类。这非常方便,因为 Windows API 现在默认为 Unicode。

还有其他几种类型,如WideStringUTF8String 等。它们都有大致相同的接口(因此可以互换)。因此.c_str() 根据所选的String 类返回不同的类型。

要迁移,您通常只需在所有常量字符串前面放置一个L,例如L"My unicode message"

应该只在极少数情况下特别需要 8 位 char。对于这些情况,您可以使用AnsiString() 进行转换。

String Foo = "This is Unicode";

Bar(AnsiString(Foo).c_str()); // AnsiString converts Foo into an 8bit char pointer.
Baz(Foo.c_str());             // Foo returns a wchar_t pointer.

Windows API 通常每个函数有两个版本,xxxxA 用于 Ansi 和 xxxxW 用于宽版本。如果省略结尾 AW,Windows 将根据 UNICODE 定义使用正确的版本。 W 版本要求您使用 L"My string",而 A 版本则不需要。 Microsoft 使用TEXT 宏:TEXT("Auto converted") 解决了这个问题。 TEXT 宏将根据UNICODE 定义将常量字符串转换为ansi 或wide。通过选择正确的 API 函数版本,此行将在 UNICODE 已定义或未定义的情况下正常工作。

MessageBox(TEXT("Auto converted string"),TEXT("TEXT MACRO"),0);

您可以通过将 A 或 W 附加到 API 函数名称来强制 Windows 使用 Ansi 或 Wide 版本。

MessageBoxA("This is the ansi version","MessageBoxA",0);
MessageBoxW(L"This is the wide version",L"MessageBoxW",0);

如果可能,我建议您将项目迁移为仅使用String,并在绝对需要时转换为AnsiString(例如调用仅接受8 位char 的库函数)。 char 在你的项目中默认应该是wchar_t(参见“project->Options->C++ Shared Options->_TCHAR maps to”)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-09
    • 2010-09-17
    • 2013-01-27
    • 1970-01-01
    • 2010-12-06
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多