防止选择 TextBox 中的文本
Prevent selecting text in a TextBox
已经有人问过类似的问题(例如,here),但是我还没有找到针对我的具体情况的答案。我正在构建一个基于 DevExpress 控件的自定义控件,该控件又基于标准 TextBox
并且我有一个闪烁的问题,这似乎是由于尝试更新选择的基本 TextBox 组件造成的。
无需解释我的自定义控件的所有细节,要重现该问题,您只需将 TextBox
放在 Form
中,然后使用此代码:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
textBox1.MouseMove += TextBox1_MouseMove;
}
private void TextBox1_MouseMove(object sender, MouseEventArgs e) {
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
}
}
如果启动它,单击 TextBox
,然后将光标向右移动,您会注意到闪烁问题(参见视频 here)。对于我的自定义控件,我需要避免这种闪烁。我必须使用 TextBox
(所以没有 RichTextBox
)。有什么想法吗?
根据你想做什么,有几种解决方案:
如果你想阻止 selection 它将是:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectionLength = 0;
}
或select全部:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectAll();
}
除此之外,您还可以指定 selecting 的条件,例如:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
if (MouseButtons == MouseButtons.Left) (sender as TextBox).SelectAll();
else (sender as TextBox).SelectionLength = 0;
}
但是只要你想 select 文本你总是会得到一些闪烁,因为一个普通的文本框不可能使用像 BeginEdit 和 EndEdit 这样的东西,所以它会先改变文本然后然后select它。
看着视频,您的文本框似乎在不必要地调用 WM_ERASEBKGND。为了解决这个问题,您可以子class 文本框class 并拦截这些消息。下面是应该可以解决问题的示例代码(未经测试) 免责声明:我已将此技术用于其他 WinForm 控件,这些控件具有视频中显示的闪烁类型,但不是 TextBox。如果它对你有用,请告诉我。祝你好运!
// textbox no flicker
public partial class TexttBoxNF : TextBox
{
public TexttBoxNF()
{
}
public TexttBoxNF(IContainer container)
{
container.Add(this);
InitializeComponent();
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form's WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
//
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
Reza Aghaei 同时通过覆盖 WndProc
和拦截 WM_SETFOCUS
消息提供了解决方案。参见 here
已经有人问过类似的问题(例如,here),但是我还没有找到针对我的具体情况的答案。我正在构建一个基于 DevExpress 控件的自定义控件,该控件又基于标准 TextBox
并且我有一个闪烁的问题,这似乎是由于尝试更新选择的基本 TextBox 组件造成的。
无需解释我的自定义控件的所有细节,要重现该问题,您只需将 TextBox
放在 Form
中,然后使用此代码:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
textBox1.MouseMove += TextBox1_MouseMove;
}
private void TextBox1_MouseMove(object sender, MouseEventArgs e) {
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
}
}
如果启动它,单击 TextBox
,然后将光标向右移动,您会注意到闪烁问题(参见视频 here)。对于我的自定义控件,我需要避免这种闪烁。我必须使用 TextBox
(所以没有 RichTextBox
)。有什么想法吗?
根据你想做什么,有几种解决方案:
如果你想阻止 selection 它将是:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectionLength = 0;
}
或select全部:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectAll();
}
除此之外,您还可以指定 selecting 的条件,例如:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
{
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
if (MouseButtons == MouseButtons.Left) (sender as TextBox).SelectAll();
else (sender as TextBox).SelectionLength = 0;
}
但是只要你想 select 文本你总是会得到一些闪烁,因为一个普通的文本框不可能使用像 BeginEdit 和 EndEdit 这样的东西,所以它会先改变文本然后然后select它。
看着视频,您的文本框似乎在不必要地调用 WM_ERASEBKGND。为了解决这个问题,您可以子class 文本框class 并拦截这些消息。下面是应该可以解决问题的示例代码(未经测试) 免责声明:我已将此技术用于其他 WinForm 控件,这些控件具有视频中显示的闪烁类型,但不是 TextBox。如果它对你有用,请告诉我。祝你好运!
// textbox no flicker
public partial class TexttBoxNF : TextBox
{
public TexttBoxNF()
{
}
public TexttBoxNF(IContainer container)
{
container.Add(this);
InitializeComponent();
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form's WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
//
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
Reza Aghaei 同时通过覆盖 WndProc
和拦截 WM_SETFOCUS
消息提供了解决方案。参见 here