为什么不应该在WM_KILLFOCUS时进行数据校验

想法很好 , 但是不大对
你可能会有这样一个好点子:当控件收到WM_KILLFOCUS消息的时候 , 我就执行我的控件数据校验流程 。
这个想法看起来还不赖 , 但是时机不大对 。
原因是多方面的
首先 , 你可能会最后才收到这个消息 , 对于某些应用场景来说 , 可能这个时间点才执行数据校验有点太晚了 。 请想象这样一个场景:有一个对话框 , 上面有一个文本框和一个确认按钮 。 当收到WM_KILLFOCUS消息时 , 文本框控件会对它的输入内容进行有效性校验 。
假设我们的用户输入了一些无效的数据 , 在理想的情况下 , 用户按下了确认按钮 , 这会导致输入焦点从文本框上上移开 , 所以文本框会收到WM_KILLFOCUS消息 , 然后数据校验代码会执行 , 程序可以提醒用户输入了无效的数据 。 因为鼠标点击事件是在鼠标按键释放时才会触发的 , 所以会出现这样一种情况:用户还没有释放鼠标按钮 , 无效数据的提示对话框就弹出来了 , 同时这个对话框会捕获输入焦点 , 而同时 , 因为输入焦点已经不在按钮上了 , 所以按钮点击事件的处理代码不会被执行 。
为什么不应该在WM_KILLFOCUS时进行数据校验】如果考虑一种稍微不那么理想的情况:用户直接按下回车或者关闭按钮对应的键盘快捷键 , 而不是点击确认按钮 。 键盘快捷键会被IsDialogMessage函数转换为一个WM_COMMAND , 参数为按钮的控件ID 。 此时 , 输入焦点并不会发生改变 。 所以 , 按钮处理代码会被执行 , 并调用EndDialog或者执行其他对应的动作 。 如果对话框关闭 , 则输入焦点会因为关闭事件从文本框上移走 , 就在此时 , 你的数据校验代码才会得到执行 , 但这个时候进行数据校验 , 实在是太晚了 , 对话框已经开始关闭了 。
另外 , 如果按钮点击处理程序不是关闭对话框 , 而是开始执行其他的动作 , 那么它将对用户输入的无效的数据进行处理 , 这显然不会是你想要看到的:只有当这个动作偶然的移动输入焦点(例如 , 显示一个进度窗口)才会使文本框控件收到一个WM_KILLFOCUS消息 , 这个时间点太晚了 , 更严重的是 , 处理程序已经对无效的数据开始进行处理了 。
在输入焦点失去时才进行数据校验还存在另外一个可用性问题 。 假设用户正在文本框中输入数据分心了 , 比如他突然想打开一封电子邮件 , 或者他想打开通讯录来打一个电话 , 又或者他有些事情离开了座位 , 导致屏幕保护程序开启 。 当用户仅仅是因为没有输入完整 , 程序就给出一个无效数据的提示 , 这个是用户不乐意看到的 。
那什么时候做数据校验?
上面我们说了你不应该在收到WM_KILLFOCUS消息时执行数据校验 , 那么 , 在上面时间点做数据校验最为合适呢?Well , 当用户完成数据输入并希望进入下一步时就开始执行数据校验 。 对于一个简单的对话框来说 , 这意味着:对用户点击确认按钮时执行数据校验 。 对于一个向导对话框 , 合适的时间点是当用户点击下一步按钮的时候 。 对于一个标签式对话框 , 则可以在用户切换到一个新的标签页时进行数据校验 。
对于一些不会改变输入焦点的提示控件是允许的 , 例如 , 当用户输入密码时 , 如果大写被打开了 , 可以弹出一个气泡提示 。 这会是一个非常好的用户体验 。
总结
每个Windows消息有它对应的使用场景 , 切不可:想当然 , 生搬硬套 , 牛头不搭马嘴 。
最后
RaymondChen的《TheOldNewThing》是我非常喜欢的博客之一 , 里面有很多关于Windows的小知识 , 对于广大Windows平台开发者来说 , 确实十分有帮助 。
本文来自:《WM_KILLFOCUSisthewrongtimetodofieldvalidation》

为什么不应该在WM_KILLFOCUS时进行数据校验
文章图片