We have a series of dialogs in our application for which the dialog template defines 4 buttons along the bottom of the screen. However (depending which version of our hardware the application is running on) we sometimes create 2 additional buttons and then line up the 6 buttons (4 from the template, 2 created by calling CButton::Create()) along the bottom.
The problem I have is that usually the user can move the focus between these buttons using the left / right arrow keys (there is no mouse or touchscreen, just a restricted keyboard). This follows the control TAB-order as you would expect for the 4 buttons from the template. However the 2 dynamically create controls appear to be inserted at the beginning of the TAB-order, and that means (because they are put at the right-hand side of the screen) that they are in the "wrong" order as far as the cursor keys goes. In other words, when the focus gets to the left-hand button (TAB order 1) pressing the left arrow jumps the focus to the button on the right-hand side, which is just plain confusing...
There appears to be some link between Z-order (which I can affect with SetWindowPos()
) and TAB-order but it does not seem to be a simple 1-to-1: by changing the Z-order I can move the sequence around so that the buttons are completely in the wrong order, so I can change the Z-order, but I can't work out how to get them in the right order.
Can anyone give a concise explanation of how TAB-order works, and how to control the sequencing of controls at runtime?
Edit:
kol suggested below using SetWindowPos()
to set the Z-order. This I had tried before but it does not let the cursor keys control the focus as expected.
However, by rigging this up so I can use TAB (as a test -- this isn't practical for the end-user solution) I find that kol's solution does resolve the TAB-order. The problem I have is that this is not the same as the order used by the cursor keys!
So, revised question: how can I specify the order in which left / right cursor keys move focus between controls?
Solution: With assistance from kol and MarkRansom's input, I have got this working now.
I used SetWindowPos()
as suggested by kol to put my new buttons after the existing buttons in the TAB order, and then (as Mark suggested) made the first button WS_GROUP | WS_TABSTOP
but cleared those flags from the other buttons.
However this was not enough to solve the problem, with the 2 new buttons still appearing to come before the first rather than after the second when using arrow keys (not TAB) to move around.
I looked at my dialog template, and it was like this:
IDD_QUERY DIALOG 0, 0, 156, 34
STYLE DS_SETFONT | WS_POPUP | WS_CAPTION
FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "+++Skey1+++",IDC_SKEY_1,1,21,36,12
PUSHBUTTON "+++Skey2+++",IDC_SKEY_2,40,21,37,12
PUSHBUTTON "+++Skey3+++",IDC_SKEY_3,79,21,36,12
PUSHBUTTON "+++Skey4+++",IDC_SKEY_4,118,21,36,12
LTEXT "Static",IDC_QUERY_MSG,2,1,153,15
END
So the static IDC_QUERY_MSG
, which is used to display information to the user, was coming after the 4th button in the template. To resolve the problem, I moved IDC_QUERY_MSG
before the first button (IDC_SKEY_1
): this means the 6 buttons are not split up by a static inbetween, and has solved the problem.
Thanks to everyone for their assistance!