简体   繁体   English

将准则添加到TextBox / RichTextBox

[英]Adding guidelines to a TextBox/RichTextBox

Is there any way to show gridlines on a multiline textbox or a richtextbox? 有什么方法可以在多行文本框或RichTextBox上显示网格线? Perhaps by overriding the OnPaint event? 也许是通过覆盖OnPaint事件?

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#. 我在C#中使用WinForms。

You can do it using one of these methods: 您可以使用以下方法之一进行操作:

  • Customize Paint of TextBox 自定义TextBox的绘制
  • Using RTF Tricks 使用RTF技巧

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 1-自定义TextBox的绘制


Customizing textbox paint in not straightforward. 自定义文本框绘制并不简单。 You can customize paint of TextBox in different ways. 您可以用不同的方式自定义TextBox的绘制。 here is 2 way of customize painting of TextBox. 这是自定义TextBox绘画的2种方法。

1-1 Customizing Paint of TextBox using NativeWindow 1-1使用NativeWindow自定义TextBox的绘制


In this way should subclass a TextBox using NativeWindow and handle WM_PAINT in window procedure. 这样,应该使用NativeWindow子类化TextBox并在窗口过程中处理WM_PAINT。 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: 要使用代码,只需将您的文本框传递到CustomPaintTextBox的实例即可:

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

And here is the code of CustomPaintTextBox 这是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 1-2-创建透明文本框


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条涵盖透明文本框和透明RichTextBox的重要文章的链接:

2- Using RTF tricks 2-使用RTF技巧


There is some rtf tricks than you ca use to show grid lines in RichTextBox. 除了在RichTextBox中显示网格线外,还有一些rtf技巧。 One of best tricks is using tables in RTF. 最好的技巧之一是在RTF中使用表格。 In below code We used 3 rows that contains a cell of width 2000 twips: 在下面的代码中,我们使用了3行,其中包含一个宽度为2000缇的单元格:

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. 重要说明:在代码编辑器中粘贴以上代码时,请注意不要在RTF字符前插入缩进。 If Visual studio inserted indent before them, you remove all indents. 如果Visual Studio在它们之前插入了缩进,则将删除所有缩进。

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: 也许是RTF模板文件:

{\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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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