65.9K
CodeProject 正在变化。 阅读更多。
Home

带衬垫的文本框控件

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.33/5 (3投票s)

2007年3月28日

3分钟阅读

viewsIcon

78235

downloadIcon

1014

一个向富文本框控件添加新属性的用户控件。

引言

文本框控件缺少的一个属性是填充属性,我已经通过这个用户控件添加了它。这允许您在实际文本周围放置边框,这可以改善文本框的外观。边框颜色可能与文本背景颜色不同,在这种情况下,它充当文本的“框架”,如上例所示,或者它可以是相同的颜色,在这种情况下,它充当边距。

背景

创建此效果相对容易,MSDN 提供了一些使用文本框和面板执行此操作的示例。但是,我更愿意创建一个具有此属性的控件,然后能够重复使用它,而不必每次都重新发明轮子。毕竟,这不正是用户控件的用途吗?在这种情况下,我已将一个富文本框放置在用户控件表面上,该表面充当“面板”(就像您要按照 MSDN 的方式进行操作一样)。

用户控件代码

public partial class PTextBox : UserControl
{
/// <summary>
/// PTextBox is a simple user control which provides the missing "Padding"
/// property to a rich text box.  This allows the user to define a border
/// around the text.  This border can be the same color as the text box
/// in which case it is simply an inner padding or it can be a true border
/// of a different color.
/// <remarks>
/// The two properties of import are the padding size and the background
/// color of the control which acts as the border color for the text box.
/// The rich text box itself is exposed via the "rtb" control which is
/// public.
/// </remarks>
/// </summary>
    public PTextBox()
    {
        InitializeComponent();
    }

    /// <summary>
    /// This property allows the user to set the background color
    /// of the rich text box at design time.
    /// </summary>
    [
        Browsable(true),
        CategoryAttribute("Appearance"),
        Description("The background color of the rich text box.")
    ]

    public Color TextBackColor
    {
        get
        {
            return rtb.BackColor;
        }
        set
        {
            rtb.BackColor = value;
        }
    }

    /// <summary>
    /// This property allows the user to set the foreground color
    /// of the rich text box at design time.
    /// </summary>
    [
        Browsable(true),
        CategoryAttribute("Appearance"),
        Description("The foreground color of the rich text box.")
    ]

    public Color TextForeColor
    {
        get
        {
        return rtb.ForeColor;
        }
        set
        {
        rtb.ForeColor = value;
        }
    }

    /// <summary>
    /// This property allows the user to set the text property
    /// of the textbox directly without having to use the "rtb" property.
    /// </summary>
    [
        Browsable(true),
        CategoryAttribute("Data"),
        Description("The text of the rich text box.")
    ]

    public override string Text
    {
        get
        {
        return rtb.Text;
        }
        set
        {
        rtb.Text = value;
        }
    }

    /// <summary>
    /// The ToString() value of the rich text box.
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return rtb.ToString();
    }
}

使用代码

首先编译控件,并将生成的 dll 放入您选择的文件夹中,最好是包含您可重用程序集的文件夹。

打开工具箱。右键单击并选择“选择项目”。在“选择工具箱项目”对话框中,浏览到 *PaddedTextBox.dll* 并将其选中用于您的项目。现在,您可以像对待内置的富文本框一样对待此控件,并具有一些附加属性。在属性窗口中,我公开了富文本框的 `Text` 属性,并添加了 `TextForeColor` 和 `TextBackColor` 属性。实际的 `ForeColor` 和 `BackColor` 属性现在应用于用户控件,即边框颜色,尽管在这种情况下,`ForeColor` 毫无意义。我还将富文本框命名为 rtb,将其设为 public,因此您可以在程序中完全控制它,如果您需要访问或更改任何其他属性或捕获任何事件。

下面的演示代码显示了如何使用该控件。为了简化操作,我创建了对富文本框的单独引用,这样我就不必一直通过 `ptb.rtb` 来引用它。在这种情况下,`ptb.TextBackColor` 和 `rtb.BackColor` 指的是同一属性。

using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Test
{
    public partial class Form1 : Form
    {
        private RichTextBox rtb;
        private byte clickType = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Use "rtb" to access the text box within the user control:
            rtb = ptb.rtb;
            rtb.Font = new Font("Tahoma", 12, FontStyle.Bold);
            // Note that we could also use rtb.Text here since they are essentially
            // the same:
            ptb.Text = "Click to change the text box background color.\r\n\r\n" +
                       "Double click to change the border color.\r\n\r\n" +
                       "Use the horizontal slider below to change the border size.\r\n\r\n" +
                       "Padding = ";
            // Set up traps for the text box events that you want to handle
            rtb.Click += new System.EventHandler(this.rtb_Click);
            rtb.DoubleClick += new System.EventHandler(this.rtb_DoubleClick);
            rtb.KeyDown += new System.Windows.Forms.KeyEventHandler(this.rtb_KeyDown);
            szBorder.Value = ptb.Padding.All;
            SetPadding();
            timer1.Interval = 500;
            timer1.Enabled = true;
        }

        /// <summary>
        /// Click to change the text box background color
        /// </summary>
        private void rtb_Click(object sender, EventArgs e)
        {
            clickType = 1;
            rtb.SelectionLength = 0;  // Prevent the click from causing a selection
        }

        /// <summary>
        /// Double click to change the border color
        /// </summary>
        private void rtb_DoubleClick(object sender, EventArgs e)
        {
            clickType = 2;
            rtb.SelectionLength = 0;  // Prevent the click from causing a selection
        }

        /// <summary>
        /// We use the timer to allow a doubleclick to be handled without first
        /// generating a single click event.
        /// </summary>
        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            if (clickType == 1)
            {
                DialogResult dr = this.colorDialog1.ShowDialog();
                if (dr == DialogResult.OK) ptb.TextBackColor = this.colorDialog1.Color;
            }
            else if (clickType == 2)
            {
                DialogResult dr = this.colorDialog1.ShowDialog();
                if (dr == DialogResult.OK) ptb.BackColor = this.colorDialog1.Color;
            }
            clickType = 0;
            timer1.Enabled = true;
        }

        /// <summary>
        /// You can trap key presses here.  This text box should be read-only
        /// so we don't allow any keystrokes in it.
        /// </summary>
        private void rtb_KeyDown(object sender, KeyEventArgs e)
        {
            e.SuppressKeyPress = true;
            e.Handled = true;   // This isn't required
        }

        private void szBorder_Scroll(object sender, ScrollEventArgs e)
        {
            SetPadding();
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            SetPadding();
        }

        /// <summary>
        /// The scroll bar returns values between 0 and 100 inclusive.  Use that value
        /// as a percentage of half the smallest of the height and width to determine
        /// the border padding.  Note that the padding is uniform and does NOT
        /// reflect any difference between the height and width.
        /// </summary>
        private void SetPadding()
        {
            ptb.Padding = new Padding(Convert.ToInt32(szBorder.Value * .005 *
                (this.Width > this.Height ? this.Height : this.Width)));
            int i = rtb.Text.IndexOf("Padding =");
            rtb.Text = rtb.Text.Substring(0, i) + "Padding = " + ptb.Padding.All.ToString();
        }
    }
}

关注点

这是一个小谜题。我不确定是否有不需要使用反射的简单解决方案,但我很乐意听取意见。考虑用户控件的 `BackColor` 属性。理想情况下,我希望该属性和 `ForeColor` 属性设置富文本框的同名属性,而不是用户控件面板。然后,您可以添加一个 `BorderColor` 属性来设置控件本身的背景颜色。问题是,当您实现 `BorderColor` 时,它必须引用 `BackColor` 属性,但该属性已被重新定义为设置文本框背景颜色,因此,它不会设置您想要的背景。

历史

  • 版本 1.0.0 – 2007 年 7 月 26 日
© . All rights reserved.