Compacting a Path to a Certain Number of Pixels
The function CompactPath
can be used to compact a path for being displayed on a Graphics
object with a specific font:
Private Declare Auto Function PathCompactPath Lib "shlwapi.dll" ( _
ByVal hDC As IntPtr, _
ByVal lpszPath As String, _
ByVal dx As Int32 _
) As Boolean
Public Function CompactPath( _
ByVal Path As String, _
ByVal Destination As Graphics, _
ByVal MaxWidth As Integer _
) As String
Dim hDC As IntPtr = Destination.GetHdc()
Dim Success As Boolean = PathCompactPath(hDC, Path, MaxWidth)
Destination.ReleaseHdc(hDC)
If Success Then
Dim p As Integer = Strings.InStr(Path, ControlChars.NullChar) - 1
If p > 0 Then
Return Strings.Left(Path, p)
Else
Return Path
End If
Else
Throw New Exception("String does not fit into space.")
End If
End Function
Usage:
Using g As Graphics = Me.CreateGraphics()
Try
MsgBox( _
CompactPath( _
"C:\Program Files\Some Company\Some Product\Data\File.txt", _
g, _
180 _
) _
)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Using
Catching the exception is a very costly operation, returning a Boolean variable that indicates the success of the operation would be the better approach when calling the method several times.
If the compacted path string is not needed, there is a managed alternative to the code shown above that can be used to draw the compacted path to a Graphics
object. The listing below contains a skeleton of an implementation for a label control displaying a compacted path. Basing the control on System.Windows.Forms.Label
would be possible too:
Imports System.Drawing
Imports System.Windows.Forms
''' <summary>
''' Provides a simple label control for displaying a compacted path.
''' </summary>
Public Class TrimmedLabel
Inherits Control
Private m_ForeColorBrush As SolidBrush = New SolidBrush(Me.ForeColor)
Private m_StringFormat As StringFormat = _
New StringFormat(StringFormatFlags.NoWrap)
''' <summary>
''' Creates a new instance of <c>PathLabel</c>.
''' </summary>
Public Sub New()
Me.SetStyle( _
ControlStyles.AllPaintingInWmPaint Or _
ControlStyles.DoubleBuffer Or _
ControlStyles.ResizeRedraw, _
True _
)
Me.UpdateStyles()
m_StringFormat.Trimming = StringTrimming.EllipsisPath
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaintBackground(e)
e.Graphics.DrawString( _
Me.Text, _
Me.Font, _
m_ForeColorBrush, _
RectangleF.op_Implicit(Me.ClientRectangle), _
m_StringFormat _
)
End Sub
Protected Overrides Sub OnForeColorChanged(ByVal e As EventArgs)
m_ForeColorBrush.Dispose()
m_ForeColorBrush = New SolidBrush(Me.ForeColor)
MyBase.OnForeColorChanged(e)
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
Me.Invalidate()
MyBase.OnTextChanged(e)
End Sub
End Class