By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,027 Members | 1,220 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,027 IT Pros & Developers. It's quick & easy.

Setting tabs / tabstops in a RichTextBox -

P: n/a
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
Nov 21 '05 #1
Share this question for a faster answer!
Share on Google+

This discussion thread is closed

Replies have been disabled for this discussion.