修改 RichTextBox 中的默认选项卡大小

发布于 2024-07-06 02:19:25 字数 218 浏览 8 评论 0原文

有没有办法更改 .NET RichTextBox 中的默认选项卡大小? 目前似乎设置为相当于 8 个空间,这对我来说有点大。

编辑:为了澄清,我想将“\t”的全局默认设置设置为控件的 4 个空格。 据我所知,SelectionTabs 属性要求您首先选择所有文本,然后通过数组选择选项卡宽度。 如果必须的话我会这样做,但如果可能的话,我宁愿只更改全局默认值一次,这样我就不必每次都这样做。

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.

Edit: To clarify, I want to set the global default of "\t" displays as 4 spaces for the control. From what I can understand, the SelectionTabs property requires you to select all the text first and then the the tab widths via the array. I will do this if I have to, but I would rather just change the global default once, if possible, sot that I don't have to do that every time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

鲜肉鲜肉永远不皱 2024-07-13 02:19:25

我将此类与等宽字体一起使用; 它将所有制表符替换为空格。

您所要做的就是根据您的要求设置以下设计器属性:

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

PS:正如@ToolmakerSteve指出的,显然这里的制表符大小逻辑非常简单:它只是将制表符替换为4个空格,这只适用于开头的制表符每行。 如果您需要改进选项卡处理,只需扩展逻辑即可。

代码

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://learn.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
            const int WM_SYSKEYDOWN = 0x104; // https://learn.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

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

PS: As @ToolmakerSteve pointed out, obviously the tab size logic here is very simple: it just replaces tabs with 4 spaces, which only works well for tabs at the beginning of each line. Just extend the logic if you need improved tab treatment.

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://learn.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
            const int WM_SYSKEYDOWN = 0x104; // https://learn.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
雨落星ぅ辰 2024-07-13 02:19:25

您可以通过设置 SelectionTabs 财产。

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

更新:
顺序很重要......

如果您在初始化控件的文本之前设置选项卡,则不必在设置选项卡之前选择文本。

例如,在上面的代码中,这将保留带有原始 8 个空格制表位的文本:

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

但这将使用新的:

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

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";
幽梦紫曦~ 2024-07-13 02:19:25

Winforms 没有用单个数字设置 RichTexBox 的默认制表符大小的属性,但如果您准备深入研究富文本框的 Rtf 并对其进行修改,则可以使用一个设置,称为: “\deftab”。 后面的数字表示缇数(1 点 = 1/72 英寸 = 20 缇)。 标准选项卡大小为 720 缇的生成的 Rtf 可能类似于:

{\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
}

如果您需要将缇转换为像素,请使用受 将像素转换为点

int tabSize=720;
Graphics g = this.CreateGraphics();
int pixels = (int)Math.Round(((double)tabSize) / 1440.0 * g.DpiX);
g.Dispose();

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();
挽清梦 2024-07-13 02:19:25

奇怪的是,一直没有人提出这个方法)

我们可以继承RichTextBox并重写CmdKey处理程序(ProcessCmdKey)
它看起来像这样:

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://learn.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
        const int WM_SYSKEYDOWN = 0x104;    // https://learn.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);
    }
}

现在,当您按Tab,控制区域将插入指定数量的空格,而不是\t

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://learn.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
        const int WM_SYSKEYDOWN = 0x104;    // https://learn.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

月光色 2024-07-13 02:19:25

如果您有一个仅用于显示(只读)固定间距文本的 RTF 框,那么最简单的事情就是不要搞乱制表位。 只需用空格替换它们即可。

如果您希望用户可以输入某些内容并使用 Tab 键前进,您还可以通过覆盖 OnKeyDown() 来捕获 Tab 键并打印空格。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文