0

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:
Text Box

I want to make something like this:

Dotted lines

and to be able to type on it.

  • Are those dotted lines inside the textbox? Like if you press "A", it replaces one of the dashes? Or are the dashes like an underline? – LarsTech Nov 03 '20 at 23:39
  • I don't want to have the borders of the textbox, I want to have just the dotted lines like an underline and to be able to type on it – Labinot Aziri Nov 03 '20 at 23:44
  • Put a borderless TextBox inside a Panel (or UserControl) and draw your dotted line in the paint event of that Panel (or UserControl). – LarsTech Nov 03 '20 at 23:46
  • 2
    @LabinotAziri did you do any research? there are lots of resources of how to use the paint events of a control – TheGeneral Nov 04 '20 at 00:12

2 Answers2

1

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:

enter image description here

LarsTech
  • 80,625
  • 14
  • 153
  • 225
1

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:

TextBox Baseline TextBox Baseline dark TextBox Baseline light


If you don't know how to used this code:

  • Add a new class to your Project and name it TextBoxBaseline.
  • Copy the using directives you find here and paste them on top of the class.
  • Copy the rest of the code and replace the default class definition in your class file, without removing the namespace.
  • Build the Project.
  • You'll find the TextBoxBaseline Control in the ToolBox. Open up a Form and drop it on it as usual.
Jimi
  • 29,621
  • 8
  • 43
  • 61