Monitoring method when changing the location of the control screen?

With WinForms, is there a way to get a warning about the location of the control relative to the screen?

Say you have a form with a button on it, and you would like to know when the button moves from the current pixel location on the screen. If the button is moved to another place in the parent form, you can obviously use the LocationChanged event, but if the form is moved by the user, how do you know that the button is visually moved?

In this simplified case, the quick answer is to track Form LocationChanged and SizeChanged events, but there can be an arbitrary number of nesting levels, so monitoring these events for each parent up the chain to the primary form is not possible. Using a timer to check if the location has changed is also similar to cheating (bad way).

Short version: Given only an arbitrary Control object, is there a way to find out when this control location changes on the screen without knowing the control parent hierarchy?

Illustration on request:

Illustration

Note that this concept of β€œpinning” is an existing possibility, but currently it requires knowledge of the parent form and how the child control behaves; this is not the problem i am trying to solve. I would like to encapsulate this control tracking logic in an abstract form that pin-able Forms can inherit. Is there any message magic I can use to know when a control moves on the screen without having to deal with all the complicated parental tracking?

+7
source share
1 answer

I'm not sure why you would say that tracking the parent chain is "impossible." Not only is this possible, it is the correct answer and an easy answer.

Just hack the solution quickly:

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); } } 
+3
source

All Articles