2009-08-19 12 views
17

Dado un control WinForms TextBox con MultiLine = true y AcceptsTab == true, ¿cómo puedo configurar el ancho del carácter de tabulación que se muestra?¿Cómo establecer el ancho de TAB en un control TextBox de Windows Forms?

Quiero utilizar esto como un cuadro de entrada de script rápido y sucio para un complemento. Realmente no tiene por qué ser de lujo en absoluto, pero sería bueno que las pestañas no se mostraban como 8 caracteres de ancho ...

De la respuesta aceptada:

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

Esto puede ser llamado en el constructor de su Form, pero tenga cuidado: asegúrese de que InitializeComponents se ejecute primero.

+1

También debe deshacerse de los gráficos, tal vez ponerlos en la instrucción using. –

Respuesta

7

Sé que está utilizando un TextBox actualmente, pero si usted puede conseguir lejos con el uso de un RichTextBox en su lugar, puede usar la propiedad SelectedTabs para establecer el ancho de la pestaña deseada:

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

Tenga en cuenta que estos desplazamientos son píxeles, no caracteres.

5

El ejemplo ofrecido es incorrecto.

El mensaje EM_SETTABSTOPS espera que los tamaños de tabulación se especifiquen en dialog template units y no en píxeles. Después de buscar un poco, parece que una unidad de plantilla de diálogo es igual a 1/4th the average width of the window's character. Por lo tanto, deberá especificar 8 pestañas largas de 2 caracteres, 16 para cuatro caracteres, y así sucesivamente.

Así que el código se puede simplificar como:

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

Gracias, Loris, no estaba al tanto de esto. –

6

Con el uso de métodos de extensión, se puede añadir un nuevo método para la clase de control de cuadro de texto. Este es mi aplicación (incluyendo un método de extensión adicional que le da las coordenadas de la ubicación actual del cursor de inserción) de lo que he reunido a partir de los anteriores colaboradores arriba:

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

gracias! ¡esto es realmente genial! –

+0

¡De nada! En realidad, un refinamiento adicional que agregué a mi propio código comprueba para asegurarse de que TextBox sea Multiline y AcceptsTab esté habilitado. –

+0

Gracias, Brien, ¡esa es una muy buena manera de encapsular esta funcionalidad! – BillW

1

Para cualquier persona que quiera diferentes anchos de pestañas, me tomó este enfoque:

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