I am using VS 2005 and writing a VB.net application for a Windows Mobile 5.0 Smartphone using .Net CF 2.0.
I need to determine the text height of multi-line wrapped text in a Label control so I can set the height of the Label to ensure that all text is visible, and then reposition other controls based on the new height of the Label.
Unfortunately, CF 2.0 Labels do not have an AutoSize property.
I have tried some examples using CreateGraphics and MeasureString such as the following...
Private Sub AutoSizeControl(ByVal ctlControl As Label, ByVal textPadding As Integer)
' Create a Graphics object for the Control
Dim g As Graphics = Me.CreateGraphics
' Get the Size needed to accommodate the formatted Text
Dim preferredSize As Size = g.MeasureString(ctlControl.Text, ctlControl.Font).ToSize()
' Pad the text and resize the control
ctlControl.ClientSize = New Size(preferredSize.Width + textPadding * 2, preferredSize.Height + textPadding * 2)
' Clean up the Graphics object
g.Dispose()
End Sub
... but with no success. The above code returns a prefferredSize as if the text is being written on a single line.
Any help/suggestions would be appreciated.

AutoSize Label
rboarman
Couple of things are missing (one is my fault)
1. You need to add a flag DT_WORDBREAK (and while you at it, DT_LEFT and DT_TOP for consistency)
2. You need to select the proper font in the device context:
Dim hFontOld as IntPtr = SelectObject(hDC, ctlLabel.Font.GetHFont())
DrawText(...
tommyready
Hi Alex,
I've finally had time to get back to this issue and try your suggestion with the following code.
Private Structure RECT Public Left As Integer Public Top As Integer Public Right As Integer Public Bottom As Integer End Structure
Private Const DT_CALCRECT As Integer = &H400 Private Const DT_MULTILINE As Integer = &H1 Private Declare Function DrawText Lib "coredll.dll" (ByVal hdc As IntPtr, ByVal lpStr As String, ByVal nCount As Integer, ByRef lpRect As RECT, ByVal wFormat As Integer) As IntegerPublic Sub AutoSizeLabel(ByVal ctlLabel As Label)
End With ' Clean up the Graphics objectobjGraphics.Dispose()
End SubBut unfortunately it doesn't work. DrawText is still returning a RECT.Bottom that equals the height of a single line, even though the text is much longer than the width of the label.
Am I doing something worng Any suggestions
Tony
Prashant Dhingra
Thanks Alex. The DT_WORDBREAK did the trick, and it now seems to work perfectly.
Some things to note are...
1. According to MSDN (http://msdn.microsoft.com/library/default.asp url=/library/en-us/wcefonts5/html/wce50lrfDrawText.asp) the DrawText API in Windows CE does not support DT_MULTILINE and "...assumes that all formatting has multiple lines unless you specify the DT_SINGLELINE".
2. To get the handle from the Font object use the ToHfont method. The GetHFont method does not exist.
For the record, the following is my entire Module. Hope this helps others with the same issue.
Module
CeAutoSizeLabel ' Externals ---------------------- Private Structure RECT Public Left As Integer Public Top As Integer Public Right As Integer Public Bottom As Integer End Structure Private Const DT_CALCRECT As Integer = &H400 Private Const DT_CENTER As Integer = &H1 Private Const DT_LEFT As Integer = &H0 Private Const DT_RIGHT As Integer = &H2 Private Const DT_TOP As Integer = &H0 Private Const DT_WORDBREAK As Integer = &H10 Private Declare Function DeleteObject Lib "coredll.dll" (ByVal hObject As IntPtr) As Integer Private Declare Function DrawText Lib "coredll.dll" (ByVal hdc As IntPtr, ByVal lpStr As String, ByVal nCount As Integer, ByRef lpRect As RECT, ByVal wFormat As Integer) As Integer Private Declare Function SelectObject Lib "coredll.dll" (ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr Public Sub AutoSizeLabelHeight(ByVal ctlLabel As Label) ' Auto size the height of a Label control based on the contents of the label. ' Note: This routine is best called from the Form's Resize event so that changes to screen size and orientation ' will force the Label height to be adjusted. Dim uRECT As RECT Try ' Create a Graphics object. We need a Graphics object so we can get a handle to a Device Context to be used ' later in the DrawText API. However the Label control in CF2.0 does not support the CreateGraphics method, ' so create the Graphics object from the form on which the Label is located. ' Note: This can cause an exception when this routine is called from a Form's Resize event. Probably because ' the form is not fully initialised and the Resize event may be called one or more times during form ' initialisation. Therefore, the entire routine is wrapped in a Try/Catch block. Dim objGraphics As Graphics = ctlLabel.TopLevelControl.CreateGraphics ' ------------------------------------------------------------- ' Note: An alternative to the above method of creating a Graphics object is to create a Bitmap object and ' obtain the Graphics object from it as follows. 'Dim objBitmap As New Bitmap(1, 1) 'Dim objGraphics As Graphics = Graphics.FromImage(objBitmap) ' And remembering to dispose of the Bitmap object in a cleanup at the end of the routine as follows. 'objBitmap.Dispose() ' This method would remove the need for the Try/Catch block, but means that Bitmap objects are repeatedly ' being created and destroyed. ' ------------------------------------------------------------- ' Get the handle to the Device Context of the Graphics object Dim hDc As IntPtr = objGraphics.GetHdc With ctlLabel ' Get the handle to the Font of the Label Dim hFont As IntPtr = .Font.ToHfont ' Apply the Font to the Graphics object Dim hFontOld As IntPtr = SelectObject(hDc, hFont) ' Set the initial size of the RectuRECT.Right = .Width
uRECT.Bottom = .Height
' Build the base format Dim lFormat As Integer = DT_CALCRECT Or DT_WORDBREAK Or DT_TOP ' ------------------------------------------------------------- ' Adjust the format to the Label's text alignment. ' Note: This probably isn't necessary as the horizontal alignment of text shouldn't affect the text ' height calculation. But just in case... Select Case .TextAlign Case ContentAlignment.TopLeft Or DT_LEFT Case ContentAlignment.TopCenter Or DT_CENTER Case ContentAlignment.TopRight Or DT_RIGHT End Select ' ------------------------------------------------------------- ' Calculate the Rect of the text If DrawText(hDc, .Text, -1, uRECT, lFormat) <> 0 Then ' Success ' Apply the new height to the label.Height = uRECT.Bottom
End If ' Cleanup ---------------------------- ' Set the Font of the Graphics object back to the originalSelectObject(hDc, hFontOld)
' Delete the handle to the Font of the LabelDeleteObject(hFont)
End With ' Clean up the Graphics objectobjGraphics.Dispose()
Catch ' Do nothing 'Debug.WriteLine("AutoSizeLabelHeight failed.") End Try End SubEnd
ModuleTony
amolchopra
Sean P. Mehrlander
Made some improvements to the above code as follows...
1. The line ...
uRECT.Right = .Width
..should read...
uRECT.Right = .Width - 2
...to accommodate for the 1 pixel internal margin that the Label control has. Needed to get the height calc correct for very long text.
2. The line...
uRECT.Bottom = .Height
...is not required and can be removed.
3. The line...
.Height = uRECT.Bottom
...should read
.Height = uRECT.Bottom + 2
...to add a 2 pixel margin at the bottom of the Label. Just looks better.
Tony