我有以下代码:
public class OurTextBox : TextBox
{
public OurTextBox()
: base()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen penBorder = new Pen(Color.Gray, 1);
Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
e.Graphics.DrawRectangle(penBorder, rectBorder);
}
}
这是完美的,但在获得焦点之前不会显示文字。
任何人都可以帮助我吗?有什么问题?
提前感谢。
答案 0 :(得分:27)
要更改TextBox
的边框颜色,您可以覆盖WndProc
方法并处理WM_NCPAINT
消息。然后使用GetWindowDC
获取控件的窗口设备上下文,因为我们想要绘制到非客户端控制区域。然后绘制,它足以从该上下文创建一个Graphics
对象,然后绘制边框以进行控制。
要在BorderColor
属性更改时重绘控件,可以使用RedrawWindow
方法。
<强>代码强>
这是TextBox
,其BorderColor
属性。如果属性值不同于BorderColor
且Color.Transparent
是其默认值BorderStyle
,则控件使用Fixed3d
。
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyTextBox : TextBox {
const int WM_NCPAINT = 0x85;
const uint RDW_INVALIDATE = 0x1;
const uint RDW_IUPDATENOW = 0x100;
const uint RDW_FRAME = 0x400;
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprc, IntPtr hrgn, uint flags);
Color borderColor = Color.Blue;
public Color BorderColor {
get { return borderColor; }
set { borderColor = value;
RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
}
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == WM_NCPAINT && BorderColor != Color.Transparent &&
BorderStyle == System.Windows.Forms.BorderStyle.Fixed3D) {
var hdc = GetWindowDC(this.Handle);
using (var g = Graphics.FromHdcInternal(hdc))
using (var p = new Pen(BorderColor))
g.DrawRectangle(p, new Rectangle(0, 0, Width - 1, Height - 1));
ReleaseDC(this.Handle, hdc);
}
}
protected override void OnSizeChanged(EventArgs e) {
base.OnSizeChanged(e);
RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
}
}
<强>结果强>
以下是使用不同颜色和不同状态的结果。支持所有边框样式的状态,如下图所示,您可以使用任何颜色作为边框:
下载强>
您可以克隆或下载工作示例:
答案 1 :(得分:5)
您还必须手动绘制文字。
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen penBorder = new Pen(Color.Gray, 1);
Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
e.Graphics.DrawRectangle(penBorder, rectBorder);
Rectangle textRec = new Rectangle(e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
TextRenderer.DrawText(e.Graphics, Text, this.Font, textRec, this.ForeColor, this.BackColor, TextFormatFlags.Default);
}
或者,如果e.Graphics.DrawString()
没有给出您想要的结果,您可以尝试使用TextRenderer
方法(我总是通过这种方法获得更好的结果)。
答案 2 :(得分:1)
有几种方法可以做到这一点,没有一种方法是理想的。这只是WinForms的本质。但是,你有一些选择。我将总结一下:
您可以通过在TextBox
中嵌入Panel
来实现您想要的目标。
public class BorderedTextBox : Panel
{
private TextBox textBox;
private bool focusedAlways = false;
private Color normalBorderColor = Color.Gray;
private Color focusedBorderColor = Color.Red;
public BorderTextBox()
{
this.DoubleBuffered = true;
this.Padding = new Padding(2);
this.TextBox = new TextBox();
this.TextBox.AutoSize = false;
this.TextBox.BorderStyle = BorderStyle.None;
this.TextBox.Dock = DockStyle.Fill;
this.TextBox.Enter += new EventHandler(this.TextBox_Refresh);
this.TextBox.Leave += new EventHandler(this.TextBox_Refresh);
this.TextBox.Resize += new EventHandler(this.TextBox_Refresh);
this.Controls.Add(this.TextBox);
}
private void TextBox_Refresh(object sender, EventArgs e)
{
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.Clear(SystemColors.Window);
using (Pen borderPen = new Pen(this.TextBox.Focused || FocusedAlways ?
focusedBorderColor : normalBorderColor))
{
e.Graphics.DrawRectangle(borderPen,
new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
}
base.OnPaint(e);
}
public TextBox TextBox
{
get { return textbox; }
set { textbox = value; }
}
public bool FocusedAlaways
{
get { return focusedAlways; }
set { focusedAlways = value; }
}
}
您也可以在不覆盖任何控件的情况下执行此操作,但上述方法更好。当控件获得焦点时,上面将绘制边框。如果您想要永久使用边框,请将FocusedAlways
属性设置为True
。
我希望这会有所帮助。
答案 3 :(得分:1)
将文本框边框样式设置为无 然后将此代码写入容器表单“paint”事件
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X, TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height);
rect.Inflate(1, 1); // border thickness
System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect, Color.DeepSkyBlue, ButtonBorderStyle.Solid);
}