【问题标题】:.NET: TextChanged event for TextBox not always firing, even though KeyUp and KeyDown are firing.NET:TextBox 的 TextChanged 事件并不总是触发,即使 KeyUp 和 KeyDown 正在触发
【发布时间】:2011-01-01 21:25:21
【问题描述】:

我遇到了一个非常奇怪的问题。我注意到偶尔在我的 TextBox 中输入时,我会丢失一些击键。我在这个 TextBox 挂钩的事件中添加了一堆跟踪语句,我发现当我丢失击键时,KeyUp、KeyDown 和 KeyPress 事件都正确触发,但 TextChanged 事件从未触发。

有人知道为什么会发生这种情况吗?我可以把它写成一个“.NET bug”,但我宁愿弄清楚这里是否有解决方案。

如果有人建议我使用 KeyUp/KeyDown 事件来确定文本是否已更改,那么这里也存在问题。每次按键都会多次调用 KeyUp/KeyDown,因此很难确定是否有人多次键入同一个字母。

【问题讨论】:

  • 你用什么按键来体验这个? Textchanged 是文本框名为 Text 的属性的一部分,任何输入(字母和数字以及 $ 等符号)都会触发 TextChanged 事件,箭头键、插入、覆盖不会触发,但会被 KeyUp/KeyDown 事件捕获.
  • 一个明显的例子是当文本框为空时按退格键。没有 TextChange 事件,但所有的键盘事件。
  • 发生这种情况时,我肯定使用的是普通的字母数字键击。
  • 我更改了您的标题,因为这与 C# 无关,只是您碰巧使用它来编写 .NET 代码。
  • 同样的事情发生在我身上,特别是当我在 TextBox 中按下退格键时(它从一个字符变为空白,这又是文本值的变化)。当我按下 Delete 并选择 TextBox 的所有文本时,它也不会触发。

标签: c# .net winforms textbox


【解决方案1】:

嗯……

这将是一个镜头,但是,您确实说过您有 KeyUp、KeyDown 和 KeyPress 事件处理程序,对吗?您是否在事件处理程序中将标志 e.Handled 设置为 true,请看这里:

私人无效文本框1_KeyDown(对象发送者,KeyEventArgs e) { e.Handled = true; } 私人无效文本框1_KeyUp(对象发送者,KeyEventArgs e) { e.Handled = true; } 私人无效文本框1_KeyPress(对象发送者,KeyPressEventArgs e) { e.Handled = true; }

MSDN 中查看有关此 Handled 属性的信息。 (如果您在本地安装了 MSDN 2008 SP 1,链接为ms-help://MS.MSDNQTR.v90.en/fxref_system.windows.forms/html/dfc80b44-1d79-6315-cbea-1388a048c018.htm

引用:

Windows 窗体中的不同控件以不同方式实现处理。 对于像 TextBox 这样的子类原生 Win32 控件的控件,它是 解释为意味着不应将关键信息传递给底层证券 本机控制。 如果在 TextBox 上将 Handled 设置为 true,则该控件将不会传递密钥 按下事件到底层的 Win32 文本框控件,但它仍然会 显示用户输入的字符。

也许它没有设置,即e.Handled = false;,从而阻止了 TextChanged 事件的触发?

你能确认一下吗?

编辑: 在 dreadprivateryan 的回复之后,我可以怀疑(由于缺少发布的代码),根据他的回复,e.Handled 在按下 Enter 键时为真,而在其他所有情况下为假在我看来,这就是为什么没有进一步的击键被接受的原因。

  • 您是否试图在按下 Enter 键时将焦点设置到另一个控件?可能是 KeyUp 和 KeyDown 冲突...
  • 移除键盘挂钩并禁用它...
  • 我的建议是完全以这种方式更改代码,如图所示,取出 KeyDown 或 KeyUp 事件处理程序,因为它们,简单地说,是相同的,好的,从技术上讲,它分别指定用于按下键时下,同样当一个键被释放时。看看这个链接here。在 SO 上发布了一个类似的问题 here

在下面的示例中,我使用 keyUp 事件处理程序在按下 Enter 键时将焦点切换到下一个可用控件。在 KeyPress 事件处理程序中,这只是过滤输入并分别只允许数字 0-9,其他任何内容都会被丢弃。包含在该事件处理程序中的是允许退格键提供编辑。

私人无效 textBox1_KeyUp(对象发送者,KeyEventArgs e) { if (e.KeyCode == Keys.Enter) SendKeys.Send("{TAB}"); } 私人常量字符串 VALID_KEYS = "0123456789"; 私人无效文本框1_KeyPress(对象发送者,KeyPressEventArgs e) { if (VALID_KEYS.IndexOf(char.ToUpper(e.KeyChar)) != -1 || e.KeyChar == (char)8) e.Handled = false; 别的 e.Handled = true; }

希望这会有所帮助, 最好的祝福, 汤姆。

【讨论】:

  • 感谢您的建议。我只在击键是回车键的情况下设置 e.Handled=true ,否则我根本没有设置处理。不幸的是,我认为这与我的问题无关——无论我是否按 Enter,我都会丢失击键。
【解决方案2】:

我实际上不知道,但我有一个随机猜测:你在 VM 中运行?

您可以使用的一个技巧是制作一个计时器来读取文本并与之前输入的值进行比较。当它不等于先前检查的值时调用事件处理程序代码。当您需要使用最终输入的值时,请再做一次检查,以防计时器尚未触发。

【讨论】:

  • 不,不在虚拟机中运行。我会考虑那个计时器的想法——好建议。
【解决方案3】:

您的意思是按键实际上丢失并且从未出现在框中?还是您的意思是每次按键都不会收到 TextChanged 事件?

我相信 TextChanged 事件是由操作系统的 EN_CHANGE 通知驱动的,该通知是通过 WM_COMMAND 消息发送的。我知道 Windows 中的某些类型的消息被“合并”以避免冗余通知。例如,这可能发生在 WM_MOUSEMOVE 消息中,这就是为什么鼠标在屏幕上移动的每个像素都没有收到鼠标移动事件的原因。

我不能肯定地说,但我怀疑 TextChanged 事件的行为方式也是如此。我可以说,替代输入法也有这种副作用。使用 Tablet PC 输入面板时,文本框不会收到每个字符的 TextChanged 通知。

【讨论】:

  • 密钥实际上丢失了,并且从未出现在框中——当这种情况发生时,我注意到 TextChanged 事件也没有触发。感谢您提供有关 Windows 消息的信息。也许我可以在 KeyUp/KeyDown 事件期间手动触发该事件?
  • 似乎有什么东西正在吞噬消息。也许在某个地方安装了一个系统范围的消息挂钩正在运行?或者我敢说,也许是某种键盘记录器?如果您安装了 Spy++,您应该尝试运行它并查看消息是否到达窗口。
  • 程序中确实有一个键盘钩子——我应该包括的重要信息。该挂钩是使用以下代码创建的: SetWindowsHookEx(WH_KEYBOARD, KeyFunction, dllInstance, AppDomain.GetCurrentThreadId()); KeyFunction 方法检查某些击键,根据这些击键的内容调用其他函数,然后调用 CallNextHookEx 函数。我的跟踪语句告诉我,在我丢失击键的情况下,钩子确实看到了键,并且 CallNextHookEx 函数被正确调用。
  • 你能确认没有钩子键击不会丢失吗?也许你可以在 hook proc 周围发布一个代码的 sn-p。
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多