在WinForms中使用Graphics.DrawString旋转后,中文竖排文本显示不正确

编程语言 2026-07-07

在WinForms应用中使用 Graphics.DrawString 搭配 StringFormatFlags.DirectionVertical 来渲染中文文本,然后应用旋转变换,文本会以出人意料的方向和阅读顺序显示。

预期的行为是文本在逻辑上保持有序,并作为竖向字符串可读,同时整块文本作为一个整体旋转。相反,单个CJK字形会以被旋转和/或重新定位的方式出现,改变了原本的视觉呈现,甚至可能影响含义。

这似乎与 System.Drawing / GDI+的底层文本渲染行为有关,而不是某个特定的WinForms控件。

此问题在.NET Framework与 .NET Core / .NET下均存在。

屏幕截图:

实际输出:

实际输出

预期输出:

预期输出

字母输出:

字母输出

简单示例:

示例已附在那个GitHub查询中:https://github.com/dotnet/winforms/issues/14698

代码片段:

private void Canvas_Paint(object sender, PaintEventArgs e)

  {

      if (!_showRotatedText)
          return;

      var g = e.Graphics;

      g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

      g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

      var text = _input.Text ?? string.Empty;

      var sf = new StringFormat(StringFormat.GenericTypographic)
      {
          Alignment = StringAlignment.Center,
          LineAlignment = StringAlignment.Center,
          FormatFlags = StringFormatFlags.DirectionVertical
                        | StringFormatFlags.NoWrap,
          Trimming = StringTrimming.EllipsisCharacter,
      };

      using (var font = new Font("Microsoft YaHei", 12, FontStyle.Bold))
      using (var brush = new SolidBrush(Color.FromArgb(64, 64, 64)))
      {
          var r = _canvas.ClientRectangle;
          float cx = r.X + r.Width / 2f;
          float cy = r.Y + r.Height / 2f;

          var old = g.Transform;
          try
          {
              g.TranslateTransform(cx, cy);
              g.RotateTransform(180f);
              g.DrawString(text, font, brush,
                           new RectangleF(-r.Height / 2f, -r.Width / 2f,
                                          r.Height, r.Width),
                           sf);
          }
          finally
          {
              g.Transform = old;
          }
      }
  }

复现步骤:

步骤1:运行附带的示例应用程序。

步骤2:点击“旋转”按钮。

步骤3:观察旋转后中文文本的呈现方式。

实际行为:

  • 中文字符以出人意料的方向显示。

  • 旋转后文本流向发生变化。

  • 渲染结果并非按预期可读。

预期行为:

  • 旋转后文本应仍然可读。

  • 整块文本应作为一个整体旋转。

  • 中文字符应保持正确的方向和逻辑阅读顺序。

问题:

  • 这是在渲染竖直CJK文本时,GDI+或 System.Drawing 的已知限制吗?

  • 在这种情形下,这是 Graphics.DrawString 的预期行为吗?

  • 是否有推荐的替代方案,用于正确呈现竖直中文文本?

环境:

框架:.NET Framework / .NET

操作系统:Windows 11

解决方案

移除 StringFormatFlags.DirectionVertical,并将旋转角度改为270度,以获得期望的输出。

DirectionVertical 会把文本竖直绘制出来,字符是否被旋转取决于具体语言。因此中文字符不会被旋转,但数字和拉丁文本会旋转。然后 g.RotateTransform(180f) 会对整段文本进行旋转,导致所有中文字符都颠倒过来。

使用 g.RotateTransform(270f),不带任何 DirectionVertical 标志,以原样绘制整段文本的同时进行旋转。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章