winapi - DrawText 错误地绘制 Segoe UI 字体文本

标签 winapi vb6 ocx drawtext

我在使用 Segoe UI 字体的 Windows API DrawText 调用绘制文本时遇到一个问题:

enter image description here

此图演示了该问题:指定的文本在指定的矩形中向右移动了一点,因此最后一个字符被剪掉(最好的例子是 0 数字)。

我们的绘图例程适用于其他字体,并且该问题仅出现在 Segoe UI 中。

这可能是什么以及如何解决它?

如果需要的话,可以在 Windows 8 Pro 64 位上的 VB6 OCX 项目中执行此操作。

<小时/>

对应的代码源码片段如下:

' Only draws or measure text (if DT_CALCRECT is specified)
' using the native WinAPI flags:
Public Sub gpInternalDrawText( _
     ByVal lHDC As Long, _
     ByRef sText As String, _
     ByRef tR As RECT, _
     ByVal lFlags As Long _
  )
  ' Allows Unicode rendering of text under NT/2000/XP
  If (g_bIsNt) Then
     ' NT4 crashes with ptr = 0
     If StrPtr(sText) <> 0 Then
        DrawTextW lHDC, StrPtr(sText), -1, tR, lFlags
     End If
  Else
     DrawTextA lHDC, sText, -1, tR, lFlags
  End If
End Sub

' Draws the string in the specifed rectangle.
' Should not be called to calculate text size
' (with DT_CALCRECT flag - use gpInternalDrawText instead)
Public Sub DrawText( _
     ByVal lHDC As Long, _
     ByRef sText As String, _
     ByRef rcText As RECT, _
     ByVal lFlags As Long, _
     Optional ByVal eAlignH As Long = 0, _
     Optional ByVal eAlignV As Long = 0 _
  )

  ' *** Automatically turns processing prefixes off (if required)

  If (lFlags And &H200000) = 0 Then
     lFlags = lFlags Or DT_NOPREFIX
  Else
     lFlags = lFlags Xor DT_PREFIXONLY
  End If


  ' *** We can modify rcText below, so do it with its copy

  Dim rcDrawText As RECT
  LSet rcDrawText = rcText


  ' *** Getting the full set of API flags for our text

  Select Case eAlignH
  ' in fact don't need that as DT_LEFT=0:
'   Case igAlignHLeft
'      lFlags = lFlags Or DT_LEFT
  Case igAlignHCenter
     lFlags = lFlags Or DT_CENTER
  Case igAlignHRight
     lFlags = lFlags Or DT_RIGHT
  End Select

  If (lFlags And DT_SINGLELINE) <> 0 Then
     Select Case eAlignV
     ' in fact don't need that as DT_TOP=0:
  '   Case igAlignVTop
  '      lFlags = lFlags Or DT_TOP
     Case igAlignVCenter
        lFlags = lFlags Or DT_VCENTER
     Case igAlignVBottom
        lFlags = lFlags Or DT_BOTTOM
     End Select
  Else
     If eAlignV <> igAlignVTop Then
        Dim rcCalcRect As RECT
        LSet rcCalcRect = rcText
        gpInternalDrawText lHDC, sText, rcCalcRect, lFlags Or DT_CALCRECT
        Dim lTextHeight As Long
        lTextHeight = rcCalcRect.Bottom - rcCalcRect.Top
        Select Case eAlignV
        Case igAlignVCenter
           ' simplified (rcText.Top + rcText.Bottom) / 2 - lTextHeight / 2
           ' should be integer division because of rounding erros in the case of "/"
           rcDrawText.Top = (rcDrawText.Top + rcDrawText.Bottom - lTextHeight) \ 2
        Case igAlignVBottom
           rcDrawText.Top = rcDrawText.Bottom - lTextHeight
        End Select
     End If
  End If


  ' *** Finally draw the text

  Const FIXED_PATH_ELLIPSIS_FLAGS As Long = DT_SINGLELINE Or DT_PATH_ELLIPSIS
  If (lFlags And FIXED_PATH_ELLIPSIS_FLAGS) = FIXED_PATH_ELLIPSIS_FLAGS Then
     DrawText_FixedPathEllipsis lHDC, sText, rcDrawText, lFlags
  Else
     gpInternalDrawText lHDC, sText, rcDrawText, lFlags
  End If

End Sub

使用以下代码设置 UserControl DC 的字体:

Public Function FontHandle(fnt As IFont) As Long
   FontHandle = fnt.hFont
End Function

Private Sub pApplyFont()
   If (m_hFntDC <> 0) Then
      If (m_hDC <> 0) Then
         If (m_hFntOldDC <> 0) Then
            SelectObject m_hDC, m_hFntOldDC
         End If
      End If
   End If

   m_hFntDC = FontHandle(UserControl.Font)
   If (m_hDC <> 0) Then
      m_hFntOldDC = SelectObject(m_hDC, m_hFntDC)
   End If
End Sub

,其中

m_hDC = CreateCompatibleDC(UserControl.hdc)

最佳答案

问题在于您所使用的输出质量。您正在使用ANTIALIASED_QUALITY。 Segoe UI 专为清晰的字体而设计。清晰的字体看起来很棒,但标准的抗锯齿功能却很糟糕。切换到透明类型(将 lqQuality 设置为 CLEARTYPE_QUALITY),您将获得更好的结果。

此图像演示了使用上面讨论的两个质量选项渲染 10pt Segoe UI。

enter image description here

关于winapi - DrawText 错误地绘制 Segoe UI 字体文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26502453/

相关文章:

actionscript-3 - 在 flex 中调用 Win32 API 来设置 Window Display Affinity

asp.net - ASP 创建对象时没有此类接口(interface)支持错误

c# - 在 Windows 服务中使用 ocx 文件

winapi - GDI - 我可以在 DrawText 中使用新的 Windows 10 Segoe UI 表情符号彩色字体吗?

将本地时间转换为时间戳

c - 将非 BMP 代码点写入控制台

Vb6 如何制作 0-9 的随机字符串和 x 字符的 a-z

dll - 从 .NET DLL 调用 VB6 方法

.net - 如何在 .NET 中安全地运行异步代码和事件以便 VB6 可以处理它?

ocx - 如果 OCX 文件(例如 flash.ocx)已注册,如何在 Visual C++ 中查找?