【发布时间】:2017-10-28 01:00:58
【问题描述】:
在我控制外部设备的基于对话框的 UI 中,我有一堆外观和行为相似的“旋钮”:由 滑块、数字编辑框组成的三组控件,以及用于该数字编辑框的 微调器。
值的变化会导致到该外部设备的往返,因此我自然会尝试每次“更改”只调用一次冗长的 API。更改可以来自 3 个控件中的任何一个,并且它们必须是同步的,显然。这在实践中意味着如果编辑框发生变化 - 它需要更改滑块的位置。反之亦然。
API 调用在单独的函数中实现,只要 UI 框架报告值发生变化,就会调用这些函数。
问题:
- 当控件开始相互更新时,“同步”范例的直接天真实现自然会导致递归调用
- 引入递归保护(如
bool m_processingUserInput;)看起来很丑,坦率地说,感觉很丑 - 当添加更多控件时,“仅”从一种类型的控件而不是另一种(例如仅从滑块)进行 API 调用很容易出现错误。此外,这种方法使代码看起来很混乱,并且(就其本身而言)也不能解决递归问题
我的问题是:我是否错过了人们用来编写此 UI 交互代码的成熟模式?请告诉我一种优雅高效的方法。
【问题讨论】:
-
不会出现递归,因为您提到的所有控件都不会在以编程方式更改时发送“已更改”通知。通知是关于用户修改的。
-
SetDlgItemInt(ID, val)肯定会触发“on change”处理程序 -
好吧,我错了。这来自从字面上阅读 MS 文档,而不是自己测试。递归保护听起来并不那么糟糕。您可以使用通知处理程序内部的布尔静态变量和 RAII 类的局部变量来做到这一点,该变量在构造函数中将静态变量设置为
true,在析构函数中设置为false,以实现异常安全和易用性。
标签: c++ windows user-interface mfc