Introduction
In this article I present a simple Caret which I have successfully used in a couple of my WPF projects. I hope that it can be useful for others too.
Background
WPF does not provide a Caret control for User Controls. There is a CaretElement
, but it is internal to the framework and undocumented. The presented code can be easily adapted for WinForms as well.
Using the code
Using the caret is pretty straightforward. You only have to create an instance of the Caret and add it as a child to your user control. In order to move the Caret around, you will have to change its Top
and Left
properties. You can change Caret's height using the CaretHeight
property.
public class MyControl : UserControl
{
Caret caret = new Caret();
public MyControl()
{
AddChild(caret);
caret.Top = 100;
caret.Left = 100;
}
}
And here is the Caret
class:
public class Caret : FrameworkElement
{
System.Threading.Timer timer;
Point location;
public double CaretHeight { get; set; }
int blinkPeriod = 500;
Pen pen = new Pen(Brushes.Black, 1);
public static readonly DependencyProperty VisibleProperty =
DependencyProperty.Register("Visible", typeof(bool),
typeof(Caret), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
public Caret()
{
pen.Freeze();
CaretHeight = 18;
Visible = true;
timer = new System.Threading.Timer(blinkCaret, null, 0, blinkPeriod);
}
protected override void OnRender(DrawingContext dc)
{
if (Visible)
{
dc.DrawLine(pen, location, new Point(Left, location.Y + CaretHeight));
}
}
bool Visible
{
get
{
return (bool)GetValue(VisibleProperty);
}
set
{
SetValue(VisibleProperty, value);
}
}
void blinkCaret(Object state)
{
Dispatcher.Invoke(new Action(delegate { Visible = !Visible; }));
}
public double Left
{
get { return location.X; }
set
{
if (location.X != value)
{
location.X = Math.Floor(value) + .5; if (Visible)
{
Visible = false;
}
}
}
}
public double Top
{
get { return location.Y; }
set
{
if (location.Y != value)
{
location.Y = Math.Floor(value) + .5; if (Visible)
{
Visible = false;
}
}
}
}
}