DrawText incorrectly draws Segoe UI font texts

I ran into one issue with the text of the drawings using the DrawText Windows API call for the Segoe UI font:

enter image description here

This image demonstrates the problem: the specified text is shifted slightly to the right in the specified rectangle, so the last character is truncated (the best example is the number 0).

Our paint program works well for other fonts, and the problem only occurs for the Segoe UI.

What could it be and how to solve it?

Doing this in a VB6 OCX project on Windows 8 Pro 64-bit, if it matters.


The relevant code snippet is as follows:

' 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

      

The font for UserControl DC is installed using this code:

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

      

Where

m_hDC = CreateCompatibleDC(UserControl.hdc)

      

+3


source to share


2 answers


The problem is the quality of the output you are using. You are using ANTIALIASED_QUALITY

. Segoe UI is designed to be clear type. It looks great with crisp type, but terrible with standard anti-aliasing. Switch to cleaning type (set lqQuality

to CLEARTYPE_QUALITY

) and you will get much better results.

This image shows a 10pt Segoe UI rendering with the two quality options discussed above.



enter image description here

+5


source


Yes, David Heffernan was right - I needed to enable the ClearType setting for the entire OS:



enter image description here

+1


source







All Articles