2008-09-24 5 views
7

Je suis à la recherche d'un composant winforms gratuit pour une application que j'écris. J'ai fondamentalement besoin d'une zone de texte qui contient des numéros de ligne dans une colonne latérale. Etre capable de tabuler des données à l'intérieur serait également un atout majeur.Boîte de texte Windows Forms avec des numéros de ligne?

Quelqu'un connaît-il un composant premade qui pourrait faire cela?

+0

Windows sans Windows. S'il-vous-plaît, réparez. M'encourage: p – Svish

Répondre

6

Référencer Wayne's post, voici le code correspondant. Il utilise GDI pour dessiner des numéros de ligne à côté de la zone de texte.

Public Sub New() 
    MyBase.New() 

    'This call is required by the Windows Form Designer. 
    InitializeComponent() 

    'Add any initialization after the InitializeComponent() call 
    SetStyle(ControlStyles.UserPaint, True) 
    SetStyle(ControlStyles.AllPaintingInWmPaint, True) 
    SetStyle(ControlStyles.DoubleBuffer, True) 
    SetStyle(ControlStyles.ResizeRedraw, True) 
End Sub 

Private Sub RichTextBox1_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.SelectionChanged 
    FindLine() 
    Invalidate() 
End Sub 

Private Sub FindLine() 
    Dim intChar As Integer 

    intChar = RichTextBox1.GetCharIndexFromPosition(New Point(0, 0)) 
    intLine = RichTextBox1.GetLineFromCharIndex(intChar) 
End Sub 

Private Sub DrawLines(ByVal g As Graphics, ByVal intLine As Integer) 
    Dim intCounter As Integer, intY As Integer 

    g.Clear(Color.Black) 

    intCounter = intLine + 1 
    intY = 2 
    Do 
     g.DrawString(intCounter.ToString(), Font, Brushes.White, 3, intY) 
     intCounter += 1 

     intY += Font.Height + 1 
     If intY > ClientRectangle.Height - 15 Then Exit Do 
    Loop 
End Sub 

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 
    DrawLines(e.Graphics, intLine) 
End Sub 

Private Sub RichTextBox1_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.VScroll 
    FindLine() 
    Invalidate() 
End Sub 

Private Sub RichTextBox1_UserScroll() Handles RichTextBox1.UserScroll 
    FindLine() 
    Invalidate() 
End Sub 

RichTextBox est redéfinie comme ceci:

Public Class UserControl1 
Inherits System.Windows.Forms.RichTextBox 

Public Event UserScroll() 

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
    If m.Msg = &H115 Then 
     RaiseEvent UserScroll() 
    End If 

    MyBase.WndProc(m) 
End Sub 
End Class 

(. Code en divil sur le forum xtremedotnettalk.com)

+0

est-ce faisable aussi en C#? – Svish

+0

oui, http://www.developerfusion.com/tools/convert/vb-to-csharp/ devrait vous aider à démarrer. Si vous le faites fonctionner, vous devriez le poster comme une réponse pour les autres. – ine

+0

Est-ce «pur» .NET? –

2

Il y a un projet avec le code disponible à http://www.xtremedotnettalk.com/showthread.php?s=&threadid=49661&highlight=RichTextBox.

Vous pouvez vous connecter sur le site pour télécharger le fichier zip avec l'utilisateur/pass: bugmenot/bugmenot

+0

Utilisateur/passe obsolète ... Pensez-vous passer à un stockage «non protégé»? : -/ – DigitalJedi805

+0

Désolé ..Ce n'était pas mon projet et la réponse était il y a 5 ans. Cependant, il semble que la meilleure réponse a saisi le code pertinent et l'a posté ci-dessus. – Wayne

2

Voici un code C# pour cela. Il est basé sur le code de xtremedotnettalk.com référencé par Wayne. J'ai fait quelques changements pour qu'il affiche le texte de l'éditeur, ce que l'original n'a pas fait. Mais, pour être juste, l'auteur du code original a mentionné qu'il avait besoin de travail.

Voici le code (NumberedTextBox.cs)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Text; 
using System.Windows.Forms; 

namespace NumberedTextBoxLib { 
    public partial class NumberedTextBox : UserControl { 
    private int lineIndex = 0; 

    new public String Text { 
     get { 
     return editBox.Text; 
     } 
     set { 
     editBox.Text = value; 
     } 
    } 

    public NumberedTextBox() { 
     InitializeComponent(); 
     SetStyle(ControlStyles.UserPaint, true); 
     SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     SetStyle(ControlStyles.ResizeRedraw, true); 
     editBox.SelectionChanged += new EventHandler(selectionChanged); 
     editBox.VScroll += new EventHandler(OnVScroll); 
    } 

    private void selectionChanged(object sender, EventArgs args) { 
     FindLine(); 
     Invalidate(); 
    } 

    private void FindLine() { 
     int charIndex = editBox.GetCharIndexFromPosition(new Point(0, 0)); 
     lineIndex = editBox.GetLineFromCharIndex(charIndex); 
    } 

    private void DrawLines(Graphics g) { 
     int counter, y; 
     g.Clear(BackColor); 
     counter = lineIndex + 1; 
     y = 2; 
     int max = 0; 
     while (y < ClientRectangle.Height - 15) { 
     SizeF size = g.MeasureString(counter.ToString(), Font); 
     g.DrawString(counter.ToString(), Font, new SolidBrush(ForeColor), new Point(3, y)); 
     counter++; 
     y += (int)size.Height; 
     if (max < size.Width) { 
      max = (int) size.Width; 
     } 
     } 
     max += 6; 
     editBox.Location = new Point(max, 0); 
     editBox.Size = new Size(ClientRectangle.Width - max, ClientRectangle.Height); 
    } 

    protected override void OnPaint(PaintEventArgs e) { 
     DrawLines(e.Graphics); 
     e.Graphics.TranslateTransform(50, 0); 
     editBox.Invalidate(); 
     base.OnPaint(e); 
    } 

    ///Redraw the numbers when the editor is scrolled vertically 
    private void OnVScroll(object sender, EventArgs e) { 
     FindLine(); 
     Invalidate(); 
    } 

    } 
} 

Et voici le code concepteur Visual Studio (NumberedTextBox.Designer.cs) de


namespace NumberedTextBoxLib { 
    partial class NumberedTextBox { 
    /// Required designer variable. 
    private System.ComponentModel.IContainer components = null; 

    /// Clean up any resources being used. 
    protected override void Dispose(bool disposing) { 
     if (disposing && (components != null)) { 
     components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    private void InitializeComponent() { 
     this.editBox = new System.Windows.Forms.RichTextBox(); 
     this.SuspendLayout(); 
     // 
     // editBox 
     // 
     this.editBox.AcceptsTab = true; 
     this.editBox.Anchor = ((System.Windows.Forms.AnchorStyles) ((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
        | System.Windows.Forms.AnchorStyles.Left) 
        | System.Windows.Forms.AnchorStyles.Right))); 
     this.editBox.Location = new System.Drawing.Point(27, 3); 
     this.editBox.Name = "editBox"; 
     this.editBox.Size = new System.Drawing.Size(122, 117); 
     this.editBox.TabIndex = 0; 
     this.editBox.Text = ""; 
     this.editBox.WordWrap = false; 
     // 
     // NumberedTextBox 
     // 
     this.Controls.Add(this.editBox); 
     this.Name = "NumberedTextBox"; 
     this.Size = new System.Drawing.Size(152, 123); 
     this.ResumeLayout(false); 

    } 

    private System.Windows.Forms.RichTextBox editBox; 
    } 
} 
+0

Vieux, mais il devrait utiliser 'editBox.Font' au lieu de' Font' partout, et il serait préférable d'obtenir la position d'une étiquette de numéro en faisant ainsi: 'y = editBox.GetPositionFromCharIndex (editBox.GetFirstCharIndexFromLine (counter - 1)); ' –

1

Je suppose que cela dépend de la taille de la police, J'ai utilisé "Courier New, 9pt, style = bold"

  • Ajout d'un correctif pour un défilement régulier (pas ligne par ligne)
  • Ajout d'un correctif pour les gros fichiers, lorsque la valeur de défilement est supérieure à 16 bits.

NumberedTextBox.cs

public partial class NumberedTextBox : UserControl 
{ 
    private int _lines = 0; 

    [Browsable(true), 
     EditorAttribute("System.ComponentModel.Design.MultilineStringEditor, System.Design","System.Drawing.Design.UITypeEditor")] 
    new public String Text 
    { 
     get 
     { 
      return editBox.Text; 
     } 
     set 
     { 
      editBox.Text = value; 
      Invalidate(); 
     } 
    } 

    private Color _lineNumberColor = Color.LightSeaGreen; 

    [Browsable(true), DefaultValue(typeof(Color), "LightSeaGreen")] 
    public Color LineNumberColor { 
     get{ 
      return _lineNumberColor; 
     } 
     set 
     { 
      _lineNumberColor = value; 
      Invalidate(); 
     } 
    } 

    public NumberedTextBox() 
    { 
     InitializeComponent(); 

     SetStyle(ControlStyles.UserPaint, true); 
     SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     SetStyle(ControlStyles.ResizeRedraw, true); 
     editBox.SelectionChanged += new EventHandler(selectionChanged); 
     editBox.VScroll += new EventHandler(OnVScroll); 
    } 

    private void selectionChanged(object sender, EventArgs args) 
    { 
     Invalidate(); 
    } 

    private void DrawLines(Graphics g) 
    { 
     g.Clear(BackColor); 
     int y = - editBox.ScrollPos.Y; 
     for (var i = 1; i < _lines + 1; i++) 
     { 
      var size = g.MeasureString(i.ToString(), Font); 
      g.DrawString(i.ToString(), Font, new SolidBrush(LineNumberColor), new Point(3, y)); 
      y += Font.Height + 2; 
     } 
     var max = (int)g.MeasureString((_lines + 1).ToString(), Font).Width + 6; 
     editBox.Location = new Point(max, 0); 
     editBox.Size = new Size(ClientRectangle.Width - max, ClientRectangle.Height); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     _lines = editBox.Lines.Count(); 
     DrawLines(e.Graphics); 
     e.Graphics.TranslateTransform(50, 0); 
     editBox.Invalidate(); 
     base.OnPaint(e); 
    } 

    private void OnVScroll(object sender, EventArgs e) 
    { 
     Invalidate(); 
    } 

    public void Select(int start, int length) 
    { 
     editBox.Select(start, length); 
    } 

    public void ScrollToCaret() 
    { 
     editBox.ScrollToCaret(); 
    } 

    private void editBox_TextChanged(object sender, EventArgs e) 
    { 
     Invalidate(); 
    } 
} 

public class RichTextBoxEx : System.Windows.Forms.RichTextBox 
{ 
    private double _Yfactor = 1.0d; 

    [DllImport("user32.dll")] 
    static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam); 

    private enum WindowsMessages 
    { 
     WM_USER = 0x400, 
     EM_GETSCROLLPOS = WM_USER + 221, 
     EM_SETSCROLLPOS = WM_USER + 222 
    } 

    public Point ScrollPos 
    { 
     get 
     { 
      var scrollPoint = new Point(); 
      SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref scrollPoint); 
      return scrollPoint; 
     } 
     set 
     { 
      var original = value; 
      if (original.Y < 0) 
       original.Y = 0; 
      if (original.X < 0) 
       original.X = 0; 

      var factored = value; 
      factored.Y = (int)((double)original.Y * _Yfactor); 

      var result = value; 

      SendMessage(this.Handle, (int)WindowsMessages.EM_SETSCROLLPOS, 0, ref factored); 
      SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref result); 

      var loopcount = 0; 
      var maxloop = 100; 
      while (result.Y != original.Y) 
      { 
       // Adjust the input. 
       if (result.Y > original.Y) 
        factored.Y -= (result.Y - original.Y)/2 - 1; 
       else if (result.Y < original.Y) 
        factored.Y += (original.Y - result.Y)/2 + 1; 

       // test the new input. 
       SendMessage(this.Handle, (int)WindowsMessages.EM_SETSCROLLPOS, 0, ref factored); 
       SendMessage(this.Handle, (int)WindowsMessages.EM_GETSCROLLPOS, 0, ref result); 

       // save new factor, test for exit. 
       loopcount++; 
       if (loopcount >= maxloop || result.Y == original.Y) 
       { 
        _Yfactor = (double)factored.Y/(double)original.Y; 
        break; 
       } 
      } 
     } 
    } 
} 

NumberedTextBox.Designer.cs

partial class NumberedTextBox 
{ 
    /// <summary> 
    /// Required designer variable. 
    /// </summary> 
    private System.ComponentModel.IContainer components = null; 

    /// <summary> 
    /// Clean up any resources being used. 
    /// </summary> 
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    #region Component Designer generated code 

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor. 
    /// </summary> 
    private void InitializeComponent() 
    { 
     this.editBox = new WebTools.Controls.RichTextBoxEx(); 
     this.SuspendLayout(); 
     // 
     // editBox 
     // 
     this.editBox.AcceptsTab = true; 
     this.editBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
     | System.Windows.Forms.AnchorStyles.Left) 
     | System.Windows.Forms.AnchorStyles.Right))); 
     this.editBox.BorderStyle = System.Windows.Forms.BorderStyle.None; 
     this.editBox.Location = new System.Drawing.Point(27, 3); 
     this.editBox.Name = "editBox"; 
     this.editBox.ScrollPos = new System.Drawing.Point(0, 0); 
     this.editBox.Size = new System.Drawing.Size(120, 115); 
     this.editBox.TabIndex = 0; 
     this.editBox.Text = ""; 
     this.editBox.WordWrap = false; 
     this.editBox.TextChanged += new System.EventHandler(this.editBox_TextChanged); 
     // 
     // NumberedTextBox 
     // 
     this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 
     this.Controls.Add(this.editBox); 
     this.Name = "NumberedTextBox"; 
     this.Size = new System.Drawing.Size(150, 121); 
     this.ResumeLayout(false); 

    } 

    private RichTextBoxEx editBox; 

    #endregion 
}