Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the TAB width in a Windows Forms TextBox control?

Given a WinForms TextBox control with MultiLine = true and AcceptsTab == true, how can I set the width of the tab character displayed?

I want to use this as a quick and dirty script input box for a plugin. It really doesn't need to be fancy at all, but it would be nice if tabs were not displayed as 8 characters wide...

like image 518
Daren Thomas Avatar asked Aug 19 '09 07:08

Daren Thomas


People also ask

How to set tab order in Windows Forms?

Tab order can be set in the Properties window of the designer using the TabIndex property. The TabIndex property of a control determines where it's positioned in the tab order. By default, the first control added to the designer has a TabIndex value of 0, the second has a TabIndex of 1, and so on.

How to set tab order in Visual Studio?

To set the tab order, you simply select all three textboxes, then select Tab Order from the View menu. Then just click the controls in the order you want the tabs to sit. As you click each control, the tab order will be displayed on the control to keep you up to date.

How to use tab order in c#?

Simply go to form. cs[design], click "View" tab at the top of the page and select "Tab Order". This will allow you to click on the form elements in order of which you want them to be tabbed to. Any items not selected will not be tabbable(I think I made this word up).

What is Tabstop in c#?

Tabstop Property. The Tabstop property specifies whether an end user can tab to a control. When an end user tabs to a control, it has focus. You can use the Tab Order dialog box to determine the tab order of controls on a form. For more information, see Assigning Tab Order to Controls.


4 Answers

I think sending the EM_SETTABSTOPS message to the TextBox will work.

// set tab stops to a width of 4 private const int EM_SETTABSTOPS = 0x00CB;  [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);  public static void SetTabWidth(TextBox textbox, int tabWidth) {     Graphics graphics = textbox.CreateGraphics();     var characterWidth = (int)graphics.MeasureString("M", textbox.Font).Width;     SendMessage         ( textbox.Handle         , EM_SETTABSTOPS         , 1         , new int[] { tabWidth * characterWidth }         ); } 

This can be called in the constructor of your Form, but beware: Make sure InitializeComponents is run first.

  • Link at MSDN
  • Here is another link
like image 142
Aamir Avatar answered Oct 05 '22 09:10

Aamir


I know you are using a TextBox currently, but if you can get away with using a RichTextBox instead, then you can use the SelectedTabs property to set the desired tab width:

richTextBox.SelectionTabs = new int[] { 15, 30, 45, 60, 75}; 

Note that these offsets are pixels, not characters.

like image 39
Rhys Jones Avatar answered Oct 05 '22 09:10

Rhys Jones


The example offered is incorrect.

The EM_SETTABSTOPS message expects the tab sizes to be specified in dialog template units and not in pixels. After some digging around, it appears that a dialog template unit equals to 1/4th the average width of the window's character. So you'll need to specify 8 for 2 characters long tabs, 16 for four charachters, and so on.

So the code can be simplified as:

public static void SetTabWidth(TextBox textbox, int tabWidth)
{
    SendMessage(textbox.Handle, EM_SETTABSTOPS, 1, 
            new int[] { tabWidth * 4 });
}
like image 31
Loris Avatar answered Oct 05 '22 08:10

Loris


With the use of extension methods, you can add a new method to the TextBox control class. This is my implementation (including an additional extension method that gives you the coordinates for the current location of the insert caret) from what I gathered from the previous contributors above:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Extensions
{
    public static class TextBoxExtension
    {
        private const int EM_SETTABSTOPS = 0x00CB;

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);

        public static Point GetCaretPosition(this TextBox textBox)
        {
            Point point = new Point(0, 0);

            if (textBox.Focused)
            {
                point.X = textBox.SelectionStart - textBox.GetFirstCharIndexOfCurrentLine() + 1;
                point.Y = textBox.GetLineFromCharIndex(textBox.SelectionStart) + 1;
            }

            return point;
        }

        public static void SetTabStopWidth(this TextBox textbox, int width)
        {
            SendMessage(textbox.Handle, EM_SETTABSTOPS, 1, new int[] { width * 4 });
        }
    }
}
like image 35
Brien Halstead Avatar answered Oct 05 '22 10:10

Brien Halstead