Текстовое поле Windows Forms с номерами строк?

Я ищу бесплатный компонент winforms для приложения, которое я пишу. Мне в основном нужно текстовое поле, содержащее номера строк в боковом столбце. Возможность сводить данные в таблицу также была бы большим плюсом.

Кто-нибудь знает готовый компонент, который мог бы это сделать?

Windows, а не Windows. Пожалуйста исправьте. Меня беспокоит: p

Svish 02.03.2009 20:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
1
8 538
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Взгляните на исходный код компилятора / IDE SharpDevelop C#. У них есть сложное текстовое поле с номерами строк. Вы можете посмотреть на источник, выяснить, что они делают, а затем реализовать это самостоятельно.

Вот пример того, о чем я говорю: альтернативный текст http://community.sharpdevelop.net/photos/mattward/images/original/FeatureTourQuickClassBrowser.aspx

There is a project with code available at http://www.xtremedotnettalk.com/showthread.php?s=&threadid=49661&highlight=RichTextBox.

Вы можете авторизоваться на сайте, чтобы загрузить zip-файл с пользователем / pass: bugmenot / bugmenot

Устаревший пользователь / пароль ... Рассмотрите возможность перехода в «незащищенное» хранилище? : - /

DigitalJedi805 10.10.2013 01:14

Извините ... это был не мой проект, и ответ был получен 5 лет назад. Однако похоже, что верхний ответ взял соответствующий код и разместил его выше.

Wayne 11.10.2013 00:05
Ответ принят как подходящий

Ссылаясь на Сообщение Уэйна, вот соответствующий код. Он использует GDI для рисования номеров строк рядом с текстовым полем.

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 переопределяется следующим образом:

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

(Код от divil на форуме xtremedotnettalk.com.)

возможно ли это и на C#?

Svish 05.03.2009 21:52

да, developerfusion.com/tools/convert/vb-to-csharp должен помочь вам начать. если он у вас заработает, вы должны опубликовать его как ответ в качестве ресурса для других.

ine 05.03.2009 21:56

В CodePlex для .net есть компонент редактирования исходного кода, http://www.codeplex.com/ScintillaNET

Вот код на C# для этого. Он основан на коде с xtremedotnettalk.com, на который ссылается Уэйн. Я внес некоторые изменения, чтобы он действительно отображал текст редактора, чего не было в оригинале. Но, честно говоря, автор исходного кода упомянул, что над этим нужно доработать.

Вот код (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();
    }

  }
}

А вот и код конструктора Visual Studio (NumberedTextBox.Designer.cs)


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

Старый, но он должен везде использовать editBox.Font вместо Font, и было бы лучше получить позицию числовой метки, сделав это: y = editBox.GetPositionFromCharIndex(editBox.GetFirstCharIndexFr‌​omLine(counter - 1));

Léon Pelletier 01.12.2017 19:25

Думаю, это зависит от размера шрифта, я использовал "Courier New, 9pt, style = bold"

  • Добавлено исправление для плавной прокрутки (не построчно)
  • Добавлено исправление для больших файлов, когда значение прокрутки превышает 16 бит.

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
}

Другие вопросы по теме