加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 使用DrawTextA,Courier New和日语语言环境的奇怪行为

发布时间:2020-12-15 09:12:40 所属栏目:大数据 来源:网络整理
导读:将DrawTextA与带有日语语言环境的Courier New-font结合使用时,我发现了一些奇怪的行为.请考虑以下Delphi XE2代码: procedure PaintTexts(aPaintBox: TPaintBox; aCharset: Byte);var A: AnsiString; S: string; R: TRect;begin aPaintBox.Font.Charset := a
将DrawTextA与带有日语语言环境的Courier New-font结合使用时,我发现了一些奇怪的行为.请考虑以下Delphi XE2代码:

procedure PaintTexts(aPaintBox: TPaintBox; aCharset: Byte);
var
  A: AnsiString;
  S: string;
  R: TRect;
begin
  aPaintBox.Font.Charset := aCharset;

  A := '[DrawTextA] The word "Japan" in Japanese: 日本';
  R := Rect(0,aPaintBox.Width,aPaintBox.Height);
  DrawTextA(aPaintBox.Canvas.Handle,PAnsiChar(A),Length(A),R,0);

  S := '[DrawTextW] The word "Japan" in Japanese: 日本';
  R := Rect(0,20,aPaintBox.Height);
  DrawTextW(aPaintBox.Canvas.Handle,PWideChar(S),Length(S),0);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintTexts(PaintBox1,DEFAULT_CHARSET);
end;

procedure TForm1.PaintBox2Paint(Sender: TObject);
begin
  PaintTexts(PaintBox2,SHIFTJIS_CHARSET);
end;

在此代码中,Form1包含两个绘图框(PaintBox1和PaintBox2). Form1的字体设置为Courier New,两个绘图框将ParentFont设置为True. Windows的非Unicode区域设置设置为日语(日本),因此它使用代码页932.

结果如下:

第一个paintbox使用Charset属性CHARSET_DEFAULT显示DrawTextA和DrawTextW调用的输出.这是字体的charset属性的默认值.请注意,传递给DrawTextA时,日语单词日本未正确显示.但是,DrawTextW完美地绘制了它.

第二个paintbox显示相同的文本,但只有Charset属性更改为SHIFTJIS_CHARSET.现在两个调用都显示正确的日文字符.但字体已更改为可变宽度字体!

当我将Form1的字体更改为Tahoma时,DrawTextA和DrawTextW都显示相同的正确文本.

当我的非Unicode语言环境设置为日语并且我的字体设置为Courier New时,有没有人知道为什么DrawTextA的行为与DrawTextW不同?

我一直认为Windows API的Ansi-和Wide版本之间的唯一区别是Ansi版本处理了与Unicode的转换.

我已尝试将其与Windows XP和Windows 7以及Delphi 7和Delphi XE2结合使用.所有组合都表现出相同的行为.

更新:
David Heffernan发表答案后,我开始阅读Micheal Kaplan’s blog.在那里我找到了a similar topic和more information about this topic.

解决方法

DrawTextA不会将文本转换为Unicode.相反,选定字体的字符集用于解释提供的文本.这确实比典型的A和W后缀API函数稍微复杂一些.

字体字符集的使用允许非Unicode程序以多个字符集显示文本.对于Unicode程序,这是一个完全没有问题,因为Unicode可以编码所有字符.

根据Michael Kaplan在this forum thread中的说法,不应该使用DEFAULT_FONTSET.他说:

Do not use DEFAULT_CHARSET at all. It is evil.

如果需要指定字符集,则应执行以下操作:

>调用GetACP以获取活动代码页.
>调用TranslateCharsetInfo传递代码页并指定TCI_SRCCODEPAGE标志.

返回的charset信息信息是用于活动代码页的相应字符集.把它包起来像这样:

function CharsetFromCP(CP: UINT): UINT;
var
  csi: TCharsetInfo;
begin
  Win32Check(TranslateCharsetInfo(CP,csi,TCI_SRCCODEPAGE));
  Result := csi.ciCharset;
end;

然后你可以写:

aPaintBox.Font.Charset := CharsetFromCP(GetACP);

当然,如果您知道文本是日文,那么您可以直接编写SHIFTJIS_CHARSET.更明显的是,您可以简单地使用Unicode API并避免所有这些废话.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读