private void InputHitTest(Point pt, out IInputElement enabledHit, out IInputElement rawHit, out PointHitTestResult rawHitResult) { var hitTestParameters = new PointHitTestParameters(pt); var inputHitTestResult = new InputHitTestResult(); VisualTreeHelper.HitTest(this, hitTestParameters, InputHitTestFilterCallback, inputHitTestResult.InputHitTestResultCallback); var visualHit = inputHitTestResult.Result; rawHit = (visualHit as IInputElement); rawHitResult = inputHitTestResult.HitTestResult; enabledHit = null; while (visualHit != null) { var uIElement = visualHit as UIElement; if (uIElement != null) { if (rawHit == null) { rawHit = uIElement; rawHitResult = null; } if (uIElement.IsEnabled) { enabledHit = uIElement; return; } } if (visualHit == this) { break; } visualHit = visualHit.Parent; } }
/// <summary> /// Returns the input element within this element that is /// at the specified coordinates relative to this element. /// </summary> /// <param name="pt"> /// This is the coordinate, relative to this element, at which /// to look for elements within this one. /// </param> /// <param name="enabledHit"> /// This element is the deepest enabled input element that is at the /// specified coordinates. /// </param> /// <param name="rawHit"> /// This element is the deepest input element (not necessarily enabled) /// that is at the specified coordinates. /// </param> /// <param name="rawHitResult"> /// Visual hit test result for the rawHit element /// </param> internal void InputHitTest(Point pt, out IInputElement enabledHit, out IInputElement rawHit, out HitTestResult rawHitResult) { PointHitTestParameters hitTestParameters = new PointHitTestParameters(pt); // We store the result of the hit testing here. Note that the // HitTestResultCallback is an instance method on this class // so that it can store the element we hit. InputHitTestResult result = new InputHitTestResult(); VisualTreeHelper.HitTest(this, new HitTestFilterCallback(InputHitTestFilterCallback), new HitTestResultCallback(result.InputHitTestResultCallback), hitTestParameters); DependencyObject candidate = result.Result; rawHit = candidate as IInputElement; rawHitResult = result.HitTestResult; enabledHit = null; while (candidate != null) { IContentHost contentHost = candidate as IContentHost; if (contentHost != null) { // Do not call IContentHost.InputHitTest if the containing UIElement // is not enabled. DependencyObject containingElement = InputElement.GetContainingUIElement(candidate); if ((bool)containingElement.GetValue(IsEnabledProperty)) { pt = InputElement.TranslatePoint(pt, this, candidate); enabledHit = rawHit = contentHost.InputHitTest(pt); rawHitResult = null; if (enabledHit != null) { break; } } } UIElement element = candidate as UIElement; if (element != null) { if (rawHit == null) { // Earlier we hit a non-IInputElement. This is the first one // we've found, so use that as rawHit. rawHit = element; rawHitResult = null; } if (element.IsEnabled) { enabledHit = element; break; } } UIElement3D element3D = candidate as UIElement3D; if (element3D != null) { if (rawHit == null) { // Earlier we hit a non-IInputElement. This is the first one // we've found, so use that as rawHit. rawHit = element3D; rawHitResult = null; } if (element3D.IsEnabled) { enabledHit = element3D; break; } } if (candidate == this) { // We are at the element where the hit-test was initiated. // If we haven't found the hit element by now, we missed // everything. break; } candidate = VisualTreeHelper.GetParentInternal(candidate); } }