如何在Windows窗体TextBox控件中设置TAB宽度?

Dar*_*mas 22 .net textbox winforms

给定带有MultiLine = true和的WinForms TextBox控件AcceptsTab == true,如何设置显示的制表符的宽度?

我想将它用作插件的快速和脏脚本输入框.它真的不需要花哨,但如果标签没有显示为8个字符宽,那就太好了......

Aam*_*mir 13

我认为将EM_SETTABSTOPS消息发送到TextBox将起作用.

// 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 }
        );
}
Run Code Online (Sandbox Code Playgroud)

这可以在你的构造函数中调用Form,但要注意:确保InitializeComponents先运行.

  • 我认为 EM_SETTABSTOPS 在 _Dialog Template Units_(有时称为 _Dialog Logical Units_,或 _DLUs_)中测量文本。您应该可以只说“numChars * 4”(因为每个字符有 4 个水平 DLU)。 (3认同)

Rhy*_*nes 8

我知道你正在使用TextBox当前的,但如果你可以使用RichTextBox替代,那么你可以使用SelectedTabs属性来设置所需的标签宽度:

richTextBox.SelectionTabs = new int[] { 15, 30, 45, 60, 75};
Run Code Online (Sandbox Code Playgroud)

请注意,这些偏移是像素,而不是字符.


Lor*_*ris 7

提供的示例不正确.

EM_SETTABSTOPS消息要求在对话框模板单元中指定选项卡大小,而不是以像素为单位.经过一些挖掘后,对话框模板单元似乎等于窗口角色平均宽度的1/4.因此,您需要为2个字符的长标签指定8,为4个字符指定16,依此类推.

所以代码可以简化为:

public static void SetTabWidth(TextBox textbox, int tabWidth)
{
    SendMessage(textbox.Handle, EM_SETTABSTOPS, 1, 
            new int[] { tabWidth * 4 });
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*ead 6

通过使用扩展方法,您可以向TextBox控件类添加新方法.这是我的实现(包括一个额外的扩展方法,为您提供插入插入符号的当前位置的坐标),我从上面的前面的贡献者收集的内容:

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 });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)