如何检测控件的可见性?

6
如何检测控件是否对用户可见?我有一个显示应用程序状态的控件,我希望仅在用户看到它时更新它(例如,增加进度条的值或更改标签的Text属性)。如果用户最小化了包含此控件的窗体,或者另一个窗体覆盖了此控件,则无需更新它。如果控件无论如何都不可见,我不想进行额外的计算。 另外,如何检测隐藏/显示此控件的事件?
5个回答

1

这是不必要的。当窗口不可见时,Windows不会生成Paint事件。如果您自己实现了绘图,请确保仅在Paint事件中执行此操作,并在需要重新绘制时调用Invalidate()。


这是正确的答案。但愿我有那个超级赞按钮。其他人似乎都没有抓住重点。 - Cody Gray
@Hans Passant,@Cody Gray,不,这不是正确的答案。问题在于,如果控件无论如何都不可见,我不想进行额外的计算。我还更新了我的问题-似乎它不够清楚。 - Bogdan Verbenets
@Bogdan0x400:你必须阅读整个答案。只有在“Paint”事件中进行额外的计算。该代码不会执行,除非控件在屏幕上对用户可见。 - Cody Gray
2
但是如果状态计算很耗费时间,你真的想在每次控件绘制时都进行计算吗?即使状态实际上没有改变?我不会将状态计算与呈现问题绑定在一起。我倾向于找到一种检测状态更改的推送消息或事件的方法。这可能会提供最佳的效率提升。 - cdkMoose

1

这似乎是一个经常被问及的主题,具有多种可能的解决方案,取决于上下文。

首先,为了参考起见,以下是我在研究过程中偶然发现的一些旧讨论的链接:

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

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

(部分)解决方案: 一个可见性跟踪器,基本上管理控件本身和每个祖先控件的专用适配器。适配器处理依赖于祖先类型的可见性,例如对于 Control,它只是 instance.Visible,对于 TabPage,我检查哪个页面被选中,... 然后管理器的维护工作就是跟踪所有祖先的父级更改,以便它跟踪正确的可见性。


0
捕捉表单是否具有焦点或最小化是您的最佳选择,但我不确定是否涵盖了所有情况。一般来说,我会更新表单,而不管用户是否关注,除非将信息传递到表单需要大量循环,但我怀疑这种情况。在应用程序中设置条件位只会增加出错的可能性。
让我们仔细看一下。最小化的表单是一回事。如果表单被最小化,您知道用户甚至没有看它。但是,如果另一个表单在前面,那么您要检查表单是否具有焦点。问题在于,一个人可以使用屏幕的一半观看,同时在另一半上打字。Word 有焦点,因此表单不会更新,这不是您的意图。如果在应用程序中创建另一个表单,则可能发生相同的情况。更新不再具有焦点。
Windows 中没有魔法“用户是否在看我”的属性。

0
状态改变的频率有多高?最好在状态更改时更新状态指示器,不要担心可见性。假设状态平均每5分钟更改一次。当状态更改时,窗口/控件可能不可见,但很容易在下一个状态更新之前变得可见。在这种情况下,状态指示器将错误,直到下一次更新,因为您避免更改指示器。除非更新状态指示器非常昂贵,否则最好不要试图预测用户会做什么。
在查看其他评论后进行编辑:
我认为,通过识别检测/通知状态更改的模型,而不是按需计算,您可能能够实现更好的效率改进。您可能需要权衡状态更改的频率与您控件的可见性更改的频率。

1
计算状态是很昂贵的。如果用户无论如何都看不到它,我就不想计算它。 - Bogdan Verbenets
1
你打算每次可见性改变时都计算状态吗?如果其他窗口/应用程序正在活动移动/显示,但您的应用程序的状态没有改变,那么这可能会大大增加计算成本。 - cdkMoose

-3

3
这个方法不起作用,我已经尝试过了。请注意,即使Visible属性设置为true,如果控件被其他控件遮挡,它对用户也可能是不可见的。 - Bogdan Verbenets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接