I want to create a dotted lines that is used as input for typing text on it instead using a text box.
For example:
Instead of text box:
I want to make something like this:
and to be able to type on it.
I want to create a dotted lines that is used as input for typing text on it instead using a text box.
For example:
Instead of text box:
I want to make something like this:
and to be able to type on it.
In the Paint event of a panel that is hosting a borderless TextBox control, you can draw it like this:
private void Panel1_Paint(object sender, PaintEventArgs e) {
using (Pen p = new Pen(Color.Black)) {
p.DashStyle = DashStyle.Dash;
e.Graphics.DrawLine(p, new Point(textBox1.Left, textBox1.Bottom + 2),
new Point(textBox1.Right, textBox1.Bottom + 2));
}
}
Ends up looking like this:
You can try with a Custom Control derived from TextBox.
Overriding its WndProc and handling WM_PAINT
, you can draw a dotted/dashed line (or anything else) inside the edit control's ClientArea. Then refresh the line drawing when keys are pressed, so the line is not erased.
WM_KEYDOWN
, WM_LBUTTONDOWN
and WM_CAPTURECHANGED
are also handled, since these can (will) cause the painting of the background.
The position of the base line is calculated using the FontFamily's GetLineSpacing() and GetCellAscent() methods, then moved down the size of the Pen used to draw the line.
OnFontChanged() is overridden to get a notification when the Font changes.
Some more info here: Properly draw text using Graphics Path
It's a little raw, but see how it goes :)
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
[ToolboxItem(true)]
[DesignerCategory("Code")]
public class TextBoxBaseline : TextBox
{
private const int WM_PAINT = 0x000F;
private const int WM_KEYDOWN = 0x0100;
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_CAPTURECHANGED = 0x0215;
private float m_lnSpacing = 0.0f;
private float m_cellAscent = 0.0f;
public TextBoxBaseline() {
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.BorderStyle = BorderStyle.None;
}
protected override void OnFontChanged(EventArgs e) {
base.OnFontChanged(e);
m_lnSpacing = Font.FontFamily.GetLineSpacing(Font.Style);
m_cellAscent = Font.FontFamily.GetCellAscent(Font.Style);
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
switch (m.Msg) {
case WM_PAINT:
using (var g = Graphics.FromHwnd(this.Handle))
using (Pen pen = new Pen(Color.DimGray, 1)) {
pen.DashStyle = DashStyle.Dash;
int baseLine = (int)(Font.GetHeight(g) * m_cellAscent / m_lnSpacing + pen.Width);
g.DrawLine(pen, 1, baseLine, ClientSize.Width - 1, baseLine);
m.Result = IntPtr.Zero;
}
break;
case WM_KEYDOWN:
case WM_LBUTTONDOWN:
case WM_CAPTURECHANGED:
this.Invalidate();
break;
}
}
}
It looks like this:
If you don't know how to used this code:
TextBoxBaseline
.using
directives you find here and paste them on top of the class.TextBoxBaseline
Control in the ToolBox. Open up a Form and drop it on it as usual.