不知何故,我设法让自己重新找到一个地方,Google或我的问题的措辞都不能解决问题。将定时器添加到自定义控件以创建闪烁光标
因此,要这样说,我要创建一个TextBox
从零开始,从System.Windows.Forms.Control
派生。到目前为止,我已经能够绘制Text
变量,并且还添加了编辑功能(正常的TextBox
通常会这样做)。
可怕的耗时练习的想法是创建我自己的自定义控件库,它具有与我开发的软件一起使用的最大主题功能。
所以,我的问题:在TextBox
中绘制闪烁的光标。
我可以绘制一条静态线,该线从左至右移动,具体取决于CursorPosition
拍摄的位置。向控件添加了一个计时器(因此if(blinker)
)到System.Timers.Timer
并且还尝试了System.Windows.Forms.Timer
,但是通过不允许我在将控件添加到表单时设置我的任何属性并且仍然无法启动绘图事件。我确实在Tick
事件中放置了Invalidate(_Cursor)
,以确保只有Cursor位置被重新绘制,甚至在没有参数的情况下尝试,仍然无济于事。
protected override void OnPaint(PaintEventArgs e)
{
...
if (Focused)
{
if (blinker)
e.Graphics.FillRectangle(new SolidBrush(_CursorColor), _Cursor);
foreach (Rectangle border in Borders)
{
if(_DrawBorders[Borders.IndexOf(border)])
e.Graphics.FillRectangle(new SolidBrush(BorderColor), border);
}
}
...
}
我还设置
DoubleBuffered = true;
SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable | ControlStyles.ResizeRedraw |
ControlStyles.OptimizedDoubleBuffer | ControlStyles.StandardClick | ControlStyles.AllPaintingInWmPaint, true);
与一个可怕的闪烁和输入的问题我有帮助。
EDIT **(REMOVED AS IT IS FIXED USING COMMENT BY Hans Passant's SUGGESTION)**
好了,现在该定时器的工作,对这个问题我上面所述。绘制光标。
private void _CursorBlinkTime_Tick(object sender, EventArgs e)
{
blinker = !blinker;
Console.WriteLine("Blink!");
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
Height = TextRenderer.MeasureText("A", Font).Height + (2 * BorderWidth) + (2 * TextPadding);
CursorPosition = (BorderWidth + TextPadding) + (_SelectedStart * (TextRenderer.MeasureText("_", Font).Width));
_InputBounds = new Rectangle(BorderWidth + TextPadding, BorderWidth + TextPadding, Width - (2 * BorderWidth) - (2 * TextPadding), Height - (2 * BorderWidth));
base.OnPaint(e);
e.Graphics.Clear(BackColor);
e.Graphics.DrawString(Text, Font, new SolidBrush(TextColor), _InputBounds.Location);
foreach (Rectangle border in Borders)
{
if (_DrawBorders[Borders.IndexOf(border)])
e.Graphics.FillRectangle(new SolidBrush(InactiveBorderColor), border);
}
if (Focused)
{
// This is where the Cursor is drawn, right before the borders.
// I've tried to move it to after the border is drawn but same result, nothing is drawn.
// I've ran through the entire OnPaint using Step-by-Step and while it does
// fire the draw event, nothing is drawn.
// BackColor = FromArgb(40,40,40), _CursorColor = Color.Red
// _Cursor is a Rectangle that reads at this moment:
// Rectangle(5,0,2,21) Which given all other variables should show result?
if (blinker)
e.Graphics.FillRectangle(new SolidBrush(_CursorColor), _Cursor);
foreach (Rectangle border in Borders)
{
if(_DrawBorders[Borders.IndexOf(border)])
e.Graphics.FillRectangle(new SolidBrush(BorderColor), border);
}
}
else if (!Focused)
{
if(string.IsNullOrWhiteSpace(Text))
e.Graphics.DrawString(WaterMarkText, Font, new SolidBrush(WaterMarkColor), _InputBounds.Location);
}
}
所以你的问题是只有在VS设计师?您可以添加一个条件来启动计时器,如下所示:'if(!DesignMode)yourtimer.Start();' – TaW
只有当控件第一次获得焦点时才启动计时器,然后在焦点丢失时停止。只是添加计时器到课堂的事实阻止我使用VS Desinger,我会添加我的设计器的截图到原始文章并添加。 – Hurly
计时器应该是* static *,以便它可以闪烁任何控制。最好创建它(如果为null),并在OnEnter/OnLeave()的重载中取消/订阅其Tick事件。同时确保它不会在设计时使用,也不会“搞砸”任何东西。 –