2009-08-19 6 views
17

Đặt điều khiển hộp văn bản WinForms với MultiLine = trueAcceptsTab == true, làm cách nào tôi có thể đặt chiều rộng của ký tự tab được hiển thị?Làm cách nào để đặt chiều rộng TAB trong điều khiển Hộp văn bản Windows Forms?

Tôi muốn sử dụng hộp này làm hộp nhập tập lệnh nhanh và dơ bẩn cho plugin. Nó thực sự không cần phải được ưa thích chút nào, nhưng nó sẽ được tốt đẹp nếu các tab không được hiển thị rộng 8 ký tự ...

Từ câu trả lời được chấp nhận:

// 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 }); 
} 

này có thể được gọi trong hàm tạo của số Form của bạn, nhưng hãy cẩn thận: Hãy chắc chắn rằng InitializeComponents được chạy trước tiên.

+1

Bạn cũng nên bỏ đồ họa, có thể đặt đồ họa vào sử dụng câu lệnh. –

Trả lời

7

Tôi biết bạn đang sử dụng một TextBox hiện nay, nhưng nếu bạn có thể nhận được ngay với sử dụng một RichTextBox thay vào đó, bạn có thể sử dụng thuộc tính SelectedTabs để đặt độ rộng tab mong muốn:

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

Lưu ý rằng các offset này là pixel, không phải ký tự.

5

Ví dụ được cung cấp không chính xác.

Thông báo EM_SETTABSTOPS dự kiến ​​kích thước tab sẽ được chỉ định trong dialog template units chứ không phải theo pixel. Sau khi tìm hiểu xung quanh, có vẻ như đơn vị mẫu hộp thoại tương đương với 1/4th the average width of the window's character. Vì vậy, bạn sẽ cần phải chỉ định 8 cho 2 ký tự tab dài, 16 cho bốn charachters, và như vậy.

Vì vậy, các mã có thể được đơn giản hóa như:

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

Cảm ơn, Loris, tôi không biết điều này. –

6

Với việc sử dụng phương pháp mở rộng, bạn có thể thêm một phương pháp mới để kiểm soát lớp TextBox. Đây là thực hiện của tôi (trong đó có một phương pháp mở rộng thêm cung cấp cho bạn các tọa độ cho vị trí hiện tại của caret chèn) từ những gì tôi thu thập được từ những người đóng góp trước trên:

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

cảm ơn! điều này thực sự tuyệt vời! –

+0

Bạn được chào đón! Trên thực tế một tinh tế hơn nữa mà tôi đã thêm vào kiểm tra mã của riêng tôi để đảm bảo rằng TextBox là Multiline và AcceptsTab được kích hoạt. –

+0

Cảm ơn, Brien, đó là một cách rất hay để gói gọn chức năng này! – BillW

1

Đối với bất cứ ai muốn độ rộng tab khác nhau, tôi đã thực hiện phương pháp này:

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