Setting tabs / tabstops in a RichTextBox -

M

Matt

This took way to long to figure out - now that I have it working I
thought I would share with the group. I've seen tons of posts with
very little good answers on this seemingly simple thing that took me 2
hours to figure out!

You can set tabs through RichTextBox using the cheesy SelectAll()->
SelectionTabs() method, but that only works after the text has been
entered. If the user hits Enter on any line, it goes back and uses
the original tab stop settings. This code will setup the RichTextBox
on form load to use a different tab stop setting until you decide to
change it.

Here is the code, I cleaned out the try..catch stuff to make it as
clean as possible... the RichTextBox control is called simply:
RichTextBox1


Public Declare Auto Function SendMessage Lib "user32" _
(ByVal hwnd As IntPtr, _
ByVal wMsg As Integer, _
ByVal wParam As Integer, _
ByVal lParam() As Integer) As Integer

Declare Function GetTextExtentPoint32 Lib "gdi32" Alias
"GetTextExtentPoint32A" (ByVal hDC As IntPtr, ByVal lpsz As String,
ByVal cbString As Integer, ByRef lpSize As Size) As Integer

Declare Function SelectObject Lib "gdi32" (ByVal hDC As IntPtr,
ByVal hObject As IntPtr) As IntPtr

Private Const EM_SETTABSTOPS As Integer = &HCB


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Dim tabStops() As Integer

tabStops = SetupTabStops(5) '// 5 is the number of chars...

'// You must call this as well as the API Send Messages
Below...
RichTextBox1.SelectionTabs = tabStops

SendMessage(RichTextBox1.Handle, EM_SETTABSTOPS, 0, Nothing)
SendMessage(RichTextBox1.Handle, EM_SETTABSTOPS,
tabStops.Length, tabStops)


End Sub

Private Function SetupTabStops(ByVal numChars As Integer) As
Integer()

Dim testString As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim g As Graphics
Dim AvgCharWidth As Integer
Dim pxTabSetting As Integer
Dim i As Integer
Dim tabStops() As Integer
Dim StringWidth As Integer

g = RichTextBox1.CreateGraphics
StringWidth = MeasureDisplayStringWidth(g, testString,
RichTextBox1.Font)
AvgCharWidth = CInt(StringWidth / testString.Length)
pxTabSetting = (numChars * AvgCharWidth)

ReDim tabStops(30)

For i = 0 To tabStops.Length - 1
tabStops(i) = (i + 1) * pxTabSetting
Next

Return tabStops

End Function

Public Function MeasureDisplayStringWidth(ByVal g As Graphics,
ByVal text As String, ByVal fnt As Font) As Integer
Dim gdiSize As New System.Drawing.Size
Dim height As Integer = 0
Dim width As Integer = 0

'// You can't use MeasureString as many of the threads like to
say...
'// - it returns an incorrect result
'// due to the differences between old GDI and GDI+ in .NET
'// RichTextBox is an old GDI based control so we have to use
'// good old fashion API calls to get the correct string width
'// in pixels...

gdiSize.Width = 0
gdiSize.Height = 0
Dim hdc As IntPtr = g.GetHdc()

Dim hOldFont As IntPtr = SelectObject(hdc, fnt.ToHfont())

GetTextExtentPoint32(hdc, text, text.Length, gdiSize)

SelectObject(hdc, hOldFont)
g.ReleaseHdc(hdc)

width = gdiSize.Width
Return width

End Function
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top