Introduction
One property that the text box controls are lacking is the Padding property which I have added with this user control. This allows you to place a border around the actual text which can improve the look of the text box. The border color may be a different color from the text background in which case it acts to "frame" the text, as in the example above, or it can be the same color in which case it acts as a margin.
Background
Creating this effect is relatively easy and MSDN provides some examples of how to do this using a text box and a panel. However, I would rather create a control with this property and then be able to reuse it subsequently without having to reinvent the wheel each time. After all, isn't that what user controls are for? In this case I have placed a rich text box on a user control surface which acts as the "panel" (as if you were to do it the MSDN way).
The user control code
public partial class PTextBox : UserControl
{
public PTextBox()
{
InitializeComponent();
}
[
Browsable(true),
CategoryAttribute("Appearance"),
Description("The background color of the rich text box.")
]
public Color TextBackColor
{
get
{
return rtb.BackColor;
}
set
{
rtb.BackColor = value;
}
}
[
Browsable(true),
CategoryAttribute("Appearance"),
Description("The foreground color of the rich text box.")
]
public Color TextForeColor
{
get
{
return rtb.ForeColor;
}
set
{
rtb.ForeColor = value;
}
}
[
Browsable(true),
CategoryAttribute("Data"),
Description("The text of the rich text box.")
]
public override string Text
{
get
{
return rtb.Text;
}
set
{
rtb.Text = value;
}
}
public override string ToString()
{
return rtb.ToString();
}
}
Using the code
First compile the control and put the resulting dll in the folder of your choice, preferably one containing your reusable assemblies.
Open the toolbox. Right click and select "Choose items". In the "Choose Toolbox Items" dialog box, browse for PaddedTextBox.dll and select it for your project. Now you can treat this control almost as if it were the built-in rich text box with a few additional properties. In the properties window, I have exposed the Text
property of the rich text box as well as added the TextForeColor
and TextBackColor
properties. The actual ForeColor
and BackColor
properties now apply to the user control, i.e., the border colors although, in this context, the ForeColor
is meaningless. I have also made the rich text box named rtb, public, so programmatically you have full control over it if you need to access or change any other properties or trap any events.
The demo code below shows how to use the control. To simplify things I have created a separate reference to the rich text box so I don't have to keep referring to it via ptb.rtb
. In this case ptb.TextBackColor
and rtb.BackColor
refer to the same property.
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)
{
rtb = ptb.rtb;
rtb.Font = new Font("Tahoma", 12, FontStyle.Bold);
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 = ";
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;
}
private void rtb_Click(object sender, EventArgs e)
{
clickType = 1;
rtb.SelectionLength = 0;
}
private void rtb_DoubleClick(object sender, EventArgs e)
{
clickType = 2;
rtb.SelectionLength = 0;
}
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;
}
private void rtb_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
e.Handled = true;
}
private void szBorder_Scroll(object sender, ScrollEventArgs e)
{
SetPadding();
}
private void Form1_Resize(object sender, EventArgs e)
{
SetPadding();
}
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();
}
}
}
Points of Interest
Here's a little puzzle for you. I'm not sure that there is an easy solution for it that doesn't use reflection but I'd love to hear if there is one. Consider the BackColor
property of the user control. Ideally I would like that and the ForeColor
property to set the eponymous properties of the rich text box, not the user control panel. Then you could add a BorderColor
property to set the background color of the control itself. The problem is that when you implement BorderColor
, it must make a reference to the BackColor
property but that has already been redefined to set the text box background color and, therefore, won't set the background that you want it to.
History
- Release 1.0.0 � 07/26/2007