2009-08-19 100 views
17

給定一個帶有MultiLine = trueAcceptsTab == true的WinForms TextBox控件,如何設置顯示的製表符的寬度?如何在Windows窗體TextBox控件中設置TAB寬度?

我想用它作爲插件的快速和髒腳本輸入框。它真的不需要有想象力可言,但如果標籤沒有顯示爲寬8個字符就好......

從接受的答案:

// 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先運行。

+1

你也應該配置圖形,也許把它放在使用語句。 – 2012-05-16 07:16:40

回答

7

我知道你使用的是TextBox目前,但如果你可以使用一個RichTextBox脫身相反,您可以使用SelectedTabs屬性來設置所需的製表符寬度:

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

請注意,這些偏移量是像素,而不是字符。

5

提供的示例不正確。

EM_SETTABSTOPS消息需要在dialog template units中指定標籤大小,而不是以像素爲單位。經過一番挖掘,看起來對話框模板單元等於1/4th the average width of the window's character。因此,您需要爲2個字符長的製表符指定8,爲4個charachters指定16,依此類推。

因此,代碼可以簡化爲:

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

謝謝,洛里斯,我沒有意識到這一點。 – 2012-10-22 07:55:26

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 }); 
     } 
    } 
} 
+0

謝謝!這真的很酷! – 2013-01-25 09:22:16

+0

不客氣!實際上,我添加到自己的代碼中的進一步細化檢查將確保TextBox是Multiline,並且AcceptsTab已啓用。 – 2013-01-25 18:24:50

+0

謝謝布里恩,這是封裝這個功能的好方法! – BillW 2013-08-18 10:35:04

1

誰想要不同的標籤寬度,我採取了這種方法:

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); 
} 
相關問題