如何检测控件的可见性?

Posted

技术标签:

【中文标题】如何检测控件的可见性?【英文标题】:How can I detect the visibility of a control? 【发布时间】:2011-10-05 08:59:30 【问题描述】:

如何检测控件是否对用户可见?我有一个显示应用程序状态的控件,并且我希望它仅在用户看到它时才更新(它的值要更新,例如,增加进度条的值,或更改标签的 Text 属性)。如果用户已最小化包含此控件的表单,或者另一个表单与此控件重叠,则无需更新它。如果控件不可见,我只是不想进行额外的计算。 另外,如何检测隐藏/显示此控件的事件?

【问题讨论】:

【参考方案1】:

这似乎是经常被问到的主题之一,并且有许多可能的解决方案,具体取决于上下文。

首先,作为参考,一些链接指向我在研究期间偶然发现的旧讨论:

How to check absolute control visibility and how to be notified for changes of absolute visibility C# winform check if control is physicaly visible

起始位置: 用于异构系统的 IDE,具有大量不同的硬件和许多不同的传输层,其中一些非常慢。一项功能是在编辑器中显示远程硬件的内存值。一个典型的用例是打开超过 20 个编辑器,每个编辑器显示 1 到 100 个不同的值。

由于传输层的带宽有限,我一直在寻找一种解决方案来“优先考虑”数据采集。

(部分)解决方案: 一个可见性跟踪器,它基本上为控件本身和每个祖先控件管理一个专门的适配器。适配器根据祖先类型处理可见性,即。对于控件,它只是实例。可见,对于 TabPage,我检查选择了哪个页面,... 然后,经理的内务管理只是跟踪所有祖先的父级更改,以便跟踪正确的可见性。

【讨论】:

【参考方案2】:

了解表单是否具有焦点或最小化是您最好的选择,但我不确定是否适用于所有情况。一般来说,无论用户是否注意,我都会更新,除非需要大量周期才能将信息发送到表单,我对此表示怀疑。在应用程序中设置条件位只会增加另一个出错的地方。

让我们来看看这个。最小化形式是一回事。如果表单被最小化,你就知道用户甚至没有看它。但是,如果另一个表单在前面,那么你要检查表单是否有焦点。这里的问题是一个人可以在另一半输入单词时使用一半屏幕观看。 Word 具有焦点,因此表单不会更新,这不是您的意图。如果您在应用程序中创建另一个表单,也会发生同样的情况。更新不再具有焦点。

Windows 中没有神奇的“用户是否在看我”属性。

【讨论】:

【参考方案3】:

这从来没有必要。当窗口不可见时,Windows 不会生成 Paint 事件。如果您自己实现了绘画,请确保仅在 Paint 事件中执行此操作,并且如果有重新绘画的原因,则调用 Invalidate()。

【讨论】:

这是正确答案。希望我有那个超级赞成按钮。其他人似乎都没有抓住重点。 @Hans Passant,@Cody Gray,不,这不是正确的答案。问题是如果控件不可见,我不想进行额外的计算。我还更新了我的问题 - 似乎还不够清楚。 @Bogdan0x400:您必须阅读整个答案。仅在 Paint 事件中进行额外计算。该代码不会执行,除非该控件在屏幕上对用户可见。 但是如果状态计算很昂贵,你真的想在每次控件绘制时都这样做,即使状态实际上并没有改变?我不会将状态计算与演示问题联系起来。我倾向于确定一种将状态更改检测为推送消息或事件的方法。这可能会提供最好的效率提升。【参考方案4】:

状态多久更改一次?最好在状态更改时更新状态指示器,而不用担心可见性。假设状态平均每 5 分钟更改一次。当状态改变时窗口/控件可能不可见,但在下一次状态更新之前很容易变得可见。在这种情况下,状态指示器会一直出错,直到下次更新,因为您避免更改指示器。除非更新状态指示器非常昂贵,否则最好不要尝试预测用户会做什么。

查看其他 cmets 后编辑:

我认为您可以通过确定用于检测/通知状态变化的模型而不是按需计算来实现更好的效率改进。您可能需要权衡状态更改的频率与控件可见性更改的频率。

【讨论】:

计算状态是昂贵的。当用户看不到它时,我不想计算它。 那么您是否计划在每次可见性变化时计算状态?如果其他窗口/应用程序正在积极移动/显示,但您的应用程序的状态没有改变,这可能会大大增加计算成本。【参考方案5】:

看看Control.Visible 和Control.VisibleChanged 事件。

【讨论】:

这不起作用,我已经尝试过了。 “请注意,即使 Visible 设置为 true,如果控件隐藏在其他控件后面,用户也可能看不到该控件。”

以上是关于如何检测控件的可见性?的主要内容,如果未能解决你的问题,请参考以下文章

Silverlight 4:如何切换控件可见性

如何确定控件的可见性?

如何识别控件的可见性是不是被用户更改?

如何从 MaterialDesignXamlToolkit 中删除 ComboBox 控件中的装饰器可见性?

如何在 Youtube Autoplay 新闻提要等回收站视图中检测查看可见性(80% 左右),当 ~80 可见时播放视频

如何在自定义 wpf 控件上绑定数据网格列的可见性?