• Solutions
    • FERC XBRL Reporting
    • FDTA Financial Reporting
    • SEC Compliance
    • Windows Clipboard Management
    • Legato Scripting
  • Products
    • GoFiler Suite
    • XBRLworks
    • SEC Exhibit Explorer
    • SEC Extractor
    • Clipboard Scout
    • Legato
  • Education
    • Training
    • SEC and EDGAR Compliance
    • Legato Developers
  • Blog
  • Support
  • Skip to blog entries
  • Skip to archive page
  • Skip to right sidebar

Friday, March 22. 2019

LDC #128: Checkbox and Radio Button Controls Part 2

The radio button is a common tool used to select a single option among multiple choices within a dialog box. In part two of this series, we will be covering the radio button and taking the mystery out of the “group box” and the operation of automatic radio buttons. In addition, the combo box will also be examined as an alternative.


Options, Options and More Options


In part one, I covered the idea of single and multiple user selections for various options. As a developer, we have the option of checkboxes, radio buttons, combo boxes and list boxes. The multiple selection scheme was covered in the first part of this series using two scripts to accomplish the same task with different user experiences and program structure. However, there are many occasions where the user should only select one of multiple options. This could include situations where you may want a user to choose a format for text where only one choice can be applied or select a single characteristic among a group where the options are logically and mutually exclusive. In these cases, checkboxes and list boxes aren’t the best choice, as they are designed to allow multiple selection. A radio button is a better approach.


The Radio Button


Radio buttons differ from checkboxes in that visually they are expected to operate actual “radio” buttons or presets. You press ‘1’ is the preset loads “K-Rock 94.5 FM” on your car radio, for example. Generally, the operator only presses one button at any given time, and only one station can be loaded at a time.


Here is a simple radio button example:


Example Dialog with one set of radio buttons.


Something a little more complicated with two groups:


Example Dialog with two sets of radio buttons.


In most cases, we like to avoid unnecessary coding, so we use auto option for radio buttons (and checkboxes). If we do not use the auto feature, code for each control must be written to respond to click (or spacebar) hits. Now, with example 1, auto operation is simple: When ‘Other’ is pressed the ‘Male’ and ‘Female’ buttons are reset. When clicked, the activated control automatically looks around for companion radio button controls and automatically resets them. This works nicely until there are two or more sets of controls such as shown in example 2.


The resource code for example 1:



RadioButtonExample01Dlg DIALOGEX 0, 0, 240, 70
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Radio Button Example 1"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 12, 19, 60, 8, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 40, 12, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 18, 40, 12, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 18, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 42, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 48, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 48, 50, 14, 0
}


To segregate the ‘Gender’ choices from the ‘Favorite Color’ choices, we have to indicate the start of control groups. Looking at the resource code:



RadioButtonExample02Dlg DIALOGEX 0, 0, 240, 100
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Radio Button Example 2"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 20, 60, 8, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 40, 13, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 18, 40, 13, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 18, 40, 13, 0
 CONTROL "Favorite Color:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 36, 60, 8, 0
 CONTROL "&Black", RB_COLOR_BLACK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 34, 40, 13, 0
 CONTROL "&White", RB_COLOR_WHITE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 34, 40, 12, 0
 CONTROL "&Red", RB_COLOR_RED, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 34, 40, 12, 0
 CONTROL "&Blue", RB_COLOR_BLUE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 46, 40, 12, 0
 CONTROL "&Pink", RB_COLOR_PINK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 46, 40, 12, 0
 CONTROL "&Teal", RB_COLOR_TEAL, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 46, 40, 12, 0
 CONTROL "&Fusia", RB_COLOR_FUSIA, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 58, 40, 12, 0
 CONTROL "&Purple", RB_COLOR_PURPLE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 58, 40, 12, 0
 CONTROL "&Violet", RB_COLOR_VIOLET, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 58, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 74, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 80, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 80, 50, 14, 0
}


To mark the groups, the WS_GROUP style must be added to a control to start a group. This is a critical: the WS_GROUP style bit does not divide, it starts the group.


Without properly defined groups, radio buttons will act erratically. Let’s look at the Microsoft documentation:


“WS_GROUP Specifies the first control of a group of controls in which the user can move from one control to the next with the arrow keys. All controls defined with the WS_GROUP style FALSE after the first control belong to the same group. The next control with the WS_GROUP style starts the next group (that is, one group ends where the next begins).”


What is interesting about this paragraph is that is discusses moving with the arrow keys but it is silent on the implications for button windows with the BS_AUTORADIOBUTTON style set. The WS_GROUP can be set on any control including the first radio button in a series. However, remember each group must be started. Failing to start the first group will result in erratic behavior. I think the first dialog I created with radio buttons was with Windows 3.1 in the early 90s! Many years later, this is still not documented clearly in MSDN.


The Group Box Control — A Separate Beast


Confusion is further compounded by the developer’s interpretation of the BS_GROUPBOX style for the button class. BS_GROUPBOX creates a visual group control using a button common control class while WS_GROUP style bit is a flag set on any control.


Microsoft’s use of term group in this context is ambiguous and unfortunate. Again, Group box controls can be used to visually group controls. However, without the WS_GROUP style set, it just looks like any other control in the dialog to a auto radio button hunting for it partners during a click action.


The visual group box style looks like this:


Example Dialog with one set of radio buttons and a group box.


With later versions of Windows, this visual style has falling out of favor, as the grouping box is very subtle unless you force your dialogs to a light background.


Example Dialog with one set of radio buttons and a group box using light background.


Group Style within the Legato Control Editor


The Legato IDE control editor adds a little clarity to the WS_GROUP option (this example is for a static control; press Ctrl+1 or select Script | Tools | Edit Dialog Control in the IDE to access control editing):


Static text control editor in Legato


For the group box control:


Group box control editor in Legato


Radio Button Examples


The code for the above examples is provided below:



                                                                        // Resource
#beginresource

#define RB_GENDER_MALE                  201
#define RB_GENDER_FEMALE                202
#define RB_GENDER_OTHER                 203
#define RB_COLOR_BLACK                  204
#define RB_COLOR_WHITE                  205
#define RB_COLOR_RED                    206
#define RB_COLOR_BLUE                   207
#define RB_COLOR_PINK                   208
#define RB_COLOR_TEAL                   209
#define RB_COLOR_FUSIA                  210
#define RB_COLOR_PURPLE                 211
#define RB_COLOR_VIOLET                 212

RadioButtonExample01Dlg DIALOGEX 0, 0, 240, 70
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Radio Button Example 1"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender:", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 12, 19, 60, 8, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 40, 12, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 18, 40, 12, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 18, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 42, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 48, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 48, 50, 14, 0
}

RadioButtonExample02Dlg DIALOGEX 0, 0, 240, 100
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Radio Button Example 2"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 20, 60, 8, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 40, 13, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 18, 40, 13, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 18, 40, 13, 0
 CONTROL "Favorite Color:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 36, 60, 8, 0
 CONTROL "&Black", RB_COLOR_BLACK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 34, 40, 13, 0
 CONTROL "&White", RB_COLOR_WHITE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 34, 40, 12, 0
 CONTROL "&Red", RB_COLOR_RED, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 34, 40, 12, 0
 CONTROL "&Blue", RB_COLOR_BLUE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 46, 40, 12, 0
 CONTROL "&Pink", RB_COLOR_PINK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 46, 40, 12, 0
 CONTROL "&Teal", RB_COLOR_TEAL, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 46, 40, 12, 0
 CONTROL "&Fusia", RB_COLOR_FUSIA, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 58, 40, 12, 0
 CONTROL "&Purple", RB_COLOR_PURPLE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 58, 40, 12, 0
 CONTROL "&Violet", RB_COLOR_VIOLET, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 58, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 74, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 80, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 80, 50, 14, 0
}

RadioButtonExample03Dlg DIALOGEX 0, 0, 240, 90
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Radio Button Example 3"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender", -1, "button", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 12, 18, 180, 34, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 24, 30, 40, 12, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 84, 30, 40, 12, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 144, 30, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 62, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 68, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 68, 50, 14, 0
}


#endresource

                                                                        // Main Entry
int main() {
    DialogBox("RadioButtonExample01Dlg", "rb_");
    return ERROR_NONE;
    }



Simply change the example in the DialogBox function from 1 to 2 or 3 to view the above examples in operation.


A Little Selection Program


Our radio button example operates a lot like our checkbox example. Here is the example dialog:


Dialog for example script showing radio buttons.


Here is the code:



                                                                        // Resource
#beginresource

#define RB_GENDER_MALE                  201
#define RB_GENDER_FEMALE                202
#define RB_GENDER_OTHER                 203
#define RB_COLOR_BLACK                  204
#define RB_COLOR_WHITE                  205
#define RB_COLOR_RED                    206
#define RB_COLOR_BLUE                   207
#define RB_COLOR_PINK                   208
#define RB_COLOR_TEAL                   209
#define RB_COLOR_FUSIA                  210
#define RB_COLOR_PURPLE                 211
#define RB_COLOR_VIOLET                 212

RadioButtonExample02Dlg DIALOGEX 0, 0, 240, 100
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Single Select Example 2"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "Gender:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 20, 60, 8, 0
 CONTROL "&Male", RB_GENDER_MALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 40, 13, 0
 CONTROL "&Female", RB_GENDER_FEMALE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 18, 40, 13, 0
 CONTROL "&Other", RB_GENDER_OTHER, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 18, 40, 13, 0
 CONTROL "Favorite Color:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 36, 60, 8, 0
 CONTROL "&Black", RB_COLOR_BLACK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 34, 40, 13, 0
 CONTROL "&White", RB_COLOR_WHITE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 34, 40, 12, 0
 CONTROL "&Red", RB_COLOR_RED, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 34, 40, 12, 0
 CONTROL "&Blue", RB_COLOR_BLUE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 46, 40, 12, 0
 CONTROL "&Pink", RB_COLOR_PINK, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 46, 40, 12, 0
 CONTROL "&Teal", RB_COLOR_TEAL, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 46, 40, 12, 0
 CONTROL "&Fusia", RB_COLOR_FUSIA, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 58, 40, 12, 0
 CONTROL "&Purple", RB_COLOR_PURPLE, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 58, 40, 12, 0
 CONTROL "&Violet", RB_COLOR_VIOLET, "button", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 58, 40, 12, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 74, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 80, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 80, 50, 14, 0
}

#endresource


                                                                        // Dialog Data
    string              rb_gender;
    string              rb_color;

                                                                        // Main Entry
int main() {
    int                 rc;

    rb_gender = GetSetting("Dialog Examples", "Single Select Options", "Gender");
    rb_color  = GetSetting("Dialog Examples", "Single Select Options", "Color");

    rc = DialogBox("RadioButtonExample02Dlg", "rb_");
    if (IsNotError(rc))  {
      PutSetting("Dialog Examples", "Single Select Options", "Gender", rb_gender);
      PutSetting("Dialog Examples", "Single Select Options", "Color", rb_color);
      MessageBox("Gender: %s\r\rColor: %s", rb_gender, rb_color);
      }
    return rc;
    }

                                                                        // In Dialog Proc - Load
int rb_load() {

    if (rb_gender == "Male") {
      CheckboxSetState(RB_GENDER_MALE);
      }
    if (rb_gender == "Female") {
      CheckboxSetState(RB_GENDER_FEMALE);
      }
    if (rb_gender == "Other") {
      CheckboxSetState(RB_GENDER_OTHER);
      }

    if (rb_color == "Black") {
      CheckboxSetState(RB_COLOR_BLACK);
      }
    if (rb_color == "White") {
      CheckboxSetState(RB_COLOR_WHITE);
      }
    if (rb_color == "Red") {
      CheckboxSetState(RB_COLOR_RED);
      }
    if (rb_color == "Blue") {
      CheckboxSetState(RB_COLOR_BLUE);
      }
    if (rb_color == "Pink") {
      CheckboxSetState(RB_COLOR_PINK);
      }
    if (rb_color == "Teal") {
      CheckboxSetState(RB_COLOR_TEAL);
      }
    if (rb_color == "Fusia") {
      CheckboxSetState(RB_COLOR_FUSIA);
      }
    if (rb_color == "Purple") {
      CheckboxSetState(RB_COLOR_PURPLE);
      }
    if (rb_color == "Violet") {
      CheckboxSetState(RB_COLOR_VIOLET);
      }

    return ERROR_NONE;
    }
    
                                                                        // In Dialog Proc - Pressed OK
int rb_validate() {
    string              s1, s2;

    if (CheckboxGetState(RB_GENDER_MALE)) {
      s1 = "Male";
      }
    if (CheckboxGetState(RB_GENDER_FEMALE)) {
      s1 = "Female";
      }
    if (CheckboxGetState(RB_GENDER_OTHER)) {
      s1 = "Other";
      }

    if (CheckboxGetState(RB_COLOR_BLACK)) {
      s2 = "Black";
      }
    if (CheckboxGetState(RB_COLOR_WHITE)) {
      s2 = "White";
      }
    if (CheckboxGetState(RB_COLOR_RED)) {
      s2 = "Red";
      }
    if (CheckboxGetState(RB_COLOR_BLUE)) {
      s2 = "Blue";
      }
    if (CheckboxGetState(RB_COLOR_PINK)) {
      s2 = "Pink";
      }
    if (CheckboxGetState(RB_COLOR_TEAL)) {
      s2 = "Teal";
      }
    if (CheckboxGetState(RB_COLOR_FUSIA)) {
      s2 = "Fusia";
      }
    if (CheckboxGetState(RB_COLOR_PURPLE)) {
      s2 = "Purple";
      }
    if (CheckboxGetState(RB_COLOR_VIOLET)) {
      s2 = "Violet";
      }

    if (s1 == "") {
      MessageBox('X', "Select a 'Gender'.");
      return ERROR_SOFT | RB_GENDER_MALE;
      }

    if (s2 == "") {
      MessageBox('X', "Select a 'Favorite Color'.");
      return ERROR_SOFT | RB_COLOR_BLACK;
      }

    rb_gender = s1;
    rb_color = s2;
    return ERROR_NONE;
    }


The main routine gets the previous settings and runs the dialog. The dialog loader is super simple: it checks for the state condition and sets the radio button accordingly. The validate function is similar, except only one control can be set. If you compare the code from the last blog, you will see that we had to scan the string for tokens since there could be more than one item checked. Here we just compare the state of the radio button and set the resultant string on validate.


There is no need for a routine to set the state since we did not add an option to specify other text for either gender or color. Try to add that, as it would be a good exercise.


You will notice we set the radio buttons using the same API functions used for checkboxes. Aside from the look and the manner in which the auto style operates, radio buttons and check boxes are programmatically the same. If we added an action routine, we must be careful to check the action code to determine why the button is providing notification.


The Same Approach But with Combo Boxes


In this example, the combo box is used to perform the exact same function. Here is the dialog example:


Dialog for example script showing combo boxes.


And here is the code:



                                                                        // Resource
#beginresource

#define CB_GENDER                       201
#define CB_COLOR                        202

RadioButtonExample02Dlg DIALOGEX 0, 0, 240, 100
EXSTYLE WS_EX_DLGMODALFRAME
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Single Select Example 2"
FONT 8, "MS Shell Dlg"
{
 CONTROL "Options", -1, "static", SS_LEFT | WS_CHILD | WS_VISIBLE, 6, 6, 30, 8, 0
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 36, 11, 196, 1
 CONTROL "&Gender:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 20, 60, 8, 0
 CONTROL "", CB_GENDER, "combobox", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 18, 50, 40
 CONTROL "Favorite &Color:", -1, "static", SS_LEFT | WS_GROUP | WS_CHILD | WS_VISIBLE, 12, 36, 60, 8, 0
 CONTROL "", CB_COLOR, "combobox", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 64, 34, 50, 40
 CONTROL "", -1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 6, 74, 226, 1
 CONTROL "OK", IDOK, "button", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 127, 80, 50, 14, 0
 CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 180, 80, 50, 14, 0
}

#endresource


                                                                        // Dialog Data
    string              cb_gender;
    string              cb_color;

                                                                        // Main Entry
int main() {
    int                 rc;

    cb_gender = GetSetting("Dialog Examples", "Single Select Options", "Gender");
    cb_color  = GetSetting("Dialog Examples", "Single Select Options", "Color");

    rc = DialogBox("RadioButtonExample02Dlg", "cb_");
    if (IsNotError(rc))  {
      PutSetting("Dialog Examples", "Single Select Options", "Gender", cb_gender);
      PutSetting("Dialog Examples", "Single Select Options", "Color", cb_color);
      MessageBox("Gender: %s\r\rColor: %s", cb_gender, cb_color);
      }
    return rc;
    }

                                                                        // In Dialog Proc - Load
int cb_load() {
    string              s1;

    s1 = "Male Female Other";
    if (cb_gender == "") { s1 = "(select) " + s1; }
    ComboBoxLoadList(CB_GENDER, s1);
    ComboBoxSelectItem(CB_GENDER, cb_gender);
    if (cb_gender == "") { ComboBoxSelectItem(CB_GENDER, 0); }

    s1 = "Black White Red Blue Pink Teal Fusia Purple Violet";
    if (cb_color == "") { s1 = "(select) " + s1; }
    ComboBoxLoadList(CB_COLOR, s1);
    ComboBoxSelectItem(CB_COLOR, cb_color);
    if (cb_color == "") { ComboBoxSelectItem(CB_COLOR, 0); }

    return ERROR_NONE;
    }
    
                                                                        // In Dialog Proc - Pressed OK
int cb_validate() {
    string              s1, s2;

    s1 = ComboBoxGetSelectString(CB_GENDER);
    if (s1[0] == '(') { s1 = ""; }

    s2 = ComboBoxGetSelectString(CB_COLOR);
    if (s2[0] == '(') { s2 = ""; }

    if (s1 == "") {
      MessageBox('X', "Select a 'Gender'.");
      return ERROR_SOFT | CB_GENDER;
      }

    if (s2 == "") {
      MessageBox('X', "Select a 'Favorite Color'.");
      return ERROR_SOFT | CB_COLOR;
      }

    cb_gender = s1;
    cb_color = s2;
    return ERROR_NONE;
    }


Similar to the checkbox versus list box example in my last blog, the combo box example has significantly less code. The main routine is the same. The load function, however, is considerably different. Each control requires selection items to be loaded and the incoming string needs to be selected. We could load the list and select a string. If the source data is incorrect or empty, the combo box would remain blank. However, we put a little polish on the interface by detecting that there is no incoming selection and adding “(select)” to the list.


During validation, we eliminate the “(select)” option by testing for an open parenthesis and clearing the string. This has the consequence of forcing an error during validation.


If you have already ran the radio button example, then the “(select)” will never appear because gender and color are already set. To test the selection, comment out the lines containing the GetSetting functions in the main() routine.


Conclusion


The combo box is a good alternative to the radio button while reducing code and increasing extensibility. On the other hand, radio buttons give a clear indication as to available options and, for most people, a visual indication that only one may be selected.


While writing this blog, I ran across a useful treatise on visual design selections for various controls. The one for radio buttons is located at https://docs.microsoft.com/en-us/windows/desktop/uxguide/ctrl-radio-buttons. It is worth at least speed read.


In my next blog on checkboxes and radio buttons, I will explore the BS_NOTIFY style and how to manually perform processing for these types of controls.


 


Scott Theis is the President of Novaworks and the principal developer of the Legato scripting language. He has extensive expertise with EDGAR, HTML, XBRL, and other programming languages.

Additional Resources

Novaworks’ Legato Resources

Legato Script Developers LinkedIn Group

Primer: An Introduction to Legato

MSDN UI Development Guidelines 



Posted by
Scott Theis
in Development at 13:43
Trackbacks
Trackback specific URI for this entry

No Trackbacks

Comments
Display comments as (Linear | Threaded)
No comments
The author does not allow comments to this entry

Quicksearch

Categories

  • XML Accounting
  • XML AICPA News
  • XML FASB News
  • XML GASB News
  • XML IASB News
  • XML Development
  • XML Events
  • XML FERC
  • XML eForms News
  • XML FERC Filing Help
  • XML Filing Technology
  • XML Information Technology
  • XML Investor Education
  • XML MSRB
  • XML EMMA News
  • XML FDTA
  • XML MSRB Filing Help
  • XML Novaworks News
  • XML GoFiler Online Updates
  • XML GoFiler Updates
  • XML XBRLworks Updates
  • XML SEC
  • XML Corporation Finance
  • XML DERA
  • XML EDGAR News
  • XML Investment Management
  • XML SEC Filing Help
  • XML XBRL
  • XML Data Quality Committee
  • XML GRIP Taxonomy
  • XML IFRS Taxonomy
  • XML US GAAP Taxonomy

Calendar

Back May '25 Forward
Mo Tu We Th Fr Sa Su
Friday, May 23. 2025
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Feeds

  • XML
Sign Up Now
Get SEC news articles and blog posts delivered monthly to your inbox!
Based on the s9y Bulletproof template framework

Compliance

  • FERC
  • EDGAR
  • EMMA

Software

  • GoFiler Suite
  • SEC Exhibit Explorer
  • SEC Extractor
  • XBRLworks
  • Legato Scripting

Company

  • About Novaworks
  • News
  • Site Map
  • Support

Follow Us:

  • LinkedIn
  • YouTube
  • RSS
  • Newsletter
  • © 2024 Novaworks, LLC
  • Privacy
  • Terms of Use
  • Trademarks and Patents
  • Contact Us