Modifying default tab size in RichTextBox

后端 未结 5 711
北海茫月
北海茫月 2020-12-11 01:07

Is there any way to change the default tab size in a .NET RichTextBox? It currently seems to be set to the equivalent of 8 spaces which is kinda large for my taste.

相关标签:
5条回答
  • 2020-12-11 01:18

    It's strange that no one has proposed this method for all this time)

    We can inherit from the RichTextBox and rewrite the CmdKey handler (ProcessCmdKey)
    It will look like this:

    public class TabRichTextBox : RichTextBox
    {
        [Browsable(true), Category("Settings")]
        public int TabSize { get; set; } = 4;
    
        protected override bool ProcessCmdKey(ref Message Msg, Keys KeyData)
        {
    
            const int WM_KEYDOWN = 0x100;       // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
            const int WM_SYSKEYDOWN = 0x104;    // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-syskeydown
            // Tab has been pressed
            if ((Msg.Msg == WM_KEYDOWN || Msg.Msg == WM_SYSKEYDOWN) && KeyData.HasFlag(Keys.Tab))
            {
                // Let's create a string of spaces, which length == TabSize
                // And then assign it to the current position
                SelectedText += new string(' ', TabSize);
    
                // Tab processed
                return true;
            }
            return base.ProcessCmdKey(ref Msg, KeyData);
        }
    }
    

    Now, when you'll press Tab, a specified number of spaces will be inserted into the control area instead of \t

    0 讨论(0)
  • 2020-12-11 01:21

    You can set it by setting the SelectionTabs property.

    private void Form1_Load(object sender, EventArgs e)
    {
        richTextBox1.SelectionTabs = new int[] { 100, 200, 300, 400 };
    }
    

    UPDATE:
    The sequence matters....

    If you set the tabs prior to the control's text being initialized, then you don't have to select the text prior to setting the tabs.

    For example, in the above code, this will keep the text with the original 8 spaces tab stops:

    richTextBox1.Text = "\t1\t2\t3\t4";
    richTextBox1.SelectionTabs = new int[] { 100, 200, 300, 400 };
    

    But this will use the new ones:

    richTextBox1.SelectionTabs = new int[] { 100, 200, 300, 400 };
    richTextBox1.Text = "\t1\t2\t3\t4";
    
    0 讨论(0)
  • 2020-12-11 01:25

    Winforms doesn't have a property to set the default tab size of a RichTexBox with a single number, but if you're prepared to dig into the Rtf of the rich text box, and modify that, there's a setting you can use called: "\deftab". The number afterwards indicates the number of twips (1 point = 1/72 inch = 20 twips). The resulting Rtf with the standard tab size of 720 twips could look something like:

    {\rtf1\ansi\ansicpg1252\deff0\deflang2057\deftab720{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}
    \viewkind4\uc1\pard\f0\fs41
    1\tab 2\tab 3\tab 4\tab 5\par
    }
    

    If you need to convert twips into pixels, use this code inspired from Convert Pixels to Points:

    int tabSize=720;
    Graphics g = this.CreateGraphics();
    int pixels = (int)Math.Round(((double)tabSize) / 1440.0 * g.DpiX);
    g.Dispose();
    
    0 讨论(0)
  • 2020-12-11 01:26

    If you have a RTF box that is only used to display (read only) fixed pitch text, the easiest thing would be not to mess around with Tab stops. Simply replace them stuff with spaces.

    If you want that the user can enter something and use that Tab key to advance you could also capture the Tab key by overriding OnKeyDown() and print spaces instead.

    0 讨论(0)
  • 2020-12-11 01:33

    I'm using this class with monospaced fonts; it replaces all TABs with spaces.

    All you have to do is to set the following designer properties according to your requirements:

    • AcceptsTab = True TabSize
    • ConvertTabToSpaces = True
    • TabSize = 4

    Code

    using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace MyNamespace
    {
        public partial class MyRichTextBox : RichTextBox
        {
            public MyRichTextBox() : base() =>
                KeyDown += new KeyEventHandler(RichTextBox_KeyDown);
    
            [Browsable(true), Category("Settings"), Description("Convert all tabs into spaces."), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public bool ConvertTabToSpaces { get; set; } = false;
    
            [Browsable(true), Category("Settings"), Description("The number os spaces used for replacing a tab character."), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public int TabSize { get; set; } = 4;
    
            [Browsable(true), Category("Settings"), Description("The text associated with the control."), Bindable(true), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public new string Text
            {
                get => base.Text;
                set => base.Text = ConvertTabToSpaces ? value.Replace("\t", new string(' ', TabSize)) : value;
            }
    
            protected override bool ProcessCmdKey(ref Message Msg, Keys KeyData)
            {
                const int WM_KEYDOWN = 0x100; // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
                const int WM_SYSKEYDOWN = 0x104; // https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-syskeydown
    
                if (ConvertTabToSpaces && KeyData == Keys.Tab && (Msg.Msg == WM_KEYDOWN || Msg.Msg == WM_SYSKEYDOWN))
                {
                    SelectedText += new string(' ', TabSize);
                    return true;
                }
                return base.ProcessCmdKey(ref Msg, KeyData);
            }
    
            public new void AppendText(string text)
            {
                if (ConvertTabToSpaces)
                    text = text.Replace("\t", new string(' ', TabSize));
                base.AppendText(text);
            }
    
            private void RichTextBox_KeyDown(object sender, KeyEventArgs e)
            {
                if ((e.Shift && e.KeyCode == Keys.Insert) || (e.Control && e.KeyCode == Keys.V))
                {
                    SuspendLayout();
                    int start = SelectionStart;
                    string end = Text.Substring(start);
                    Text = Text.Substring(0, start);
                    Text += (string)Clipboard.GetData("Text") + end;
                    SelectionStart = TextLength - end.Length;
                    ResumeLayout();
                    e.Handled = true;
                }
            }
    
        } // class
    } // namespace
    
    0 讨论(0)
提交回复
热议问题