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. |
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
Next
'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\" & _
"pathrelativepathto.vbp"
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)
Next
'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
Else
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, _
DT_CALCRECT Or DT_MODIFYSTRING Or DT_STYLE)
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
|