private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { if (!e.Handled && e.Scope == null && e.Target == null) { e.Target = sender as GroupBox; } }
private void OnAccessKeyPressed(object sender, System.Windows.Input.AccessKeyPressedEventArgs e) { string rawKey = e.Key; if (Int32.TryParse(rawKey, out int index)) { rawKey = $"D{index}"; } if (Enum.TryParse(rawKey, out Key pressed) && pressed != Key.None) { AccessKeyPressingEventArgs args = new AccessKeyPressingEventArgs(keys, pressed); if (pressingHandler != null) { pressingHandler(window, args); } if (!args.IsCancelled) { keys.Add(pressed); } e.Handled = true; } }
private void accessKeyPressed(object sender, System.Windows.Input.AccessKeyPressedEventArgs e) { if (Keyboard.Modifiers != ModifierKeys.Alt) { e.Scope = sender; e.Handled = true; } }
private static void HandleScopedElementAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { if (!Keyboard.IsKeyDown(Key.LeftAlt) && !Keyboard.IsKeyDown(Key.RightAlt) && GetIsAccessKeyScope((DependencyObject)sender)) { e.Scope = sender; e.Handled = true; } }
/// <summary> /// Fixes access key scoping bug within the WPF framework. /// </summary> /// <param name="sender">Potential target of the current access keys.</param> /// <param name="e"> /// Info object for the current access keys and proxy to effect it's confirmation. /// </param> /// <remarks> /// The problem is that all access key presses are scoped to the active window, /// regardless of what properties, handlers, scope etc. you may have set. Targets /// are objects that have potential to be the target of the access keys in effect. /// /// If you happen to have a current object focused and you press the access keys /// of one of it's child's targets it will execute the child target. But, if you /// also have a ancestor target, the ancestor target will be executed instead. /// That goes against intuition and standard Windows behavior. /// The root of this logic (bug) is within the HwndSource.OnMnemonicCore method. /// If the scope is set to anything but the active window's HwndSource, the /// target will not be executed and the handler for the next target in the chain /// will be called. /// This handler gets called for every target within the scope, which because /// of the bug is always at the window level of the active window. If you set /// e.Handled to true, no further handlers in the chain will be executed. However /// because setting the scope to anything other than active window's HwndSource /// causes the target not to be acted on, we can use it to not act on the target /// while not canceling the chain either, thereby allowing us to skip to the next /// target's handler. Note that if a handler does act on the target it will /// inheritably break the chain because the menu will lose focus and the next /// handlers won't apply anymore; because a target has already been confirmed. /// We will use this knowledge to resolve the issue. /// We will set the scope to something other than the active window's HwndSource, /// if we find that the incorrect element is being targeted for the access keys /// (because the target is out of scope). This will cause the target to be /// skipped and the next target's handler will be called. /// If we detect the target is correct, we'll just leave everything alone so the /// target will be confirmed. /// /// NOTE: Do not call AccessKeyManager.IsKeyRegistered as it will cause a /// <see cref="T:System.StackOverflowException"/> to be thrown. The key is /// registered otherwise this handler wouldn't be called for it, therefore /// there is no need to call it. /// </remarks> private static void HandleAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { var focusedElement = Keyboard.FocusedElement as FrameworkElement; if (focusedElement == null) return; // No focused element. if (Equals(sender, focusedElement)) return; // This is the correct target. // Look through descendants tree to see if this target is a descendant of // the focused element. We will stop looking at either the end of the tree // or if a object with multiple children is encountered that this target // isn't a descendant of. // If no valid target is found, we'll set the scope to the sender which // results in skipping to the next target handler in the chain // (due to the bug). DependencyObject obj = focusedElement; while (obj != null) { int childCount = VisualTreeHelper.GetChildrenCount(obj); for (int i = 0; i < childCount; i++) { if (VisualTreeHelper.GetChild(obj, i) == sender) return; // Found correct target; let it execute. } if (childCount > 1) { // This target isn't a direct descendant and there are multiple // direct descendants; skip this target. e.Scope = sender; return; } if (childCount == 1) { // This target isn't a direct descendant, but we'll keep looking // down the descendants chain to see if it's a descendant of the // direct descendant. obj = VisualTreeHelper.GetChild(obj, 0); } else { // End of the line; skip this target. e.Scope = sender; return; } } }
/// <summary> /// Returns scope for the given element. /// </summary> /// <param name="element"></param> /// <param name="key"></param> /// <returns>Scope for the given element, null means the context global scope</returns> private AccessKeyInformation GetInfoForElement(IInputElement element, string key) { AccessKeyInformation info = new AccessKeyInformation(); if (element != null) { AccessKeyPressedEventArgs args = new AccessKeyPressedEventArgs(key); element.RaiseEvent(args); info.Scope = args.Scope; info.target = args.Target; if (info.Scope == null) { info.Scope = GetSourceForElement(element); } } else { info.Scope = CriticalGetActiveSource(); } return(info); }
private string GetAccessKeyCharacter(DependencyObject d) { // See what the local value for AccessKeyElement is first and start with that. WeakReference cachedElementWeakRef = (WeakReference)d.GetValue(AccessKeyElementProperty); IInputElement accessKeyElement = (cachedElementWeakRef != null) ? (IInputElement)cachedElementWeakRef.Target : null; if (accessKeyElement != null) { // First figure out if the target of accessKeyElement is still "d", then go find // the "primary" character for the accessKeyElement. AccessKeyPressedEventArgs accessKeyPressedEventArgs = new AccessKeyPressedEventArgs(); accessKeyElement.RaiseEvent(accessKeyPressedEventArgs); if (accessKeyPressedEventArgs.Target == d) { // Because there is no way to get at the access key element's character from the // element (there is no interface or anything) we have to go through all registered // access keys and see if this access key element is still registered and what its // "primary" character is. foreach (DictionaryEntry entry in Current._keyToElements) { ArrayList elements = (ArrayList)entry.Value; for (int i = 0; i < elements.Count; i++) { // If this element matches accessKeyElement, then return the current character WeakReference currentElementWeakRef = (WeakReference)elements[i]; if (currentElementWeakRef.Target == accessKeyElement) { return (string)entry.Key; } } } } } // There was no access key stored or it no longer matched. Clear out the cache and figure it out again. d.ClearValue(AccessKeyElementProperty); foreach (DictionaryEntry entry in Current._keyToElements) { ArrayList elements = (ArrayList)entry.Value; for (int i = 0; i < elements.Count; i++) { // Determine the target for this element. Cache the weak reference for the element on the target. WeakReference currentElementWeakRef = (WeakReference)elements[i]; IInputElement currentElement = (IInputElement)currentElementWeakRef.Target; if (currentElement != null) { AccessKeyPressedEventArgs accessKeyPressedEventArgs = new AccessKeyPressedEventArgs(); currentElement.RaiseEvent(accessKeyPressedEventArgs); // If the target was non-null, cache the access key element on the target. // if the target matches "d", return the current character. if (accessKeyPressedEventArgs.Target != null) { accessKeyPressedEventArgs.Target.SetValue(AccessKeyElementProperty, currentElementWeakRef); if (accessKeyPressedEventArgs.Target == d) { return (string)entry.Key; } } } } } return String.Empty; }
/// <summary> /// This is overridden to pass hot keys on to the contained user control. /// </summary> /// <param name="m">The message to pre-process</param> /// <returns>True if the message was handled, false if not</returns> /// <remarks>When a WPF user control is hosted in a docked tool window, the hot keys no longer work. /// This works around the problem by manually seeing if the control makes use of the hot key, and if /// it does, processing it here.</remarks> protected override bool PreProcessMessage(ref System.Windows.Forms.Message m) { if(m.Msg == 0x0100 /* WM_KEYDOWN */) { System.Windows.Forms.Keys keyCode = (System.Windows.Forms.Keys)m.WParam & System.Windows.Forms.Keys.KeyCode; if(keyCode == System.Windows.Forms.Keys.F1) { ApplicationCommands.Help.Execute(null, (UserControl)base.Content); return true; } } if(m.Msg == 0x0104 /*WM_SYSKEYDOWN*/) { if(Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) { // Cache a copy of the scope on first use if(scope == null && base.Content != null) { // Get the scope for handling hot keys. The key used here doesn't matter. We're just // getting the scope to use. AccessKeyPressedEventArgs e = new AccessKeyPressedEventArgs("X"); ((UserControl)base.Content).RaiseEvent(e); scope = e.Scope; } string key = ((char)m.WParam).ToString(); // See if the hot key is registered for the control. If so, handle it. Ignore Alt+F4 though // as it should close Visual Studio (it comes through as a lowercase "s"). if(scope != null && key != "s" && AccessKeyManager.IsKeyRegistered(scope, key)) { AccessKeyManager.ProcessKey(scope, key, false); return true; } } } return base.PreProcessMessage(ref m); }
private string GetAccessKeyCharacter(DependencyObject d) { // See what the local value for AccessKeyElement is first and start with that. WeakReference cachedElementWeakRef = (WeakReference)d.GetValue(AccessKeyElementProperty); IInputElement accessKeyElement = (cachedElementWeakRef != null) ? (IInputElement)cachedElementWeakRef.Target : null; if (accessKeyElement != null) { // First figure out if the target of accessKeyElement is still "d", then go find // the "primary" character for the accessKeyElement. AccessKeyPressedEventArgs accessKeyPressedEventArgs = new AccessKeyPressedEventArgs(); accessKeyElement.RaiseEvent(accessKeyPressedEventArgs); if (accessKeyPressedEventArgs.Target == d) { // Because there is no way to get at the access key element's character from the // element (there is no interface or anything) we have to go through all registered // access keys and see if this access key element is still registered and what its // "primary" character is. foreach (DictionaryEntry entry in Current._keyToElements) { ArrayList elements = (ArrayList)entry.Value; for (int i = 0; i < elements.Count; i++) { // If this element matches accessKeyElement, then return the current character WeakReference currentElementWeakRef = (WeakReference)elements[i]; if (currentElementWeakRef.Target == accessKeyElement) { return((string)entry.Key); } } } } } // There was no access key stored or it no longer matched. Clear out the cache and figure it out again. d.ClearValue(AccessKeyElementProperty); foreach (DictionaryEntry entry in Current._keyToElements) { ArrayList elements = (ArrayList)entry.Value; for (int i = 0; i < elements.Count; i++) { // Determine the target for this element. Cache the weak reference for the element on the target. WeakReference currentElementWeakRef = (WeakReference)elements[i]; IInputElement currentElement = (IInputElement)currentElementWeakRef.Target; if (currentElement != null) { AccessKeyPressedEventArgs accessKeyPressedEventArgs = new AccessKeyPressedEventArgs(); currentElement.RaiseEvent(accessKeyPressedEventArgs); // If the target was non-null, cache the access key element on the target. // if the target matches "d", return the current character. if (accessKeyPressedEventArgs.Target != null) { accessKeyPressedEventArgs.Target.SetValue(AccessKeyElementProperty, currentElementWeakRef); if (accessKeyPressedEventArgs.Target == d) { return((string)entry.Key); } } } } } return(String.Empty); }
private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { if (!e.Handled && e.Scope == null && e.Target == null) { e.Target = (UIElement)sender; } }
//-------------------------------------------------------------- private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs eventArgs) { // This code is borrowed from the WPF TabItem. if (!eventArgs.Handled && eventArgs.Scope == null) { var dockTabItem = (DockTabItem)sender; if (eventArgs.Target == null) { eventArgs.Target = dockTabItem; } else if (!dockTabItem.IsSelected) // If DockTabItem is not active it is a scope for its content elements. { eventArgs.Scope = dockTabItem; eventArgs.Handled = true; } } }
// custom event to work around .NET bug to prevent access key fireup without ALT key pressed private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { // allowing default for enter and escape keys if (Keyboard.IsKeyDown(Key.Enter) || Keyboard.IsKeyDown(Key.Escape)) return; if (!e.Handled && e.Scope == null && (e.Target == null || e.Target is Label)) { // If Alt key is not pressed - handle the event if ((Keyboard.Modifiers & ModifierKeys.Alt) != ModifierKeys.Alt) { e.Target = null; e.Handled = true; } } }
void GridAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { throw new NotImplementedException(); }
private void UpdateIsDefaulted(IInputElement focus) { // If it's not a default button, or nothing is focused, or it's disabled then it's not defaulted. if (!IsDefault || focus == null || !IsEnabled) { SetValue(IsDefaultedPropertyKey, BooleanBoxes.FalseBox); return; } DependencyObject focusDO = focus as DependencyObject; object thisScope, focusScope; // If the focused thing is not in this scope then IsDefaulted = false AccessKeyPressedEventArgs e; object isDefaulted = BooleanBoxes.FalseBox; try { // Step 1: Determine the AccessKey scope from currently focused element e = new AccessKeyPressedEventArgs(); focus.RaiseEvent(e); focusScope = e.Scope; // Step 2: Determine the AccessKey scope from this button e = new AccessKeyPressedEventArgs(); this.RaiseEvent(e); thisScope = e.Scope; // Step 3: Compare scopes if (thisScope == focusScope && (focusDO == null || (bool)focusDO.GetValue(KeyboardNavigation.AcceptsReturnProperty) == false)) { isDefaulted = BooleanBoxes.TrueBox; } } finally { SetValue(IsDefaultedPropertyKey, isDefaulted); } }
private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { Label label = sender as Label; // ISSUE: if this is handled in Control then we need to check here as well if (!e.Handled && e.Scope == null && (e.Target == null || e.Target == label)) { e.Target = label.Target; } }
private void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs args) { foreach (string accessKey in _renameAccessKeys) { if (string.Compare(accessKey, args.Key, StringComparison.OrdinalIgnoreCase) == 0) { args.Target = this; args.Handled = true; return; } } }
private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { MenuItem menuItem = sender as MenuItem; bool isScope = false; if (e.Target == null) { // MenuItem access key should not work if something else beside MenuBase has capture if (Mouse.Captured == null || Mouse.Captured is MenuBase) { e.Target = menuItem; // special case is if we are the original source and our submenu is open, // this is the case where the mouse moved over the header and focus is on // the menu item but really you want to access key processing to be in your // submenu. // This assumes that no one will ever directly register a MenuItem with the AKM. if (e.OriginalSource == menuItem && menuItem.IsSubmenuOpen) { isScope = true; } } else { e.Handled = true; } } else if (e.Scope == null) { // We want menu items to be a scope, but not for any AKs in its header. // If e.Target is already filled in, check if it's a MenuItem. // If it is and it's not us, we are its scope (i.e. we're the first MenuItem // above it in the chain). If it's not a MenuItem, we have to take the long way. if (e.Target != menuItem && e.Target is MenuItem) { isScope = true; } else { // This case handles when you have some non-MenuItem in a menu that can be // the target of access keys, like a Button. // MenuItems are a scope for all access keys which are outside of themselves. // e.Source is the logical element in which the event was raised. // If we can walk from the source to ourselves, then we are not correct // scope of this access key; some parent should be. DependencyObject source = e.Source as DependencyObject; while (source != null) { // If we walk up to this Menuitem, we are not the scope. if (source == menuItem) { break; } UIElement uiElement = source as UIElement; // If we walk up to an item which is one of our children, we are their scope. if ((uiElement != null) && (ItemsControlFromItemContainer(uiElement) == menuItem)) { isScope = true; break; } source = GetFrameworkParent(source); } } } if (isScope) { e.Scope = menuItem; e.Handled = true; } }
/// <summary> /// This is overridden to pass hot keys on to the contained user control. /// </summary> /// <param name="m">The message to pre-process</param> /// <returns>True if the message was handled, false if not</returns> /// <remarks>When a WPF user control is hosted in a docked tool window, the hot keys no longer /// work. This works around the problem by manually seeing if the control makes use of the /// hot key, and if it does, processing it here.</remarks> protected override bool PreProcessMessage(ref System.Windows.Forms.Message m) { if(m.Msg == 0x0100 /* WM_KEYDOWN */) { System.Windows.Forms.Keys keyCode = (System.Windows.Forms.Keys)m.WParam & System.Windows.Forms.Keys.KeyCode; if(keyCode == System.Windows.Forms.Keys.F1) { ApplicationCommands.Help.Execute(null, ucTopicPreviewer); return true; } } if(m.Msg == 0x0104 /*WM_SYSKEYDOWN*/) { if(Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) { // Cache a copy of the scope on first use if(scope == null && base.Content != null) { // Get the scope for handling hot keys. The key used here doesn't matter. // We're just getting the scope to use. AccessKeyPressedEventArgs e = new AccessKeyPressedEventArgs("X"); ucTopicPreviewer.RaiseEvent(e); scope = e.Scope; } string key = ((char)m.WParam).ToString(); // See if the hot key is registered for the control. If so, handle it. if(scope != null && AccessKeyManager.IsKeyRegistered(scope, key)) { AccessKeyManager.ProcessKey(scope, key, false); return true; } } } return base.PreProcessMessage(ref m); }
//------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { if (!e.Handled && e.Scope == null) { TabItem tabItem = sender as TabItem; if (e.Target == null) { e.Target = tabItem; } else if (!tabItem.IsSelected) // If TabItem is not active it is a scope for its content elements { e.Scope = tabItem; e.Handled = true; } } }
//-------------------------------------------------------------- private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs eventArgs) { if (eventArgs.Handled || eventArgs.Scope != null) return; var focusedElement = Keyboard.FocusedElement as FrameworkElement; if (focusedElement == null) return; // Do not accept access keys that originated outside of the DockTabPane. var dockTabPane = (DockTabPane)sender; if (!dockTabPane.IsVisualAncestorOf(focusedElement)) { // Do not set eventArgs.Handled because this would break the chain. // --> Setting the scope skips the current target. eventArgs.Scope = dockTabPane; // See DigitalRune.Windows.AccessKeyScope for additional information! } }
//------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { // If ALT is down, then blend our scope into the one above. Maybe bad, but only if Menu is not top-level. if (!(Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))) { e.Scope = sender; e.Handled = true; } }
private AccessKeyInformation GetInfoForElement(IInputElement element, string key) { AccessKeyInformation info = new AccessKeyInformation(); if (element != null) { AccessKeyPressedEventArgs args = new AccessKeyPressedEventArgs(key); element.RaiseEvent(args); info.Scope = args.Scope; info.target = args.Target; if (info.Scope == null) { info.Scope = GetSourceForElement(element); } } else { info.Scope = CriticalGetActiveSource(); } return info; }
private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { e.Scope = sender; e.Handled = true; }
private void Window_AccessKeyPressed(object sender, System.Windows.Input.AccessKeyPressedEventArgs e) { }