简体   繁体   中英

Adding guidelines to a TextBox/RichTextBox

Is there any way to show gridlines on a multiline textbox or a richtextbox? Perhaps by overriding the OnPaint event?

I am using the textbox to insert address information, for each line it would be something like:

Street
City
Country
etc.

I am using WinForms with C#.

You can do it using one of these methods:

  • Customize Paint of TextBox
  • Using RTF Tricks

and here is a screenshot of these 2 ways:

在此处输入图片说明

I recommend using first method if you really want this feature.

1- Customizing Paint of TextBox


Customizing textbox paint in not straightforward. You can customize paint of TextBox in different ways. here is 2 way of customize painting of TextBox.

1-1 Customizing Paint of TextBox using NativeWindow


In this way should subclass a TextBox using NativeWindow and handle WM_PAINT in window procedure. Here is a complete code listing that implements what you need.

To use code it is enough to pass your textbox to an instance of CustomPaintTextBox:

var t = new CustomControls.CustomPaintTextBox(this.textBox1);

And here is the code of CustomPaintTextBox

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace CustomControls
{
    public class CustomPaintTextBox : NativeWindow
    {
        private TextBox parentTextBox;
        private const int WM_PAINT = 15;
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_PAINT: 
                    // invalidate textbox to make it refresh
                    parentTextBox.Invalidate();
                    // call default paint
                    base.WndProc(ref m);
                    // draw custom paint
                    this.CustomPaint();
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        public CustomPaintTextBox(TextBox textBox)
        {
            this.parentTextBox = textBox;
            textBox.TextChanged += textBox_TextChanged;
            // subscribe for messages
            this.AssignHandle(textBox.Handle);
        }
        void textBox_TextChanged(object sender, EventArgs e)
        {
            CustomPaint();
        }
        private void CustomPaint()
        {
            var g= this.parentTextBox.CreateGraphics();
            float y = 0;
            var lineHeight = g.MeasureString("X", this.parentTextBox.Font).Height;
            while (y < this.parentTextBox.Height)
            {
                y += lineHeight;
                g.DrawLine(Pens.Red, 0f, y, (float)this.parentTextBox.Width, y);
            }
        }
    }
}

The up side of this solution is its is quiet simple and doesn't need new inherited textbox.

1-2- Creating Transparent TextBox


This way you should first Make a transparent text box and then set the background of it to your gridlines that you want. Since this way is also a way of creating custom paint textbox, you can customize the painting of that textbox too and bend it to your will.

Here is link to 2 greate articles that cover Transparent TextBox and Transparent RichTextBox:

2- Using RTF tricks


There is some rtf tricks than you ca use to show grid lines in RichTextBox. One of best tricks is using tables in RTF. In below code We used 3 rows that contains a cell of width 2000 twips:

this.richTextBox1.SelectAll();
this.richTextBox1.SelectedRtf =
@"{\rtf1\ansi\deff0
{\trowd
\cellx2000
\intbl Street\cell
\row}
{\trowd
\cellx2000
\intbl City\cell
\row}
{\trowd
\cellx2000
\intbl Country\cell
\row}
}";

Important: When pasting above code in code editor, be careful to put no indents before richtext characters. If Visual studio inserted indent before them, you remove all indents.

Start with this code:

class GridLineTextBox : TextBox
{
    public GridLineTextBox()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        var y = 0f;
        var lineHeight = e.Graphics.MeasureString("W", Font).Height;
        while (y < e.ClipRectangle.Height)
        {
            y += lineHeight;
            e.Graphics.DrawLine(System.Drawing.Pens.Aqua, new PointF(0, y), new PointF(e.ClipRectangle.Width, y));
        }
    }
}

Maybe an RTF template file:

{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
{\trowd \trgaph180
\cellx3440\pard\intbl [0]\cell
\row
\trowd \trgaph180
\cellx3440\pard\intbl [1]\cell
\row
\trowd \trgaph180
\cellx3440\pard\intbl [2]\cell
\row
\para}

Dim fileContents As String
fileContents = My.Computer.FileSystem.ReadAllText("C:\temp\template.rtf")
Dim sRTF As String = fileContents.Replace("[0]", "line 1").Replace("[1]", "line 2").Replace("[2]", "line 3")
RichTextBox1.Rtf = sRTF

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM