/// <summary> /// Gets and sets the root control for point translation and message dispatch. /// </summary> /// <param name="parent">Parent control.</param> public void UpdateParent(Control parent) { // Keep looking till we run out of parents while (parent != null) { // We can hook into a visual control derived class if (parent is VisualControl) { _rootControl = (VisualControl)parent; _rootPopup = null; break; } // We can hook into a visual popup derived class if (parent is VisualPopup) { _rootControl = null; _rootPopup = (VisualPopup)parent; break; } // Move up another level parent = parent.Parent; } }
/// <summary> /// Finish tracking the current popup. /// </summary> public void EndCurrentTracking() { // Are we tracking a popup? if (_current != null) { // Kill the popup window if (!_current.IsDisposed) { _current.Dispose(); } // Is there anything stacked? if (_stack.Count > 0) { // Pop back and now track _current = _stack.Pop(); } else { // No longer tracking any popup _current = null; // Last popup removed, so unhook from message processing FilterMessages(false); } } }
/// <summary> /// Finish tracking from the current back to and including the provided popup. /// </summary> /// <param name="popup">Popup that needs to be killed.</param> public void EndPopupTracking(VisualPopup popup) { // Are we tracking a popup? if (_current != null) { bool found = false; do { // Is this the target? found = (_current == popup); // If possible then kill the current popup if (!_current.IsDisposed) { _current.Dispose(); } _current = null; // If anything on stack, then it becomes the current one if (_stack.Count > 0) { _current = _stack.Pop(); } }while (!found && (_current != null)); // If we removed all the popups if (_current == null) { // No longer need to filter FilterMessages(false); } } }
/// <summary> /// Finish tracking all popups. /// </summary> public void EndAllTracking() { // Are we tracking a popup? if (_current != null) { // Kill the popup window if (!_current.IsDisposed) { _current.Dispose(); _current = null; } // Is there anything stacked? while (_stack.Count > 0) { // Pop back the popup _current = _stack.Pop(); // Kill the popup _current.Dispose(); _current = null; } // No longer need to filter FilterMessages(false); } }
/// <summary> /// Start tracking the provided popup. /// </summary> /// <param name="popup">Popup instance to track.</param> public void StartTracking(VisualPopup popup) { Debug.Assert(popup != null); Debug.Assert(!popup.IsDisposed); Debug.Assert(popup.IsHandleCreated); Debug.Assert(_suspended == 0); // The popup control must be valid if ((popup != null) && !popup.IsDisposed && popup.IsHandleCreated) { // Cannot start tracking when a popup menu is alive if (_suspended == 0) { // If we already have a popup... if (_current != null) { // Then stack it _stack.Push(_current); } else { // Cache the currently active window _activeWindow = PI.GetActiveWindow(); // For the first popup, we hook into message processing FilterMessages(true); } // Store reference _current = popup; } } }
private bool ProcessNonClientMouseDown(ref Message m) { // Extract the x and y mouse position from message Point screenPt = new Point(PI.LOWORD((int)m.LParam), PI.HIWORD((int)m.LParam)); // Ask the popup if this message causes the entire stack to be killed if (_current.DoesCurrentMouseDownEndAllTracking(m, ScreenPtToClientPt(screenPt))) { EndAllTracking(); } // Do any of the current popups want the mouse down to be eaten? bool processed = false; if (_current != null) { processed = _current.DoesMouseDownGetEaten(m, screenPt); if (!processed) { // Search from end towards the front, the last entry is the most recent 'Push' VisualPopup[] popups = _stack.ToArray(); for (int i = 0; i < popups.Length; i++) { // Ignore disposed popups VisualPopup popup = popups[i]; if (!popup.IsDisposed) { processed = popup.DoesMouseDownGetEaten(m, screenPt); if (processed) { break; } } } } } return(processed); }
private bool ProcessClientMouseDown(ref Message m) { bool processed = false; // Convert the client position to screen point Point screenPt = CommonHelper.ClientMouseMessageToScreenPt(m); // Is this message for the current popup? if (m.HWnd == _current.Handle) { // Message is intended for the current popup which means we ask the popup if it // would like to kill the entire stack because it knows the mouse down should // cancel the showing of popups. if (_current.DoesCurrentMouseDownEndAllTracking(m, ScreenPtToClientPt(screenPt))) { EndAllTracking(); } } else { // If the current popup is not the intended recipient but the current popup knows // that the mouse down is safe because it is within the client area of itself, then // just let the message carry on as normal. if (_current.DoesCurrentMouseDownContinueTracking(m, ScreenPtToClientPt(screenPt))) { return(processed); } else { // Mouse is not inside the client area of the current popup, so we are going to end all tracking // unless we can find a popup that wants to become the current popup because the mouse happens to // be other it, and it wants it. VisualPopup[] popups = _stack.ToArray(); // Search from end towards the front, the last entry is the most recent 'Push' for (int i = 0; i < popups.Length; i++) { // Ignore disposed popups VisualPopup popup = popups[i]; if (!popup.IsDisposed) { // If the mouse down is inside the popup instance if (popup.RectangleToScreen(popup.ClientRectangle).Contains(screenPt)) { // Does this stacked popup want to become the current one? if (popup.DoesStackedClientMouseDownBecomeCurrent(m, ScreenPtToClientPt(screenPt, popup.Handle))) { // Kill the popups until back at the requested popup while ((_current != null) && (_current != popup)) { _current.Dispose(); if (_stack.Count > 0) { _current = _stack.Pop(); } } } return(processed); } } } // Do any of the current popups want the mouse down to be eaten? if (_current != null) { processed = _current.DoesMouseDownGetEaten(m, screenPt); if (!processed) { // Search from end towards the front, the last entry is the most recent 'Push' for (int i = 0; i < popups.Length; i++) { // Ignore disposed popups VisualPopup popup = popups[i]; if (!popup.IsDisposed) { processed = popup.DoesMouseDownGetEaten(m, screenPt); if (processed) { break; } } } } } // Mouse down not intercepted by any popup, so end tracking EndAllTracking(); } } return(processed); }