C#的TextBoxChanged导致TextBox输入不正常
本帖最后由 SUPER_CRJ 于 2020-6-16 15:35 编辑查了一天了。
具体情况是:
因为要实时解析文本框中的数据。所以用了:TextBoxChanged事件。
但是此时:文本框则不正常了:
1:删除里面的内容,要删除两下,才能成功。而且光标移动到了开头。
2:输入内容也是:输入两下才可以。
仔细检查了相关代码:根本没有可以改变Text的代码。十分费解!!
代码如下(已经过压缩):
{ // 如果增加多个事件,则函数看来会比较乱。所以把众多事件统一处理,简化代码!
for( int i = 0;i<1;i++ )
{ // 总共5个
{ // 取数据
string inputData = (tabPage3.Controls["txb_sendData" + i.ToString()] as TextBox).Text;
string str = Regex.Replace(inputData, @"((\d\s)|(\d\d))(\s*)", "$0" + " ");
MatchCollection mc = Regex.Matches(str, @"\b+\b");
List<byte> buf = new List<byte>();
foreach (Match m in mc)
{
buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber));
}
if (buf.Count > 8)
{
showMessageBoxLanguage("第 " + i.ToString() + " 行输入数据超过8字节,请重新输入", "Line " + i.ToString() + " :Input data exceeding 8 bytes, please reenter");
}
masterSend.dataLen = buf.Count;
Array.Copy(buf.ToArray(), masterSend.dataBuf, buf.Count);
}
{ // 出校验值
if (masterSend.checkWay == 0)
{ // 标准校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
}
else if (masterSend.checkWay == 1)
{ // 增强校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, idParityQueryWay(masterSend.ID));
(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
}
else
{ // 自定义校验
masterSend.checkValue = byte.Parse((tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text);
}
}
}
}
源代码:
这里修改了 txb_checkValueX 控件的 Text 属性
// 标准校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
而 TextBox 控件的 Text 属性值发生变化时,会发送一个 message:
// System.Windows.Forms.TextBoxBase
using System.ComponentModel;
using System.Drawing.Design;
public override string Text
{
get
{
return base.Text;
}
set
{
if (value != base.Text)
{
base.Text = value;
if (base.IsHandleCreated)
{
SendMessage(185, 0, 0);
}
}
}
}
看参数不确定这是能否区分出来目标对象是 txb_checkValueX 还是 txb_sendDataX
其实这种问题自己一点一点注释代码,反复试一试应该能先定位到出问题的代码
SendMessage(185, 0, 0) 的 185 应该是这个消息
EM_SETMODIFY := 0xB9
https://wiki.winehq.org/List_Of_Windows_Messages
https://docs.microsoft.com/en-us/windows/win32/controls/em-setmodify
wudicgi 发表于 2020-6-16 15:58
这里修改了 txb_checkValueX 控件的 Text 属性
测试不行
把代码屏蔽:
//(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
仍然不能解决问题。
我的附件已上传了源代码,可不可以帮看下。 SUPER_CRJ 发表于 2020-6-16 16:16
测试不行
把代码屏蔽:
我就是打开项目试的,注释掉后边这行在删除时就正常了
wudicgi 发表于 2020-6-16 17:21
我就是打开项目试的,注释掉后边这行在删除时就正常了
不行!
我把这句换成其它的功能一致的也不行!!
证明应该不是这种原因造成的。
好纠结,完全没有头绪!
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
txb_checkValue0.Text = masterSend.checkValue.ToString("X"); wudicgi 发表于 2020-6-16 17:21
我就是打开项目试的,注释掉后边这行在删除时就正常了
另外:请问
注释掉后边这行在删除?这是什么样的操作,不太懂。。。{:smile:} 改用key-up或者key-press事件试试 SUPER_CRJ 发表于 2020-6-16 20:24
另外:请问
注释掉后边这行在删除?这是什么样的操作,不太懂。。。...
注释掉后边这行(后,)在(文本框中进行)删除时就正常了
SUPER_CRJ 发表于 2020-6-16 20:22
不行!
我把这句换成其它的功能一致的也不行!!
证明应该不是这种原因造成的。
我从 Win10 换到 Win8.1 的另一台电脑上,还是 VS2017,同样注释掉那行代码还是能消除这个问题
{ // 出校验值
if (masterSend.checkWay == 0)
{ // 标准校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
// (tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X"); // 注释掉此行,或者下边 else if 里那行也一块注释掉
}
else if (masterSend.checkWay == 1)
{ // 增强校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, idParityQueryWay(masterSend.ID));
(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
}
else
{ // 自定义校验
//try
//{
masterSend.checkValue = byte.Parse((tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text);
//}
//catch { }
}
}
本帖最后由 zyqcome 于 2020-6-16 22:14 编辑
改成失去焦点事件?
-----
楼主,都这么多控件了,不要硬钢了,
这个是你遍历控件的时候,鼠标焦点丢失了,
我的建议是,要么不要用遍历这些控件,这样焦点至少在这个控件,
当然,
有个更简单的,增加一个 button,专门来确认修改
希望能帮到你 加个timeout,只有输入超时才去校验文本内容,或者keydown事件去校验 其实话说回来,比较好的方式应该是正常的时候在 TextBox LostFocus 时才验证内容,在经过验证内容不合法时才在 TextChanged 或 KeyUp 时就马上验证内容
另外每次只验证当前 TextBox, 而不是所有 TextBox
在执行类似提交的操作时才一次性验证所有 TextBox
一般都是执行操作前,统一进行合法性检验。省事,也够用。 zyqcome 发表于 2020-6-16 21:56
改成失去焦点事件?
-----
我上传的代码中实际并没有遍历控件。其中几个参数修改了。
其实最终只是:获取了textBox中的数值解析,然后再改另外一个textBox中的数值。并没有访问其它控件。
难道仅仅是:访问了其它一个控件就产生了这样的效果?
(因为是实时解析出值,所以加了一个按键感觉有点:多此一举。)
下面是我上传的代码,麻烦可以再参考下。
wudicgi 发表于 2020-6-17 00:48
其实话说回来,比较好的方式应该是正常的时候在 TextBox LostFocus 时才验证内容,在经过验证内容不合法时 ...
好的,谢谢。
TextBox LostFocus 不方便使用,因为要实时解析出数据。
可以考虑:KeyUp事件,因为之前测试KeyPress没有出现这样的问题。
另外有一点:我修改的代码中其实只检测了一个TextBox,并没有你说的遍历所有。但是也出了这样的问题,所以我想到原因。
(代码我上传到了15楼) wudicgi 发表于 2020-6-16 21:44
我从 Win10 换到 Win8.1 的另一台电脑上,还是 VS2017,同样注释掉那行代码还是能消除这个问题
如果是改变了属性。
我把你备注掉的语句直接改为:
txb_checkValue0.Text = strTmp; //strTmp是结果
为什么也还是不行!同样的效果。 SUPER_CRJ 发表于 2020-6-17 10:20
如果是改变了属性。
我把你备注掉的语句直接改为:
那你试试注释掉其他的代码,看是哪块有印象
我这试出来就是这块
SUPER_CRJ 发表于 2020-6-17 10:17
我上传的代码中实际并没有遍历控件。其中几个参数修改了。
其实最终只是:获取了textBox中的数值解析,然 ...
确实是输入焦点失去了,我在回复中提到遍历出自
string inputData = (tabPage3.Controls["txb_sendData" + i.ToString()] as TextBox).Text;
这里读了其他的控件
今天仔细看了一下,是另一个 edit 控件引起的
这两个都是 edit 这样在这里
if (masterSend.checkWay == 0)
{ // 标准校验
masterSend.checkValue = dataCheck(masterSend.dataBuf, masterSend.dataLen, 0);
//masterSend.checkValue = 99;
//(tabPage3.Controls["txb_checkValue" + i.ToString()] as TextBox).Text = masterSend.checkValue.ToString("X");
string strTmp = masterSend.checkValue.ToString("X");
txb_checkValue0.Text = strTmp; //AAAA
}
//AAAA 这个地方,输入的焦点到了 txb_checkValue0 当你再次修改 txb_sendData0 的时候,就需要点两次才能进去,一次激活输入,就是是光标闪烁,一个真正修改
我想到的解决办法
把txb_checkValue0 换成 label 既然 校验值是算出来的,没必要修改
zyqcome 发表于 2020-6-17 18:08
确实是输入焦点失去了,我在回复中提到遍历出自
非常感谢。
应该就是修改另外一个textBox导致的。
但是:另外一个textBox在另外一种模式下,还需要使用。所以不能换成label。
不过终于找到问题的原因了。
我现在用的解决方法是:把textChanged换成keyUp事件就好了。 hcambridge 发表于 2020-6-16 20:31
改用key-up或者key-press事件试试
key-up事件测试可以的。
key-Press不行,因为此时按下的键还没有真正输入到TextBox中。 分析了你的源码,发现跟你的复杂的数据绑定有关,你最好取消txb_checkValue0-n这些控件的数据绑定;数据流回路导致的。
文字描述这个过程太复杂,你自己按照我的思路调调看。
页:
[1]