Flat Textbox

F

Filipe Marcelino

Hi,

I'm trying to create a textbox inheriting from the standard textbox. I
would like to:

1. repaint the textbox border;
2. define a color for that border;

Till now I made this:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

namespace Library.Controls
{
public class TextBox : System.Windows.Forms.TextBox
{
private enum MouseState
{
Focused,
Hoover,
Normal
}

private Color borderColor = Color.FromArgb(128, 128, 128);
//Gray
private Color highlightColor = Color.FromArgb(10, 36, 106);
//Blue
private Color hoverColor = Color.Silver; //Silver
private MouseState m_MouseState = MouseState.Normal;

public TextBox()
{
this.MouseEnter += new EventHandler(OnMouseEnter);
this.MouseLeave += new EventHandler(OnMouseLeave);
this.MouseHover += new EventHandler(OnMouseHover);
this.Enter += new EventHandler(OnEnter);
this.Leave += new EventHandler(OnLeave);
this.BorderStyle = BorderStyle.FixedSingle;

SetStyle(ControlStyles.UserPaint, true);

}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawString(Text, Font, new
SolidBrush(ForeColor), new PointF(0, 0));

switch (m_MouseState)
{
case MouseState.Focused:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(highlightColor), 0, 0, Width - 1, Height - 1);
break;
case MouseState.Hoover:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(highlightColor), 0, 0, Width - 1, Height - 1);
break;
case MouseState.Normal:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(borderColor), 0, 0, Width - 1, Height - 1);
break;
}
}

#region Mouse Events
private void OnMouseEnter(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Hoover;
Invalidate();
}
private void OnMouseLeave(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Normal;
Invalidate();
}
private void OnMouseHover(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Hoover;
Invalidate();
}
#endregion

private void OnEnter(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Focused;
Invalidate();
}
private void OnLeave(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Normal;
Invalidate();
}

}
}

The problem is related with the text drawing. Somehow, when editing,
the textbox suddenlly uses other font then the default causing
missreading.

There's any way to solve this situation.


Thanks in advance for your attention,
Filipe Marcelino
 
F

Filipe Marcelino

Hi Cor,

Has you may noticed I already set my textbox borderstyle to FixedSingle
(this.BorderStyle = BorderStyle.FixedSingle;). Now I want to paint that
border (black by default) with blue for example.

If I'm not being clear please make me know to clarify you.


Thanks in advance,
Filipe Marcelino
 
S

Steve Barnett

Try adding this:

protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Refresh();
}

Seemed to fix the problem for me... though there is the problem of painting
the caret to deal with!

Steve
 
F

Filipe Marcelino

Hi Steve,

thanks for your reply but I tried and, in fact, the font doesn't "seems
to change" but it changes. Because we can see that, the caret, stays
way forward to the text. And, at some point, if we right text enough we
lose the sense of were we are writing... can you help me again?


Thanks,
Filipe Marcelino
 
S

Steve Barnett

I've tried but can't get the caret in the right place. To be honest though,
I think you're making a lot of work for yourself with this approach. If I
were to approach this problem, I'd go for creating a standard UserControl
with a text box in it:

partial class txtBox
{
private System.ComponentModel.IContainer components = null;

protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Component Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.txtTest = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// txtTest
//
this.txtTest.BorderStyle =
System.Windows.Forms.BorderStyle.None;
this.txtTest.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtTest.Location = new System.Drawing.Point(2, 2);
this.txtTest.Margin = new System.Windows.Forms.Padding(1);
this.txtTest.Multiline = true;
this.txtTest.Name = "txtTest";
this.txtTest.Size = new System.Drawing.Size(352, 23);
this.txtTest.TabIndex = 0;
this.txtTest.Text = "Test Text";
//
// txtBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.txtTest);
this.Name = "txtBox";
this.Padding = new System.Windows.Forms.Padding(1);
this.Size = new System.Drawing.Size(356, 27);
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private System.Windows.Forms.TextBox txtTest;
}

Important thing to note is the padding on the user control (to give you room
to put the border) and the fact that the text box has no border and is
docked to fill the user control. This means that you don't have to handle
any of the painting of the text box, so won't have to deal with font sizes
or cope with the circumstance where your entered text is longer than the
text box (which your paint routine does not cope with now).

In the main body of the class, you'll need to provide accessors for the key
properties of the text box, but only for those that you desperately need,
such as the "Text" property and any events that you need to pass on.
(Alternatively, you can provide an accessot to get at the TextBox control).

public partial class txtBox : UserControl
{
public txtBox()
{
InitializeComponent();
}

public new string Text
{
get { return txtTest.Text; }
set { txtTest.Text = value; }
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Text box takes care of itself. We just paint our border.
e.Graphics.DrawRectangle(new System.Drawing.Pen(Color.Red), 1, 1,
Width-2, Height-2);
}

}

Obviously, you'll need to insert your logic for handling the mouse events. A
more complete set of code is:

public partial class txtBox : UserControl
{
private enum MouseState
{
Focused,
Hoover,
Normal
}

private Color borderColor = Color.FromArgb(128, 128, 128);
//Gray
private Color highlightColor = Color.FromArgb(10, 36, 106);
//Blue
private Color hoverColor = Color.Silver; //Silver
private MouseState m_MouseState = MouseState.Normal;

public txtBox()
{
InitializeComponent();

txtTest.MouseEnter += new EventHandler(OnMouseEnter);
txtTest.MouseLeave += new EventHandler(OnMouseLeave);
txtTest.MouseHover += new EventHandler(OnMouseHover);
txtTest.Enter += new EventHandler(OnEnter);
txtTest.Leave += new EventHandler(OnLeave);

}

public new string Text
{
get { return txtTest.Text; }
set { txtTest.Text = value; }
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
switch (m_MouseState)
{
case MouseState.Focused:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(Color.Salmon), 0, 0, Width - 1, Height - 1);
break;
case MouseState.Hoover:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(Color.Red), 0, 0, Width - 1, Height - 1);
break;
case MouseState.Normal:
e.Graphics.DrawRectangle(new
System.Drawing.Pen(borderColor), 0, 0, Width - 1, Height - 1);
break;
}
}

#region Mouse Events
private void OnMouseEnter(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Hoover;
Invalidate();
}
private void OnMouseLeave(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Normal;
Invalidate();
}
private void OnMouseHover(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Hoover;
Invalidate();
}
#endregion

private void OnEnter(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Focused;
Invalidate();
}
private void OnLeave(object sender, System.EventArgs e)
{
m_MouseState = MouseState.Normal;
Invalidate();
}

}


That would have been my approach, anyway.It may not be the most efficient
(I'm only a beginner here) but it means I don't have to reproduce any of the
functionality of a text box and I always like it when I don't have a lot of
complicated tuff to do!

HTH
Steve
 
S

Steve Barnett

Filipe
Just had a thought, you can make this even simpler by not overriding the
OnPaint event. Since all you're doing now is drawing the border in a
specific colour, all you need to do is set the background colour of the
UserControl to the border colour you want.

Because you have the 1 pixel margin, the background of the user control is
effectively your border around the text box. So, if you set the background
of the user control, your text box gets a 1 pixel border of that colour.

You can then dump the additional burden of overriding OnPaint. You don't
need to save the mouse state and don't need to Invalidate() the control.
Just set the background in the mouse events.

Just a thought.
Steve
 
F

Filipe Marcelino

Man....you said "(I'm only a beginner here)"!!!
You're a GENIUS beginner NO???? ehehehehhe
Thanks for everything!!!! I'll give it a try.


Many thanks,
Filipe Marcelino
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top