防止在 TextBox 中选择文本
Posted
技术标签:
【中文标题】防止在 TextBox 中选择文本【英文标题】:Prevent selecting text in a TextBox 【发布时间】:2017-07-11 03:28:01 【问题描述】:已经提出了类似的问题(例如,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
)。有什么想法吗?
【问题讨论】:
您是要完全避免选择,还是要允许选择但不应该在文本更改时闪烁? 我试过你的例子,点击后没有闪烁。应该是其他事件覆盖,可以分享其他事件吗 来自 MSDNBe careful when you write code for a MouseMove handler. MouseMove will frequently occur while the user is interacting with the application or with the specific object area that has the handler. Any computationally or graphically intensive code in a MouseMove handler can potentially introduce a noticeable lag in how the mouse pointer (or stylus pointer) draws and how the application generally behaves.
我会说它正在发生,因为它在鼠标移动期间会多次更新。
@IkramTurgunbaev 当您选择文本时会出现闪烁。左键单击文本框(并按住鼠标按钮)并在文本上移动以选择它。当鼠标移动处理程序更改文本时,蓝色选择颜色闪烁。
@RenéVogt 是的,你是对的,谢谢你的澄清
【参考方案1】:
与此同时,Reza Aghaei 通过覆盖 WndProc
并拦截 WM_SETFOCUS
消息提供了解决方案。见here
【讨论】:
【参考方案2】:查看视频,您的文本框似乎在不必要地调用 WM_ERASEBKGND。为了解决这个问题,您可以子类化文本框类并拦截这些消息。下面是可以解决问题的示例代码(未经测试) 免责声明:我已将此技术用于其他 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);
//http://***.com/questions/442817/c-sharp-flickering-listview-on-update
protected override void OnNotifyMessage(Message m)
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
base.OnNotifyMessage(m);
【讨论】:
@MauroGanswer - 您可以尝试在 OnNotifyMessage 函数中添加一些代码,该代码将显示或更好地记录传入的消息。感兴趣的消息将在您看到的时间内闪烁。在此期间,您可能需要过滤掉不同的 WM 消息。以下是 WM 消息列表供您参考 - wiki.winehq.org/List_Of_Windows_Messages【参考方案3】:根据你想做什么,有几种解决方案:
如果你想阻止选择它会是:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectionLength = 0;
或者选择全部:
private void TextBox1_MouseMove(object sender, MouseEventArgs e)
(sender as TextBox).Text = DateTime.Now.Ticks.ToString();
(sender as TextBox).SelectAll();
除此之外你还可以指定选择的条件,例如:
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;
但只要你想选择文本,你总是会得到一些闪烁,因为普通的Textbox不可能使用BeginEdit和EndEdit之类的东西,所以它会先改变文本然后选择它。
【讨论】:
我想避免如我的问题中所述的选择,这样做我想避免闪烁。您提供的第一个解决方案 ((sender as TextBox).SelectionLength = 0;
) 无法防止闪烁以上是关于防止在 TextBox 中选择文本的主要内容,如果未能解决你的问题,请参考以下文章
winform中textbox 鼠标可以自由选择其中的文本然后Enter删除