不知何故,我设法让自己再次进入一个地方,Google或我的问题措辞都没有给我一个解决方案。
所以,就这样说,我从头开始创建TextBox
,派生自System.Windows.Forms.Control
。到目前为止,我已经能够绘制Text
变量,并且还为其添加了编辑功能(通常像普通TextBox
一样)。
可怕的耗时练习的想法是创建我自己的自定义控件库,这些控件具有最大的主题功能,可以与我开发的软件一起使用。
所以,我的问题:在TextBox
中绘制闪烁的光标。
我能够绘制一条静态线,它根据CursorPosition
所取的位置从左向右移动。通过if(blinker)
向控件添加了一个计时器(因此System.Timers.Timer
)并尝试了System.Windows.Forms.Timer
但是在添加控件时不允许我设置任何属性而弄乱了我的Designer到一个表格,仍然没有启动我的绘图事件。我确实在Invalidate(_Cursor)
事件中放置了Tick
,以确保只重绘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);
}
}
答案 0 :(得分:0)
好吧,所以在我决定放弃并停止尝试之后,我删除了光标的每一条痕迹,并开始重新绘制它。得到了修复。然后我回去看望计时器,并认为当不使用从System.Windows.Forms.Form
派生的类时,System.Windows.Forms.Timer
会让你认为自己已经拥有的每一盎司都变得混乱。所以,我转到了System.Timers.Timer(我之前在Mobile Development上使用过,取得了巨大的成功)。
我遇到的所有问题现已解决,再次感谢您的帮助!我爱这个地方。
以下是代码更改:
private double _CursorInterval;
/// <summary>
/// Values below 500ms not recommended, due to safety hazards on epilepsy.
/// </summary>
public double CursorInterval
{
get { return _CursorInterval; }
set { _CursorInterval = value; }
}
private bool blink = false;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Height = TextRenderer.MeasureText("A", Font).Height + (2 * BorderWidth) + (2 * TextPadding);
_InputBounds = new Rectangle(BorderWidth + TextPadding, BorderWidth + TextPadding, Width - (2 * BorderWidth) - (2 * TextPadding), Height - (2 * BorderWidth) - (2 * TextPadding));
if (blink)
e.Graphics.FillRectangle(new SolidBrush(BorderColor), new Rectangle(_InputBounds.Location, new Size(1, _InputBounds.Height)));
}
System.Timers.Timer blinkTimer;
protected override void OnGotFocus(EventArgs e)
{
if (!DesignMode)
{
blinkTimer = new System.Timers.Timer(CursorInterval);
blinkTimer.Elapsed += TimerElapsed;
blinkTimer.Start();
Console.WriteLine("OnGotFocus - I was here.");
}
blink = true;
Invalidate();
base.OnGotFocus(e);
}
private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
blink = !blink;
Console.WriteLine("TimerElapsed - I was here.");
Invalidate();
}
protected override void OnLostFocus(EventArgs e)
{
if(!DesignMode)
{
blink = false;
blinkTimer.Stop();
blinkTimer.Elapsed -= TimerElapsed;
Console.WriteLine("OnLostFocus - I was here.");
}
Invalidate();
base.OnLostFocus(e);
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
Focus();
}