Keyboard navigation with nested TabStrips

Docking/MDI for Windows Forms Forum

Posted 11 years ago by Shaun Martin - RevQ
Version: 2.0.0098
Avatar
I have two nested TabStrips, inner and outer, and am wondering how to control each TabStrip independently, using the keyboard.

Currently, this is what happens (KeyboardNavigationEnabled = true for both):

If the inner TabStrip has only one tab, the outer TabStrip handles the Control+Tab. If the inner TabStrip has more than one tab, then it handles the Control+Tab, not the outer.

When the inner and outer TabStrips both have multiple tabs, I would like to be able to cycle either the inner or outer tabs, using the keyboard. Ideally, I'd be able to use a different key combination (such as Control+Alt+Tab) to control the inner TabStrip and use the Control+Tab to control the outer TabStrip.

Anyone know how to do this?

Thanks!

Comments (7)

Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Shaun,

If you have KeyboardNavigationEnabled for both, the ProcessCmdKey method will trap the Ctrl+Tab and Ctrl+Shift+Tab keys right now. You can create a class that inherits TabStrip and override that method to provide the additional functionality you desire.


Actipro Software Support

Posted 11 years ago by Shaun Martin - RevQ
Avatar
Ok, thanks for the reply, sorry for the delay, here's what I did.

As you suggested I created a derived TabStrip class with an overridden ProcessCmdKey method which cycled the tabs on Ctrl+Alt+Tab. That was with the *inner* of the two nested TabStrips. The problem is that I want Ctrl+Tab to cycle the tabs in the *outer* TabStrip - the inner TabStrip should inspect the key command (which it does) and if it's not Ctrl+Alt+Tab, then the key command is passed to the outer TabStrip. What I'm seeing is that if the inner TabStrip sees the command/message/keys/whatever, the outer TabStrip doesn't. Make sense? I need some way to pass the command along (bubble up).

Thanks for your help.

Here's my ProcessCmdKey override:

        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData)
        {
            if (m_useAltKeyNav)
            {
                if (keyData == (System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.Tab))
                {
                    if (this.Pages != null && this.Pages.Count > 1)
                    {
                        this.SelectedIndex = (this.SelectedIndex + 1) % this.Pages.Count;
                    }

                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
                return base.ProcessCmdKey(ref m, keyData);
        }
Posted 11 years ago by Shaun Martin - RevQ
Avatar
I apologize - some of the above info isn't correct. What I have is NOT two nested TabStrips, but instead a TabStrip nested [in a document] in a DockManager, where the DockManager has the following settings:

DocumentMdiStyle = Tabbed
KeyboardNavigationEnabled = true
NextWindowNavigationEnabled = true
NextWindowNavigationType = DocumentWindow

All the behavior I've described is correct though...sorry for the confusion.
Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Shaun,

Why don't you just override ProcessCmdKey on the inner TabStrip and if you see Ctrl+Tab then do not call the base method? That would block the inner one from grabbing it and would probably allow it to bubble up, no?


Actipro Software Support

Posted 11 years ago by Shaun Martin - RevQ
Avatar
Currently if m_useAltKeyNav is true (meaning we're looking for Ctrl+Alt+Tab), we don't call the base. I tried commenting out the base call, just in case my logic was wrong, and I still see the same behavior. Even though we're not calling the base, it appears to me that the overridden ProcessCmdKey is not allowing the message/event/command to bubble up. Or perhaps just setting KeyboardNavigationEnabled to true is causing the message to always be trapped?

In an earlier post, I mentioned that if the inner TabStrip had only one tab, the key command would bubble up. This was wrong. In my test, the inner TabStrip that only had one tab also had KeyboardNavigationEnabled set to false. If I set it to true, key commands don't bubble up, even with just one tab/page in the TabStrip.

Again, I appreciate your help.
Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Just looked at the code again. ProcessCmdKey is the only method in TabStrip in which we look for Ctrl+Tab and we only do that if KeyboardNavigationEnabled is true.

Maybe you should change your code above to not "return false;" in that one case but also call the base method in that case like in your other "else"?


Actipro Software Support

Posted 11 years ago by Shaun Martin - RevQ
Avatar
No, calling the base how you suggested would essentially be the same as using the base implementation of ProcessCmdKey when anything other than Ctrl+Alt+Tab is pressed. I tried it and it caused my inner TabStrip to switch pages on BOTH Ctrl+Alt+Tab and Ctrl+Tab.

I found a solution though, albeit a bit of a hack. I still believe that if KeyboardNavigationEnabled is enabled, ANY implementation of ProcessCmdKey (base or overridden) will prevent the key command from bubbling up. That's the basis for my workaround (I removed my m_useAltKeyNav flag for clarity) which turns off KeyboardNavigationEnabled briefly while the base ProcessCmdKey is called so that the key command will bubble up:

        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message m, System.Windows.Forms.Keys keyData)
        {
            if (keyData == (System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.Tab))
            {
                if (this.Pages != null && this.Pages.Count > 1)
                {
                    this.SelectedIndex = (this.SelectedIndex + 1) % this.Pages.Count;
                }

                return true;
            }
            else
            {
                this.KeyboardNavigationEnabled = false;
                bool result = base.ProcessCmdKey(ref m, keyData);
                this.KeyboardNavigationEnabled = true;
                return result;
            }
        }
Anyway, thanks for your help.
The latest build of this product (v2020.1 build 0400) was released 9 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.