Visual Basic File API Routines
DrawText: Add Ellipses to a File Path
Posted:   Thursday May 20, 2004
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   None
Author:   VBnet - Randy Birch

DrawText: Add Ellipses to a File Path
PathCompactPath: Adding Ellipses to a File Path
PathCompactPathEx: Adding Ellipses to a File Path


There are three methods to adding ellipses to file paths ... DrawText, PathCompactPath, and PathCompactPathEx. All three are equally effective, and all three have specific uses.
  • PathCompactPath creates a final ellipsed string in a length specified in pixels.
  • PathCompactPathEx creates the ellipsed string by specifying the size of the desired string in characters.
  • DrawText with the DT_PATH_ELLIPSIS style creates the ellipsed string to fit within a specific RECT, e.g. the RECT created by a text box or other control.

All three create APIs strings with the ellipses placed at an approximate midpoint inside the string (when possible) to ensure the end result shows both the start and end of the path. When DT_END_ELLIPSIS is specified for DrawText, the ellipses are placed at the end of the string.

DrawText is the workhorse of the three APIs with a number of different output styles available depending on the parameters set. DrawText is also the only one of the APIs that can create end-ellipses, useful for things like truncated listing of long data in a listview column.

Because of the extra requirement to calculate the RECT size for the destination string, the code for this method is a bit more involved than the Path methods, but certainly not difficult.  I recommend developing all three demos to determine the features of each for yourself.  All three are certainly small enough to be added to any project requiring ellipsed strings.  In addition to the text box output, this demo also shows how simple it is to pass a hwnd-less control to achieve the same ellipsed results.

You will note as well that the first ellipsed string in the demo does not show the original string's ".vbp" extention. It's not actually missing - the ellipsed string includes the file extension but the final ellipsed string exceeds the width of the textbox. This is a limitation of the small text box size and demonstrates that it may be possible to obtain unexpected results when the ellipsed string can not be logically broken at a path marker.

 BAS Module Code

 Form Code
Add a text box (Text1), a second text box (Text2) with it's Index set to 0 to create a control array, a label (Label1) and a command button (Command1) to a form. The code will create the required array of Text2() controls for the demo. Add the following code:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
'Determines the width and height of
'the rectangle. If there are multiple
'lines of text, DrawText uses the width
'of the rectangle pointed to by the lpRect
'parameter and extends the base of the
'rectangle to bound the last line of text.
'If there is only one line of text, DrawText
'modifies the right side of the rectangle so
'that it bounds the last character in the line.
'In either case, DrawText returns the height
'of the formatted text but does not
'draw the text.
Private Const DT_CALCRECT = &H400

'Replaces part of the given string with
'ellipses, if necessary, so that the result
'fits in the specified rectangle. The given
'string is not modified unless the DT_MODIFYSTRING
'flag is specified. You can specify
'DT_END_ELLIPSIS to replace characters at
'the end of the string, or DT_PATH_ELLIPSIS
'to replace characters in the middle of the
'string. If the string contains backslash
'(\) characters, DT_PATH_ELLIPSIS preserves
'as much as possible of the text after the
'last backslash.
Private Const DT_PATH_ELLIPSIS = &H4000
Private Const DT_END_ELLIPSIS = &H8000

'Modifies the given string to match the
'displayed text. This flag has no effect
'unless the DT_END_ELLIPSIS or
'DT_PATH_ELLIPSIS flag is specified.
Private Const DT_MODIFYSTRING = &H10000

'Expands tab characters. The default number of
'characters per tab is eight.
Private Const DT_EXPANDTABS = &H40

'Turns off processing of prefix characters.
'Normally, DrawText interprets the mnemonic-prefix
'character & as a directive to underscore the
'character that follows, and the mnemonic-prefix
'characters && as a directive to print a
'single &. By specifying DT_NOPREFIX, this
'processing is turned off.
Private Const DT_NOPREFIX = &H800

'Breaks words. Lines are automatically broken
'between words if a word would extend past the
'edge of the rectangle specified by the lpRect
'parameter. A carriage return-linefeed sequence
'also breaks the line.
Private Const DT_WORDBREAK = &H10

'Sets tab stops. Bits 15-8 (high-order byte
'of the low-order word) of the uFormat parameter
'specify the number of characters for each tab.
'The default number of characters per tab is eight.
Private Const DT_TABSTOP = &H80

'Truncates text that does not fit in the
'rectangle and adds ellipses.
Private Const DT_WORD_ELLIPSIS = &H40000

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Declare Function DrawText Lib "user32" Alias "DrawTextA" _
   (ByVal hDC As Long, _
    ByVal lpString As String, _
    ByVal nCount As Long, _
    lpRect As RECT, _
    ByVal uFormat As Long) As Long
Private Declare Function GetWindowRect Lib "user32" _
  (ByVal hwnd As Long, _
   lpRect As RECT) As Long
Private Declare Function lstrlenW Lib "kernel32" _
  (ByVal lpString As Long) As Long

Private Sub Form_Load()

   Dim cnt As Long
  'set up a few text boxes of varying widths
   For cnt = 0 To 9
      If cnt > 0 Then
         Load Text2(cnt)
      End If
      With Text2(cnt)
         .Text = ""
         .Left = Text1.Left
         .Top = (Text1.Top + Text1.Height) + (210 + (300 * cnt))
         .Height = 285
         'change the 400 to another value
         'to create wider or narrower controls
         .Width = 1600 + (cnt * 400)
         .Visible = True
      End With
  'set up a label to simulate the size
  'of an arbitrary text box, e.g. #5
   With Label1
      .Left = Text2(5).Left + Text2(5).Width + 500
      .Top = Text2(5).Top
      .Width = Text2(5).Width
      .Caption = "<label>"
   End With
   With Command1
      .Move Text1.Left, Text2(9).Top + 600, 2400, 345
      .Caption = "DrawText Ellipses"
   End With
  'a nice long path
   Text1.Text = "d:\vbasic\vbnet development" & _
                " projects\shell\filesystem\" & _
                "paths\pathrelativepathto\" & _

End Sub

Private Sub Command1_Click()

  'Truncates a file path to fit within
  'the width of the specified control.
  'No modification is required to target
  'either controls with a hwnd/hdc or without.
   Dim buff As String
   Dim cnt As Long

   buff = Text1.Text
   For cnt = 0 To 9

      Text2(cnt).Text = MakeEllipsedString(Text2(cnt), buff, DT_PATH_ELLIPSIS)
  'shows passing a hwnd/hdc-less control
   Label1.Caption = MakeEllipsedString(Label1, buff, DT_PATH_ELLIPSIS)
End Sub

Private Function MakeEllipsedString(ctl As Control, _
                                     ByVal sItem As String, _
                                     DT_STYLE As Long) As String

   Dim rc As RECT
   With ctl
     'obtain the rectangle of the control
     'that will hold the text
      If TypeOf ctl Is Label Then
         rc.Left = 0
         rc.Right = ctl.Width \ Screen.TwipsPerPixelX
         GetWindowRect ctl.hwnd, rc
      End If
     'tweak size a tad
      rc.Left = rc.Left * 0.95
      rc.Right = rc.Right * 0.95

     'call DrawText with the DT_MODIFYSTRING
     'parameter to modify the sItem string
      Call DrawText(hDC, sItem, -1, rc, _
   End With
  'assign the modified text to the function return
   MakeEllipsedString = TrimNull(sItem)
End Function

Private Function TrimNull(startstr As String) As String

   TrimNull = Left$(startstr, lstrlenW(StrPtr(startstr)))
End Function


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter