一种监视控件的屏幕位置何时更改的方法?

Posted

技术标签:

【中文标题】一种监视控件的屏幕位置何时更改的方法?【英文标题】:A way to monitor when a Control's screen location changes? 【发布时间】:2011-12-29 20:17:17 【问题描述】:

使用 WinForms,有没有办法提醒控件相对于屏幕的位置发生变化?

假设您有一个带有按钮的表单,并且您想知道该按钮何时从屏幕上的当前像素位置移动。如果按钮被移动到其父窗体上的不同位置,您显然可以使用 LocationChanged 事件,但如果用户移动了窗体,您如何知道按钮在视觉上移动了?

在这个简化的情况下,快速的答案是监控表单的 LocationChanged 和 SizeChanged 事件,但是可以有任意数量的嵌套级别,因此监控这些事件对于链上到主表单的每个父级是不可行的。使用计时器检查位置是否发生变化也似乎是作弊(以一种糟糕的方式)。

短版: 仅给定一个任意 Control 对象,有没有办法知道该 Control 在屏幕上的位置何时发生变化,而不需要知道该控件的父层次结构?

插图,应要求提供:

请注意,这种“固定”概念是现有功能,但目前需要了解父窗体以及子控件的行为方式;这不是我要解决的问题。我想将此控制跟踪逻辑封装在“可固定”表单可以继承的抽象表单中。是否有一些消息泵魔法可以让我知道控件何时在屏幕上移动,而无需处理所有复杂的父跟踪?

【问题讨论】:

为什么不能一直监控所有的父母到顶部窗口不可行? 假设您有 20 层嵌套,全部停靠到 Fill。当您通过拖动边框调整主窗体的大小时,SizeChanged 事件将在每个级别上触发,在拖动过程中多次触发。这是一大堆多余的事件。其次,这些控件可能会从一个地方移动到另一个地方(完全不同的嵌套层次结构),因此即使您为每个父级连接 ParentChanged,在它更改后,您也无法在不存储所有父级控件的情况下从以前的父级取消挂钩 SizeChanged/LocationChanged遍历时的信息。这一切似乎都很肮脏。 这似乎是需要问题的人之一:“你想做什么?” 我想将表单“固定”到任意控件,因此当控件移动时,表单的位置将保持在相对于控件的相同位置。 也许您可以提供一些您正在尝试完成的屏幕截图。 【参考方案1】:

我不确定您为什么会说跟踪父链“不可行”。它不仅可行,而且是正确的答案简单的答案。

快速解决方案:

private Control         _anchorControl;
private List<Control>   _parentChain = new List<Control>();
private void BuildChain()

    foreach(var item in _parentChain)
    
        item.LocationChanged -= ControlLocationChanged;
        item.ParentChanged -= ControlParentChanged;
    

    var current = _anchorControl;

    while( current != null )
    
        _parentChain.Add(current);
        current = current.Parent;
    

    foreach(var item in _parentChain)
    
        item.LocationChanged += ControlLocationChanged;
        item.ParentChanged += ControlParentChanged;
    


void ControlParentChanged(object sender, EventArgs e)

    BuildChain();
    ControlLocationChanged(sender, e);


void ControlLocationChanged(object sender, EventArgs e)

    // Update Location of Form
    if( _anchorControl.Parent != null )
    
        var screenLoc = _anchorControl.Parent.PointToScreen(_anchorControl.Location);
        UpdateFormLocation(screenLoc);
    

【讨论】:

这是我在对该问题的大量评论中回避的可能解决方案,但觉得它很脏。不过,我认为没有更好的方法来做到这一点。

以上是关于一种监视控件的屏幕位置何时更改的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何截取第二个屏幕监视器的屏幕截图?

监视重大位置更改时不会调用“didUpdateLocations”

监视/轮询 FTP 位置

如何在 AIX 中监视没有 cron 作业的文件更改

检测触摸何时开始在屏幕上的任何位置,即使是在 UIButton 上

如何让我的程序监视 C++ 中的文件修改?