问题描述
我想创建一条虚线,用作在其上键入文本的输入,而不是使用文本框。 例如: 代替文本框: Text Box
我想做这样的事情:
并能够在其上输入。
解决方法
在承载无边界TextBox控件的面板的Paint事件中,您可以像这样绘制它:
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));
}
}
最终看起来像这样:
,您可以尝试使用从TextBox派生的自定义控件。
覆盖其WndProc并处理WM_PAINT
,您可以在编辑控件的ClientArea内部绘制虚线(或其他虚线)。然后在按下键时刷新线条图,这样线条就不会被擦除。
WM_KEYDOWN
,WM_LBUTTONDOWN
和WM_CAPTURECHANGED
也被处理,因为它们可以(将)导致背景的绘制。
使用FontFamily的GetLineSpacing()和GetCellAscent()方法计算基线的位置,然后向下移动用于划清界线。
字体更改时,OnFontChanged()被覆盖以获取通知。
此处有更多信息:Properly draw text using Graphics Path
有点原始,但是看看进展如何:)
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;
}
}
}
它看起来像这样:
如果您不知道如何使用此代码:
- 在您的项目中添加一个新类,并将其命名为
TextBoxBaseline
。 - 复制您在此处找到的
using
指令,并将其粘贴到类的顶部。 - 复制其余代码并替换类文件中的默认类定义,而不删除名称空间。
- 构建项目。
- 您将在工具箱中找到
TextBoxBaseline
控件。像往常一样打开一个窗体并将其放在上面。