0
votes

I want to use the tab key to change focus between 6 edit controls.

I set the parent window style to WS_EX_CONTROLPARENT

I set the edit controls style to WS_TABSTOP

I call IsDialogMessage to ignore messages that have been handled

It works great!

Now I want to split the controls into two groups of three, so that tabbing in the third control returns focus to the first, and tabbing in the sixth returns control to the fourth ( rather than the first )

So I add WS_GROUP to the style of the first and fourth control

    auto ret = SetWindowLongPtr(
        myEditbox.handle(),
        GWL_STYLE,
        GetWindowLongPtr( myEditbox.handle(), GWL_STYLE) | WS_GROUP  );
    if( ret == 0 )
        throw std::runtime_error("setGroupStyle");

Nothing happens. Tabbing causes keyboard focus to move through controls 1 to 6 and back to 1 as before.

@PaulSanders points out that WS_GROUP affects arrow key behavior, NOT tab key. The Windows documentation appears to confirm this.

The window is the first control of a group of controls. The group consists of this first control and all controls defined after it, up to the next control with the WS_GROUP style. The first control in each group usually has the WS_TABSTOP style so that the user can move from group to group. The user can subsequently change the keyboard focus from one control in the group to the next control in the group by using the direction keys. You can turn this style on and off to change dialog box navigation. To change this style after a window has been created, use the SetWindowLong function. ( https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles )

So, I tried removing the WS_TABSTOP style from the controls, expecting to see the direction controls change the focus. Doesn't work - the arrow keys just move the text cursor through the edit control, not the focus between controls.

What do I need to do more, or differently?

2

2 Answers

2
votes

This is different than the normal dialog traversal, so you will have to implement it yourself rather than relying on IsDialogMessage(). It might be possible to use non-modal child dialogs leaving off the WS_EX_CONTROLPARENT extended style, but I do not believe that would actually do what you want.

I suggest you use SetWindowSubClass() to attach a sub-class function to the first and last edit controls of each group, and have it handle WM_CHAR messages with tab characters, setting focus as appropriate.

0
votes

I managed to get this to work using IsDialogMessage

Two tricks:

  • Add WS_TABSTOP to every control you want to visit by tabbing

  • Add WS_EX_CONTROLPARENT to every window that contains controls that are visited by tabbing. This includes windows that contain other windows that eventually contain the controls. ( If this is ommited, IsDialogMessage will hang when tabbing reaches the final control and should loop back to the first ) https://stackoverflow.com/a/11090609/16582