【问题标题】:How to set the TAB width in a Windows Forms TextBox control?如何在 Windows 窗体 TextBox 控件中设置 TAB 宽度?
【发布时间】:2009-08-19 07:59:46
【问题描述】:

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

我想将其用作插件的快速而肮脏的脚本输入框。真的完全不需要花哨,但如果标签不显示为 8 个字符宽就好了……

【问题讨论】:

  • 你也应该处理图形,也许把它放在 using 语句中。

标签: .net winforms textbox


【解决方案1】:

我认为将 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 }
        );
}

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

【讨论】:

  • MSDN 链接适用于 Windows CE;我改了。
  • 我认为 EM_SETTABSTOPS 在 Dialog Template Units(有时称为 Dialog Logical UnitsDLUs)中测量文本.您应该可以只说“numChars * 4”(因为每个字符有 4 个水平 DLU)。
【解决方案2】:

我知道您目前使用的是TextBox,但如果您可以改用RichTextBox,那么您可以使用 SelectedTabs 属性来设置所需的标签宽度:

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

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

【讨论】:

    【解决方案3】:

    提供的示例不正确。

    EM_SETTABSTOPS 消息要求标签大小以 dialog template units 而不是像素为单位指定。经过一番挖掘,似乎对话模板单元等于1/4th the average width of the window's character。因此,您需要为 2 个字符的长制表符指定 8,为 4 个字符指定 16,依此类推。

    所以代码可以简化为:

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

    【讨论】:

    • 谢谢,Loris,我不知道这一点。
    【解决方案4】:

    通过使用扩展方法,您可以向 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 });
            }
        }
    }
    

    【讨论】:

    • 不客气!实际上,我在自己的代码中添加了进一步的改进,以确保 TextBox 是多行并且启用了 AcceptsTab。
    • 谢谢,Brien,这是封装此功能的好方法!
    【解决方案5】:

    对于任何想要不同标签宽度的人,我采用了这种方法:

    using System.Runtime.InteropServices;
    
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, uint[] lParam);
    private const int EM_SETTABSTOPS = 0x00CB;
    
    private void InitialiseTabStops()
    {
        // Declare relative tab stops in character widths
        var tabs = new uint[] { 2, 2, 4, 8, 2, 32 };
    
        // Convert from character width to 1/4 character width
        for (int position = 0; position < tabs.Length; position++)
            tabs[position] *= 4;
    
        // Convert from relative to absolute positions
        for (int position = 1; position < tabs.Length; position++)
            tabs[position] += tabs[position - 1];
    
        SendMessage(textBox.Handle, EM_SETTABSTOPS, tabs.Length, tabs);
    }
    

    【讨论】:

      【解决方案6】:

      【讨论】:

        猜你喜欢
        • 2016-05-22
        • 1970-01-01
        • 2012-02-02
        • 1970-01-01
        • 2010-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-21
        相关资源
        最近更新 更多