2009-08-19 5 views
17

Étant donné un contrôle WinForms TextBox avec MultiLine = true et AcceptsTab == true, comment puis-je définir la largeur du caractère de tabulation affiché? Je veux l'utiliser comme une boîte de saisie de script rapide et sale pour un plugin. Il n'a vraiment pas besoin d'être de fantaisie du tout, mais ce serait bien si les onglets ne sont pas affichés sous forme de 8 caractères large ...Comment définir la largeur TAB dans un contrôle Windows Forms TextBox?

De la réponse acceptée:

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

Cela peut être appelé le constructeur de votre Form, mais attention: Assurez-vous que InitializeComponents est exécuté en premier.

+1

Vous devez également disposer des graphiques, peut-être le mettre en utilisant l'instruction. –

Répondre

7

Je sais que vous utilisez un TextBox actuellement, mais si vous pouvez vous en sortir avec l'aide d'un RichTextBox à la place, vous pouvez utiliser la propriété SelectedTabs pour définir la largeur de la tabulation souhaitée:

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

Notez que ces décalages sont des pixels et non des caractères.

5

L'exemple proposé est incorrect.

Le message EM_SETTABSTOPS s'attend à ce que les tailles d'onglet soient spécifiées en dialog template units et non en pixels. Après quelques recherches, il apparaît qu'une unité de modèle de dialogue est égale à 1/4th the average width of the window's character. Vous devrez donc spécifier 8 pour les onglets de 2 caractères, 16 pour les 4 caractères, et ainsi de suite.

Ainsi, le code peut être simplifié comme:

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

Merci, Loris, je n'étais pas au courant de ça. –

6

Avec l'utilisation de méthodes d'extension, vous pouvez ajouter une nouvelle méthode à la classe de contrôle TextBox. Ceci est ma mise en œuvre (y compris une méthode d'extension supplémentaire qui vous donne les coordonnées de l'emplacement actuel du curseur d'insertion) de ce que je recueillis auprès des contributeurs précédents ci-dessus:

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

merci! c'est vraiment cool! –

+0

De rien! En fait, un raffinement supplémentaire que j'ai ajouté à mon propre code vérifie que la TextBox est Multiline et que AcceptsTab est activé. –

+0

Merci, Brien, c'est une très belle façon d'encapsuler cette fonctionnalité! – BillW

1

Pour tous ceux qui veulent différentes largeurs de l'onglet, je a pris cette approche:

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