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

rok*_*ken 7 c# controls location screen winforms

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

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

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

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

按要求说明:

插图

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

Joh*_*len 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);
    }
}
Run Code Online (Sandbox Code Playgroud)