Skip to content

The Hidden Dangers of TRadioButton.TabStop

TRadioButton has a TabStop property. It looks harmless enough. Why not set it? You’d like the user to be able to set radio button controls with the keyboard, right?

Trust me, just leave that little bastard alone.

To understand why, we should review the Windows standards for interacting with radio buttons using the keyboard. If you drop several TRadioButtons onto a group box, then these buttons are treated as a group; although they aren’t quite the same thing as a TRadioGroup, they behave similarly. Namely, if you tab into the group box, then the checked radio button will receive input focus. If you press tab again, you will tab out of the group box. When the checked radio button has focus, pressing the arrow keys will check a different radio button in the group (and un-check all other radio buttons in the group box).

The VCL does not rely on Windows for this behavior; instead, it is implemented in the VCL source code, and you can trace through it.

The reason that this is on my mind is because of a curious bug report I received the other day. A tester reported that tabbing into a radio group on a certain form caused the selection to change (in other words, a different radio button was checked simply by tabbing into the group box). Based upon the explanation above, you can probably see where this is headed, but it took me a long time to figure out. The behavior was easy to reproduce, and I could even see a CN_COMMAND message of BN_CLICKED in the debugger, but it was near the top of the call stack, and I could not figure out where it was coming from.

It seems that if you tab to this particular radio button, and only this particular radio button, and only when you first enter the form, Windows will send BN_CLICKED. But why was I able to tab to a non-selected radio button at all? Shouldn’t focus go to the selected button?

No, not really. Again, Windows doesn’t choose which control is focused when you press tab; the Delphi VCL does. Glossing over a few details, it essentially looks for the next enabled control where TabStop is true. When you click a radio button, in addition to un-checking all of the other radio buttons in the group, the VCL sets their TabStop properties to False.

But only if they weren’t checked in the first place. If a radio button is not already checked, then its TabStop property will not be set false when another radio button in the radio group has its Checked property set true.

So here is what actually happened:

  1. A few months ago, a well-meaning developer had done some tab order maintenance on the form in question. He changed the TabStop and TabIndex properties of a number of controls. The changes looked quite innocuous, and even passed code review.
  2. Unfortunately, he had set TabStop true on a TRadioButton which was not Checked.
  3. Some code in the form configured the radio group by setting the Checked property of a different radio button True. This caused the Checked and TabStop properties of the other radio buttons in the group to be set False, but only if their Checked properties were not true to begin with.
  4. Now the tester tabbed into the group box. The first radio button in the tab order was not checked, so a BN_CLICKED message is sent. The tester is surprised that the "wrong" radio button is focused, and, worse, it is checked, as well.

The moral of the story? Just don’t touch the TRadioButton.TabStop property. The VCL is going to manipulate it in code. Leave it at its default value. If you want to change whether or not the user can tab into a group of radio buttons on a TGroupBox, then change the property of the container, instead.

{ 1 } Comments

  1. Penny | February 16, 2009 at 2:24 pm | Permalink

    I used to love radio buttons but now they suck!

    Radio buttons are brilliant for displaying a select list in a none uniform method. However, if you want to put a textbox or dropdown inbetween 2 radios the user will not have the ability to tab through or arrow through the radio buttons because these controls block access due to the crap way the tab now works in not selected unchecked radios.

    Also, the fact that radio buttons now check on focus means that dynamically constructed forms that contain on the fly data are destroyed at the users dismay because they are unable to tab through the radio button list freely without altering any settings.

    Radio buttons are now defunct! (unless, of course, there is an option to adopt the old style of tabbing that I am unaware of)

    grrr! whose the idiot, i’ll shoot em!

Post a Comment

Your email is never published nor shared. Required fields are marked *

Bad Behavior has blocked 713 access attempts in the last 7 days.

Close