private PresentationSource CriticalGetActiveSource() { IntPtr hwnd = MS.Win32.UnsafeNativeMethods.GetActiveWindow(); if (hwnd != IntPtr.Zero) { return(HwndSource.CriticalFromHwnd(hwnd)); } return(null); }
private void RestorePreviousFocus() { if (base.IsKeyboardFocusWithin) { IntPtr focus = UnsafeNativeMethods.GetFocus(); HwndSource hwndSource = (focus != IntPtr.Zero) ? HwndSource.CriticalFromHwnd(focus) : null; if (hwndSource != null) { Keyboard.Focus(null); return; } Keyboard.ClearFocus(); } }
internal static Visual GetElementFromPoint(IntPtr hwnd, Visual root, Point pointScreen) { HwndSource hwndSource = HwndSource.CriticalFromHwnd(hwnd); if (hwndSource == null) { return(null); } Point pointClient = PointUtil.ScreenToClient(pointScreen, hwndSource); Point pointRoot = PointUtil.ClientToRoot(pointClient, hwndSource); PointHitTestResult result = VisualTreeUtils.AsNearestPointHitTestResult(VisualTreeHelper.HitTest(root, pointRoot)); Visual visual = (result != null) ? result.VisualHit : null; return(visual); }
private void RestorePreviousFocus() { // Only restore focus if focus is still within the menu. If // focus has already been moved outside of the menu, then // we don't want to disturb it. if (IsKeyboardFocusWithin) { // Only restore WPF focus if the HWND with focus is an // HwndSource. This enables child HWNDs, other top-level // non-WPF HWNDs, or even child HWNDs of other WPF top-level // windows to retain focus when menus are dismissed. IntPtr hwndWithFocus = MS.Win32.UnsafeNativeMethods.GetFocus(); HwndSource hwndSourceWithFocus = hwndWithFocus != IntPtr.Zero ? HwndSource.CriticalFromHwnd(hwndWithFocus) : null; if (hwndSourceWithFocus != null) { // We restore focus by setting focus to the parent's focus // scope. This may not seem correct, because it presumes // the focus came from the logical-focus element of the // parent scope. In fact, it could have come from any // number of places. However, we have not figured out a // better solution for restoring focus across scenarios // such as: // // 1) A context menu of a menu item. // 2) Two menus side-by-side // 3) A menu and a toolbar side-by-side // // Simply remembering the last element with focus and // restoring focus to it does not work. For example, // two menus side-by-side will end up remembering each // other, and you can get stuck in an infinite loop. // // Restoring focus through the parent's focus scope will // not directly work if you open one window's menu from // another window. Visual Studio, as an example, will // intercept the focus change events and forward // appropriately for the scenario of restoring focus to // an element in a different top-level window. // DependencyObject parent = Parent; // if (parent == null) // { // If there is no logical parent, use the visual parent. // parent = VisualTreeHelper.GetParent(this); // } // if (parent != null) // { // IInputElement parentScope = FocusManager.GetFocusScope(parent) as IInputElement; // if (parentScope != null) // { // Keyboard.Focus(parentScope); // } // } // Unfortunately setting focus to the parent focusscope tripped up VS in the scenario where // Menus are contained within ToolBars. In this case when the Menu is dismissed they want // focus to be restored to the element in the main window that previously had focus. However // since ToolBar is the parent focusscope for the Menu we end up restoring focus to its // focusedelment. It is also noted that this implementation is a behavioral change from .Net 3.5. // Hence we are putting back the old behavior which is to set Keyboard.Focus to null which will // delegate focus through the main window to its focusedelement. Keyboard.Focus(null); } else { // In the case where Win32 focus is not on a WPF // HwndSource, we just clear WPF focus completely. // // Note that calling Focus(null) will set focus to the root // element of the active source, which is not what we want. Keyboard.ClearFocus(); } } }