监控Control的屏幕位置何时发生变化的方法?

时间:2011-11-15 19:48:17

标签: c# winforms controls location screen

使用WinForms,有没有办法提醒控制器改变屏幕位置?

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

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

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

按要求说明:

Illustration

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

1 个答案:

答案 0 :(得分:3)

我不确定你为什么要说跟踪母链"不可行"。这不仅是可行的,而且是正确答案的简单答案。

快速破解解决方案:

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);
    }
}