private void Show() { this.timer.Stop(); // Check whether the window is // - still present (prevents exceptions when window is closed by system commands) // - still active (prevents keytips showing during Alt-Tab'ing) if (this.window == null || this.window.IsActive == false) { this.RestoreFocus(); return; } // Special behavior for backstage, application menu and start screen. // If one of those is open we have to forward key tips directly to them. var keyTipsTarget = this.GetStartScreen() ?? this.GetBackstage() ?? this.GetApplicationMenu() ?? this.ribbon; if (keyTipsTarget == null) { return; } this.ClosePopups(); this.backUpFocusedControl = null; // If focus is inside the Ribbon already we don't want to jump around after finishing with KeyTips if (UIHelper.GetParent <Ribbon>(Keyboard.FocusedElement as DependencyObject) == null) { this.backUpFocusedControl = FocusWrapper.GetWrapperForCurrentFocus(); } if (keyTipsTarget is Ribbon targetRibbon && targetRibbon.IsMinimized == false && targetRibbon.SelectedTabIndex >= 0 && targetRibbon.TabControl != null) { // Focus ribbon (this.ribbon.TabControl.ItemContainerGenerator.ContainerFromIndex(this.ribbon.TabControl.SelectedIndex) as UIElement)?.Focus(); } this.ClearUserInput(); if (this.activeAdornerChain != null) { this.activeAdornerChain.Terminated -= this.OnAdornerChainTerminated; } this.activeAdornerChain = new KeyTipAdorner(keyTipsTarget, keyTipsTarget, null); this.activeAdornerChain.Terminated += this.OnAdornerChainTerminated; this.activeAdornerChain.Attach(); }
private void Show() { this.timer.Stop(); // Check whether the window is // - still present (prevents exceptions when window is closed by system commands) // - still active (prevents keytips showing during Alt-Tab'ing) if (this.window == null || this.window.IsActive == false) { this.RestoreFocus(); return; } this.ClosePopups(); // If focus is inside the Ribbon already we don't want to jump around after finishing with KeyTips if (UIHelper.GetParent <Ribbon>(Keyboard.FocusedElement as DependencyObject) == null) { this.backUpFocusedControl = FocusWrapper.GetWrapperForCurrentFocus(); } // Focus ribbon this.ribbon.SelectedTabItem?.Focus(); this.ClearUserInput(); this.activeAdornerChain = new KeyTipAdorner(this.ribbon, this.ribbon, null); this.activeAdornerChain.Terminated += this.OnAdornerChainTerminated; // Special behavior for backstage var specialControl = this.GetBackstage() ?? this.GetApplicationMenu() ?? this.GetStartScreen(); if (specialControl != null) { this.DirectlyForwardToSpecialControl(specialControl); } else { this.activeAdornerChain.Attach(); } }
private void Show() { this.timer.Stop(); // Check whether the window is // - still present (prevents exceptions when window is closed by system commands) // - still active (prevents keytips showing during Alt-Tab'ing) if (this.window == null || this.window.IsActive == false) { this.RestoreFocus(); return; } this.backUpFocusedControl = FocusWrapper.GetWrapperForCurrentFocus(); // Focus ribbon this.ribbon.Focus(); this.ClearUserInput(); this.activeAdornerChain = new KeyTipAdorner(this.ribbon, this.ribbon, null); this.activeAdornerChain.Terminated += this.OnAdornerChainTerminated; // Special behavior for backstage var specialControl = this.GetBackstage() ?? this.GetApplicationMenu() ?? this.GetStartScreen(); if (specialControl != null) { this.DirectlyForwardToSpecialControl(specialControl); } else { this.activeAdornerChain.Attach(); } }
private void RestoreFocus() { this.backUpFocusedControl?.Focus(); this.backUpFocusedControl = null; }
private void OnWindowPreviewKeyDown(object sender, KeyEventArgs e) { if (e.IsRepeat || e.Handled) { return; } if (this.ribbon.IsCollapsed || this.ribbon.IsEnabled == false || this.window.IsActive == false) { return; } // Keytips should be cancelled if Alt+Num0 is pressed #241. // This allows entering special keys via numpad. if (e.KeyboardDevice.Modifiers == ModifierKeys.Alt && e.SystemKey >= Key.NumPad0 && e.SystemKey <= Key.NumPad9) { this.Terminate(); return; } if (IsShowOrHideKey(e)) { if (this.activeAdornerChain == null || this.activeAdornerChain.IsAdornerChainAlive == false || this.activeAdornerChain.AreAnyKeyTipsVisible == false) { this.ShowDelayed(); } else { this.Terminate(); } } else if (e.Key == Key.Escape && this.activeAdornerChain != null) { this.activeAdornerChain.ActiveKeyTipAdorner.Back(); this.ClearUserInput(); e.Handled = true; } else { if ((e.Key != Key.System && this.activeAdornerChain == null) || e.SystemKey == Key.Escape || (e.KeyboardDevice.Modifiers != ModifierKeys.Alt && this.activeAdornerChain == null)) { return; } var actualKey = e.Key == Key.System ? e.SystemKey : e.Key; // we need to get the real string input for the key because of keys like ä,ö,ü #258 var key = KeyEventUtility.GetStringFromKey(actualKey); var isKeyRealInput = string.IsNullOrEmpty(key) == false && key != "\t"; // Don't do anything and let WPF handle the rest if (isKeyRealInput == false) { // This block is a "temporary" fix for keyboard navigation not matching the office behavior. // If someone finds a way to implement it properly, here is your starting point. // In office: If you navigate by keyboard (in menus) and keytips are shown they are shown or hidden based on the menu you are in. // Implementing navigation the way office does would require complex focus/state tracking etc. so i decided to just terminate keytips and not restore focus. { this.backUpFocusedControl = null; this.Terminate(); } return; } var shownImmediately = false; // Should we show the keytips and immediately react to key? if (this.activeAdornerChain == null || this.activeAdornerChain.IsAdornerChainAlive == false || this.activeAdornerChain.AreAnyKeyTipsVisible == false) { this.ShowImmediatly(); shownImmediately = true; } if (this.activeAdornerChain == null) { return; } var previousInput = this.currentUserInput; this.currentUserInput += key; if (this.activeAdornerChain.ActiveKeyTipAdorner.ContainsKeyTipStartingWith(this.currentUserInput) == false) { // Handles access-keys #258 if (shownImmediately) { this.Terminate(); return; } // If no key tips match the current input, continue with the previously entered and still correct keys. this.currentUserInput = previousInput; System.Media.SystemSounds.Beep.Play(); e.Handled = true; return; } if (this.activeAdornerChain.ActiveKeyTipAdorner.Forward(this.currentUserInput, true)) { this.ClearUserInput(); e.Handled = true; return; } this.activeAdornerChain.ActiveKeyTipAdorner.FilterKeyTips(this.currentUserInput); e.Handled = true; } }
private void Show() { this.timer.Stop(); // Check whether the window is // - still present (prevents exceptions when window is closed by system commands) // - still active (prevents keytips showing during Alt-Tab'ing) if (this.window == null || this.window.IsActive == false) { this.RestoreFocus(); return; } this.backUpFocusedControl = FocusWrapper.GetWrapperForCurrentFocus(); // Focus ribbon this.ribbon.Focus(); this.ClearUserInput(); this.activeAdornerChain = new KeyTipAdorner(this.ribbon, this.ribbon, null); this.activeAdornerChain.Terminated += this.OnAdornerChainTerminated; // Special behavior for backstage var specialControl = this.GetBackstage() ?? this.GetApplicationMenu() ?? this.GetStartScreen(); if (specialControl != null) { this.DirectlyForwardToSpecialControl(specialControl); } else { this.activeAdornerChain.Attach(); } }
private void RestoreFocus() { this.backUpFocusedControl?.Focus(); this.backUpFocusedControl = null; }
private void OnWindowPreviewKeyDown(object sender, KeyEventArgs e) { if (e.IsRepeat || e.Handled) { return; } if (this.ribbon.IsCollapsed || this.ribbon.IsEnabled == false || this.window.IsActive == false) { return; } // Keytips should be cancelled if Alt+Num0 is pressed #241. // This allows entering special keys via numpad. if (e.KeyboardDevice.Modifiers == ModifierKeys.Alt && e.SystemKey >= Key.NumPad0 && e.SystemKey <= Key.NumPad9) { this.activeAdornerChain?.Terminate(); return; } if (IsShowOrHideKey(e)) { if (this.activeAdornerChain == null || this.activeAdornerChain.IsAdornerChainAlive == false || this.activeAdornerChain.AreAnyKeyTipsVisible == false) { this.ShowDelayed(); } else { this.activeAdornerChain?.Terminate(); return; } } else if (e.Key == Key.Escape && this.activeAdornerChain != null) { this.activeAdornerChain.ActiveKeyTipAdorner.Back(); this.ClearUserInput(); e.Handled = true; return; } else { if ((e.Key != Key.System && this.activeAdornerChain == null) || e.SystemKey == Key.Escape || (e.KeyboardDevice.Modifiers != ModifierKeys.Alt && this.activeAdornerChain == null)) { return; } var actualKey = e.Key == Key.System ? e.SystemKey : e.Key; // we need to get the real string input for the key because of keys like ä,ö,ü #258 var key = KeyEventUtility.GetStringFromKey(actualKey); var isKeyRealInput = string.IsNullOrEmpty(key) == false; // Don't do anything and let WPF handle the rest if (isKeyRealInput == false) { // This block is a "temporary" fix for keyboard navigation not matching the office behavior. // If someone finds a way to implement it properly, here is your starting point. // In office: If you navigate by keyboard (in menus) and keytips are shown they are shown or hidden based on the menu you are in. // Implementing navigation the way office does would require complex focus/state tracking etc. so i decided to just terminate keytips and not restore focus. { this.backUpFocusedControl = null; this.activeAdornerChain?.Terminate(); } return; } var shownImmediately = false; // Should we show the keytips and immediately react to key? if (this.activeAdornerChain == null || this.activeAdornerChain.IsAdornerChainAlive == false || this.activeAdornerChain.AreAnyKeyTipsVisible == false) { this.ShowImmediatly(); shownImmediately = true; } if (this.activeAdornerChain == null) { return; } var previousInput = this.currentUserInput; this.currentUserInput += key; if (this.activeAdornerChain.ActiveKeyTipAdorner.ContainsKeyTipStartingWith(this.currentUserInput) == false) { // Handles access-keys #258 if (shownImmediately) { this.activeAdornerChain?.Terminate(); return; } // If no key tips match the current input, continue with the previously entered and still correct keys. this.currentUserInput = previousInput; System.Media.SystemSounds.Beep.Play(); e.Handled = true; return; } else if (this.activeAdornerChain.ActiveKeyTipAdorner.Forward(this.currentUserInput, true)) { this.ClearUserInput(); e.Handled = true; return; } else { this.activeAdornerChain.ActiveKeyTipAdorner.FilterKeyTips(this.currentUserInput); e.Handled = true; return; } } }