【问题标题】:Win32API: How to determine if EN_CHANGE was because of user action, not software action?Win32API:如何确定 EN_CHANGE 是否是因为用户操作,而不是软件操作?
【发布时间】:2010-02-05 16:20:53
【问题描述】:

我发现这种情况时有发生,而且我似乎从来没有一个真正强大的通用解决方案。

我有一个控件——在这个例子中是一个对话框上的 EDIT 控件。我想采取某些行动来响应用户 - 并且只有用户 - 修改编辑控件的内容。

可以通过编程方式设置编辑控件 - 例如在设置对话框时,可能会在编辑字段中放置一个初始值。或者当用户从列表视图中选择一个项目时,该选择的文本很可能就是放置在编辑字段中的内容。

但是当 用户 修改编辑字段的内容时,我需要知道这一点并做出响应(在这种情况下,我想从对应的列表视图)。

我目前正在查看哪个控件具有焦点,并且如果编辑控件具有焦点,则仅将 EN_CHANGE 视为“来自用户”。

这在 Windows 7 下运行良好。在 XP 下失败(我还没有测试过 Vista)。

在 XP 中,如果编辑字段具有焦点,但用户单击列表视图,并且列表视图告诉编辑控件设置其内容,那么我会收到来自编辑控件的通知,声称仍然有焦点(::GetFocus() == 编辑控件的 HWND)。但是这种不正确的状态在Win7中不会出现。

这是一个分层接口,所以我不能修改列表视图通知处理程序。它会更改选择并更新编辑字段,而无需我参与或真正干预,而不是从他们俩那里获得通知。

关于如何普遍、永久地解决“此控件通知是否真的来自用户”难题的任何想法?

【问题讨论】:

    标签: c++ windows mfc winapi notifications


    【解决方案1】:

    您始终可以跟踪LVM_ITEMCHANGINGLVM_ITEMCHANGEDEN_MSGFILTER 消息。如果编辑框在LVM_ITEMCHANGINGLVM_ITEMCHANGED 之间修改而没有EN_MSGFILTER,那么您可以假设用户没有修改该项目。或者只是检查EN_CHANGE 触发时是否选择了任何项目,如果没有或文本与所选项目不匹配,则假设它是用户编辑。

    或使用ES_MULTILINE(来自EN_CHANGE 文档):

    未发送 EN_CHANGE 通知 当使用 ES_MULTILINE 样式时 并且文本是通过发送的 WM_SETTEXT。

    【讨论】:

      【解决方案2】:

      我建议使用正确的信息。 EN_CHANGE 太通用了,你想知道用户是输入了还是粘贴了文本。那么为什么不子类化控件并观察 WM_KEYPRESS 消息呢?

      或者,您可以在设置编辑控件内容的其他代码中设置一个标志。您也许可以假设任何使您的 wndproc 可重入的东西都代表了一种程序性更改。

      您不是在寻找真正安全的东西,是吗?如果您只想排除设置内容调用,这相当简单。如果您想区分用户操作和用户按键的编程模拟,这是一个更难的问题。

      【讨论】:

      • 没有什么特别安全或万无一失的。我只需要检测 ListView 是否正在发送文本,或者用户是否在编辑控件中键入(或粘贴)了某些内容。现实情况是,这是在文件对话框中,控件实际上是一个 COMBOBOX32EX,其中包含一个包含 EDIT 控件的 COMBOBOX,我尝试使用 wndproc 挂钩(子类化)从内部转发消息,但由于乱序问题(ComboBox 被赋予 WM_SETTEXT,但它仍然认为它有焦点),我不知道如何对此进行充分过滤。
      • ListView 更改文本时调用堆栈是什么样的?如果对 WndProc 的调用是嵌套的(例如,您通过调用 SendMessage 处理 ListView 通知),这应该很容易解决,如果更改使用消息队列(例如,您通过调用 PostMessage 处理 ListView 通知),那么事情会变得更加艰难。
      猜你喜欢
      • 2013-03-28
      • 2019-10-25
      • 2012-05-04
      • 2011-01-07
      • 1970-01-01
      • 2020-02-02
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多