CommandObject Commands


This section describes how each of the command objects available in V is used to build dialogs.

Synopsis

Header:
<v/v_defs.h>
Type name:
CmdType

Description

V provides several different kinds of command items that are used in dialogs. The kind of command is specified in the cmdType field of the CommandObject structure when defining a dialog. This section describes current dialog commands available with V. They will be constructed by V to conform to the conventions of the host windowing system. Each command is named by the value used to define it in the CommandObject structure.

List of commands

C_Blank, C_BoxedLabel, C_Button, C_CheckBox, C_ColorButton, C_ComboBox, C_EndOfList, C_Frame, C_Icon, C_IconButton, C_Label, C_ColorLabel, C_List, C_ProgressBar, C_RadioButton, C_Slider, C_Spinner, C_Text, C_TextIn, C_ToggleButton, C_ToggleFrame, C_ToggleIconButton

Commands

C_Blank

A Blank can help you control the layout of your dialogs. The Blank object will occupy the space it would take if it were a C_Label, but nothing will be displayed. This is especially useful for leaving space between other command objects, and getting nice layouts with RightOfs and Belows. You control the size of the Blank by providing a string with an appropriate number of blanks for the title field.

C_BoxedLabel


This command object is just like a C_Label, but drawn with a surrounding box. See C_Label.

C_Button


A Button is one of the primary command input items used in dialog boxes. When the user clicks on a Button, the values set in the cmdId and retVal fields are passed to the DialogCommand method. In practice, the retVal field is not really used for buttons - the cmdId field is used in the switch statement of the DialogCommand method.

A button is defined in a CommandObject array. This is a typical definition:

 {C_Button, btnId, 0,"Save",NoList,CA_None,isSens,NoFrame,0,0}
The retVal field can be used to hold any value you wish. For example, the predefined color button frame (see vColor) uses the cmdId field to identify each color button, and uses the retVal field to hold the index into the standard V color array. If you don't need to use the retVal, a safe convention is to a 0 for the retVal. You can put any label you wish in the title field.

If you provide the attribute CA_DefaultButton to the CmdAttribute field, then this button will be considered the default button for the dialog. The default button will be visually different than other buttons (usually a different border), and pressing the Return key is the same as clicking on the button.

The size of the button in pixels can be controlled by using the CommandObject element size. By specifying the attribute CA_Size and providing a value for the size element, you can control the size of the button. Note the that the size element is the last one of a CommandObject, and can left out of a declaration, which results in the compiler generating a zero value.

You can change the label of a button with: SetString(btnId, "New Label"). You can change the sensitivity of a button with SetValue(btnID, OnOrOff, Sensitive).

C_CheckBox


A CheckBox is usually used to set some option on or off. A CheckBox command item consists of a check box and an associated label. When the user clicks on the check box, the DialogCommand method is invoked with the Id set to the cmdId and the Val set to the current state of the CheckBox. The system takes care of checking and unchecking the displayed check box - the user code tracks the logical state of the check box.

A CheckBox is defined in a CommandObject array. This is a typical definition:

 {C_CheckBox, chkId, 1,"Show Details",NoList,CA_None,isSens,NoFrame,0,0}
The retVal is used to indicate the initial state of the check box. You should use the GetValue method to get the current state of a check box. You can also track the state dynamically in the DialogCommand method. You can put any label you wish in the title field.

You can change the label of a check box with: SetString(chkId, "New Label"). You can change the sensitivity of a check box with SetValue(chkID, OnOrOff,Sensitive). You can change the checked state with SetValue(chkID, OnOrOff, Checked).

If the user clicks the Cancel button and your code calls the default DialogCommand method, V will automatically reset any check boxes back to their original state, and call the DialogCommand method an additional time with the original value if the state has changed. Thus, your code can track the state of check boxes as the user checks them, yet rely on the behavior of the Cancel button to reset changed check boxes to the original state.

The source code for the V vDebugDialog class provides a good example of using check boxes (at least for the X version). It is found in v/src/vdebug.cxx.

C_ColorButton


A color command button. This works exactly the same as a C_Button except that the button may be colored. You use C_ColorButton for the cmdType field, and provide a pointer to a vColor structure in the itemList field using a (void*) cast. The label is optional.

The retVal field of a color button is not used. You can generate a square color button of a specified size by specifying an empty label ("") and a size value greater than 0. When you specify the size field, the color button will be a colored square size pixels per side. When used within a CA_NoSpace frame, this feature would allow you to build a palette of small, tightly spaced color buttons. In fact, V provides a couple of such palettes in v/vcb2x4.h and v/vcb2x8.h. These include files, as well as the other details of the vColor class are described in the section vColor in the Drawing chapter.

There are two ways to change to color of a button. The most direct way is to change each of the RGB values in three successive calls to SetValue using Red, Green, and finally Blue as the ItemSetType to change the RGB values. The call with Blue causes the color to be updated. I know this isn't the most elegant way to do this, but it fits with the SetValue model.

An alternate way is to change the value of the original vColor used to define the initial color of the control, and then call SetValue with the ChangeColor set type.

This is a short example of defining a red button, and then changing it.

    static vColor btncolor(255,0,0};  // define red
    ...

    // part of a CommandObject definition
    {C_ColorButton, cbt1, 0, "", (void*)&btncolor,
        CA_None, isSens, NoFrame, 0, btnXXX},

    ...
    // Code to change the color by some arbitrary values
    btncolor.Set(btncolor.r()+127, btncolor.g()+63, btncolor.b()+31);
#ifdef ByColor    // by vColor after changing btncolor
    SetValue(cbt1,0,btncolor);
#else          // by individual colors
    SetValue(cbt1,(ItemVal)btncolor.r(),Red);
    SetValue(cbt1,(ItemVal)btncolor.g(),Green);
    // This final call with Blue causes color to update in dialog
    SetValue(cbt1,(ItemVal)btncolor.b(),Blue);
#endif
    ...

C_ComboBox


A combo box is a drop-down list. It normally appears as box with text accompanied by some kind of down arrow button. You pass a list of alternative text values in the itemList field of the CommandObject structure. You also must set the retVal field to the index (starting at 0) of the item in the list that is the default value for the combo box text title.

If the user clicks the arrow, a list pops up with a set of alternative text values for the combo box label. If the user picks one of the alternatives, the popup closes and the new value fills the text part of the combo box. V supports up to 32 items in the combo box list. You need to use a C_List if you need more than 32 items.

With default attributes, a combo box will send a message to DialogCommand whenever a user picks a selection from the combo box dialog. This can be useful for monitoring the item selected. If you define the combo box with the attribute CA_NoNotify, the dialog in not notified on each pick. You can use GetValue to retrieve the index of the item shown in the combo box text field.

You can preselect the value by using SetValue. You can change the contents of the combo list by using vDialog::SetValue with either ChangeList or ChangeListPtr. See vDialog::SetValue for more details.

Example

The following is a simple example of using a combo box in a modal dialog. This example does not process items as they are clicked, and does not show code that would likely be in an overridden DialogCommand method. The code interface to a list and a combo box is very similar - the interaction with the user is different. This example will initially fill the combo box label with the text of comboList[2].

enum { cbxId = 300 };
char* comboList[] =
  {
    "First 0",   // The first item in the list
     ...
    "Item N",    // The last item in the list
    0            // 0 terminates the list
  };
  ...
CommandObject ComboList[] =
  {
    {C_ComboBox, cbxId, 2, "A Combo Box", (void*)comboList,
       CA_NoNotify,isSens,NoFrame,0,0},
    {C_Button, M_OK, M_OK, " OK ", NoList,
       CA_DefaultButton, isSens, NoFrame, 0, ListId},
    {C_EndOfList,0,0,0,0,CA_None,0,0,0}
  };
    ...
    vModalDialog cd(this);    // create list dialog
    int cid, cval;
    ...
    cd.AddDialogCmds(comboList);   // Add commands to dialog
    cid = ld.ShowModalDialog("",cval);  // Wait for OK
    cval = ld.GetValue(cbxId);  // Retrieve the item selected

C_EndOfList

This is not really a command, but is used to denote end of the command list when defining a CommandObject structure.

C_Frame


The frame is a line around a related group of dialog command items. The dialog window itself can be considered to be the outermost frame. Just as the placement of commands within the dialog can be controlled with the cRightOf and cBelow fields, the placement of controls within the frame use the same fields. You then specify the id of the frame with the cFrame field, and then relative position within that frame.

The title field of a frame is not used.

You may supply the CA_NoBorder attribute to any frame, which will cause the frame to be drawn without a border. This can be used as a layout tool, and is especially useful to force buttons to line up in vertical columns.

See the section CommandObject for an example of defining a frame.

C_Icon


A display only icon. This works exactly the same as a C_Label except that an icon is displayed instead of text. You use C_Icon for the cmdType field, and provide a pointer to the vIcon object in the itemList field using a (void*) cast. You should also provide a meaningful label for the title field since some versions of V may not support icons.

You can't dynamically change the icon.

C_IconButton


A command button Icon. This works exactly the same as a C_Button except that an icon is displayed for the button instead of text. You use C_IconButton for the cmdType field, and provide a pointer to the vIcon object in the itemList field using a (void*) cast. You should also provide a meaningful label for the title field since some versions of V may not support icons.

You can't dynamically change the icon. The button will be sized to fit the icon. Note that the v/icons directory contains quite a few icons suitable for using on command bars.

C_Label

C_ColorLabel

This places a label in a dialog. A label is defined in a CommandObject array. This is a typical definition:

 {C_Label, lblId,0,"Select Options",NoList,CA_None,isSens,NoFrame,0,0, 0,0}
While the value of a label can be changed with SetString(lblId, "New Label"), they are usually static items. If the label is defined with the CA_MainMsg attribute, then that label position will be used to fill the the message provided to the ShowDialog method.

A C_ColorLabel is a label that uses the List parameter of the CommandObject array to specify a vColor. You can specify the color and change the color in the same fashion as described in the C_ColorButton command.

C_List


A list is a scrollable window of text items. The list can be made up of any number of items, but only a limited number are displayed in the list scroll box. The default will show eight items at a time. The number of rows can be controlled as explained later.

The user uses the scroll bar to show various parts of the list. Normally, when the user clicks on a list item, the DialogCommand is invoked with the id of the List command in the Id parameter, and the index into the list of the item selected in the Val parameter. This value may be less than zero, which means the user has unselected an item, and your code should properly handle this situation. This only means the user has selected the given item, but not that the selection is final. There usually must be a command Button such as OK to indicate final selection of the list item.

If the List is defined with the attribute CA_NoNotify, DialogCommand is not called with each pick. You must then use GetValue to get which item in the list was selected.

It is possible to preselect a given list item with the SetValue method. Use the GetValue to retrieve the selected item's index after the OK button is selected. A value less than zero means no item was selected.

The number of rows displayed can be controlled by using the CommandObject element size. By specifying the attribute CA_Size and providing a value for the size element, you can specify how many rows to show. If you don't specify a size, 8 rows will be displayed. Vwill support between 1 and 32 rows. Note the that the size element is the last one of a CommandObject, and can left out of a declaration, which results in the compiler generating a zero value, giving the default 8 rows.

The width in pixels (approximately) of the list can be controlled by specifying the CA_ListWidth attribute and providing a value to the retVal parameter, which is otherwise unused for a list object. This implementation isn't perfect - you may have to play with the interaction between the width you specify, and the font used in a list control.

Change the contents of the list with vDialog::SetValue using either ChangeList or ChangeListPtr. See vDialog::SetValue for more details.

The vSList class provides a very useful set of utilities for working with C_List lists.

Example

The following is a simple example of using a list box in a modal dialog. This example does not process items as they are clicked. This list will be displayed in 12 rows.

enum {lstId = 200 };
char* testList[] =
  {
    "First 0",   // The first item in the list
     ...
    "Item N",    // The last item in the list
    0            // 0 terminates the list
  };
  ...
CommandObject ListList[] =
  {
    {C_List, lstId, 0, "A List", (void*)testList,
       CA_NoNotify | CA_Size,isSens,NoFrame,0,0,12},
    {C_Button, M_OK, M_OK, " OK ", NoList,
       CA_DefaultButton, isSens, NoFrame, 0, lstId},
    {C_EndOfList,0,0,0,0,CA_None,0,0,0}
  };
    ...
    vModalDialog ld(this);    // create list dialog
    int lid, lval;
    ...
    ld.AddDialogCmds(ListList);   // Add commands to dialog
    ld.SetValue(lstId,8,Value);  // pre-select 8th item
    lid = ld.ShowModalDialog("",lval);  // Wait for OK
    lval = ld.GetValue(lstId);  // Retrieve the item selected

C_ProgressBar


Bar to show progress. Used with CA_Vertical or CA_Horizontal attributes to control orientation. You change the value of the progress bar with SetValue(ProgID, val, Value), where val is a value between 0 and 100, inclusive. Normally, the progress bar will show both a graphical indication of the value, and a text indication of the value between 0 and 100.

If you don't want the text value (for example, your value represents something other than 0 to 100), then define the progress bar with the CA_NoLabel attribute. Use the CA_Percent attribute to have a % added to the displayed value. You can also use CA_Small or CA_Large to make the progress bar smaller or larger than normal. If you need a text value display for ranges other than 0 to 100, you can build a CA_NoSpace frame with a progress bar and a text label that you modify yourself.

Example

The following shows how to define a progress bar, and how to set its value.

enum{frm1 = 200, lbl1, pbrH, pbrV, ... };
  static CommandObject Cmds[] =
  {
    ...
    // Progress Bar in a frame
    {C_Frame, frm1, 0, "",NoList,CA_None,isSens,NoFrame, 0,0},
    {C_Label, lbl1, 0, "Progress",NoList,CA_None,isSens,frm1,0,0},
    {C_ProgressBar, pbrH, 50, "", NoList,
        CA_Horizontal,isSens,frm1, 0, lbl1},  // Horiz, with label

    {C_ProgressBar, pbrV, 50, "", NoList,  // Vertical, no value
      CA_Vertical | CA_Small, isSens,NoFrame, 0, frm1},
    ...
  };
  ...
  // Set the values of both bars to same
  SetValue(pbrH,retval,Value);    // The horizontal bar
  SetValue(pbrV,retval,Value);    // The vertical bar

C_RadioButton


Radio buttons are used to select one and only one item from a group. When the user clicks on one button of the group, the currently set button is turned off, and the new button is turned on. Note that for each radio button press, two events are generated. One a call to DialogCommand with the id of the button being turned off, and the other a call with the id of the button being turned on. The order of these two events is not guaranteed. The retVal field indicates the initial on or off state, and only one radio button in a group should be on.

Radio buttons are grouped by frame. You will typically put a group of radio buttons together in a frame. Any buttons not in a frame (in other words, those just in the dialog window) are grouped together.

Radio buttons are handled very much like check boxes. Your code should dynamically monitor the state of each radio button with the DialogCommand method. Selecting Cancel will automatically generate calls to DialogCommand to restore the each of the buttons to the original state.

You can use SetValue with a Value parameter to change the settings of the buttons at runtime. SetValue will enforce a single button on at a time.

Example

The following example of defining and using radio buttons was extracted from the sample file v/examp/mydialog.cpp. It starts with the button RB1 pushed.

enum {
    frmV1 = 200, rdb1, rdb2, rdb3, ...
...
  };
...
static CommandObject DefaultCmds[] =
  {
    {C_Frame, frmV1, 0,"Radios",NoList,CA_Vertical,isSens,NoFrame,0,0},
    {C_RadioButton, rdb1, 1, "KOB",  NoList,CA_None,isSens, fmV1,0,0},
    {C_RadioButton, rdb2, 0, "KOAT", NoList,CA_None, isSens,frmV1,0,0},
    {C_RadioButton, rdb3, 0, "KRQE", NoList,CA_None, isSens,frmV1,0,0},
    {C_Button, M_Cancel,M_Cancel,"Cancel",NoList,CA_None,
        isSens, NoFrame, 0, frmV1},
    {C_Button, M_OK, M_OK, " OK ", NoList, CA_DefaultButton, 
        isSens, NoFrame, M_Cancel, frmV1},
    {C_EndOfList,0,0,0,0,CA_None,0,0,0}
  };
...
void myDialog::DialogCommand(ItemVal Id, ItemVal Val, CmdType Ctype)
  {
    switch (Id)              // switch on command id
      {
        case rdb1:            // Radio Button KOB
            // do something useful - current state is in retval
            break;
        ...
        // cases for other radio buttons

      }
    // let the super class handle M_Cancel and M_OK
    vDialog::DialogCommand(id,retval,ctype);
  }

C_Slider


Used to enter a value with a slider handle. The slider will provide your program with a value between 0 and 100, inclusive. Your program can then scale that value to whatever it needs.

V will draw sliders in one of three sizes. Use CA_Small for a small slider (which may not be big enough to return all values between 0 and 100 on all platforms), CA_Large to get a larger than normal slider, and no attribute to get a standard size slider that will return all values between 0 and 100. Use the CA_Vertical and CA_Horizontal attributes to specify orientation of the slider.

When the user changes the value of the slider, the DialogCommand method is called with the id of the slider for the Id value, and the current value of the slider for the Retval value. You can use SetVal to set a value for the slider.

Example

The following example shows the definition line of a slider, and a code fragment from an overridden DialogCommand method to get the value of the dialog and update a C_Text item with the current value of the slider. The slider starts with a value of 50.

enum { frm1 = 80, sld1, txt1 };
CommandObject Commands[] =
  {
    ...
    {C_Frame, frm1, 0, "",NoList,CA_None,isSens,NoFrame,0,0},
    {C_Slider, sld1, 50, "",NoList,CA_Horizontal,isSens,frm1,0,0},
    {C_Text, txt1, 0, "", "50",CA_None,isSens, frm1, sld1, 0},
    ...
  };
  ...
void testDialog::DialogCommand(ItemVal id,
  ItemVal retval, CmdType ctype)
  { 
    ...
    switch (id)     // Which dialog command item?
      {
        ...
        case sld1:    // The slider
          {
            char buff[20];
            sprintf(buff,"%d",retval);  // To string
            SetString(txt1,buff);      // Show value
          }
        ...
      }
    ...
  }

C_Spinner


This command item is used to provide an easy way for the user to enter a value from a list of possible values, or in a range of values. Depending on the attributes supplied to the CommandObject definition, the user will be able to select from a short list of text values, from a range of integers, or starting with some initial integer value. As the user presses either the up or down arrow, the value changes to the next permissible value. The retVal field specifies the initial value of the integer, or the index of the initial item of the text list. You use the GetValue method to retrieve the final value from the C_Spinner.

You can change the contents of the spinner list by using vDialog::SetValue with either ChangeList or ChangeListPtr. See vDialog::SetValue for more details.

The size of the spin value field in pixels can be controlled by using the CommandObject element size. By specifying the attribute CA_Size and providing a value for the size element, you can control the size of the value field . Note the that the size element is the last one of a CommandObject, and can left out of a declaration, which results in the compiler generating a zero value.

Example

This example shows how to setup the C_Spinner to select a value from a text list (when supplied with a list and the CA_Text attribute), from a range of integers (when supplied a range list), or from a starting value (when no list is provided). The definitions of the rest of the dialog are not included.

  static char* spinList[] =    // a list of colors
    {
      "Red","Green","Blue", 0
    };
  static int minMaxStep[3] =  // specify range of
    {                         // -10 to 10
      -10, 10, 2              // in steps of 2
    };
  enum { spnColor = 300, spnMinMax, spnInt, ... };
  CommandObject SpinDialog[] =
    {
      ...
      {C_Spinner,spnColor,0,"Vbox", // A text list.
        (void*)spinList,CA_Text,     // the list is CA_Text
        isSens,NoFrame, 0,0},
      {C_Spinner,spnMinMax,0,"Vbox", // a range -10 to 10
        (void*)minMaxStep,CA_None,  // by 2's starting at 0
        isSens,NoFrame, 0,0},
      {C_Spinner,spnInt,32,"Vbox",  // int values step by 1
        NoList,CA_None,             // starting at 32
        isSens,NoFrame, 0,0},
      ...
    };

C_Text


This draws boxed text. It is intended for displaying information that might be changed, unlike a label, which is usually constant. The text may be multi-line by using a '\n`. The retVal and title fields are not used. The text to display is passed in the itemList field.

You can use the CA_NoBorder attribute to suppress the border.

A definition of a C_Text item in a CommandObject definition would look like:

 {C_Text, txtId, 0, "", "This is an example\nof a two line text.",
          CA_None,isSens,NoFrame, 0, 0, 0,0}, 
You can change the label of text box with: SetString(txtId, "New text to show.").

C_TextIn


This command is used for text entry from the user. The text input command item will typically be boxed field that the user can use to enter text.

The strategy for using a TextIn command item is similar to the List command item. You need an OK button, and then retrieve the text after the dialog has been closed.

You can provide a default string in the title field which will be displayed in the TextIn field. The user will be able to edit the default string. Use an empty string to get a blank text entry field. The retVal field is not used.

There are two ways to control the size of the TextIn control. If you specify CA_None, you will get a TextIn useful form most simple input commands. Using CA_Large gets a wider TextIn, while CA_Small gets a smaller TextIn. You can also use the size field of the CommandObject to explicitly specify a width in characters. When you specify a size, that number of characters will fit in the TextIn, but the control does not enforce that size as a limit.

If you specify the attribute CA_Password, then the user's input will either be echoed as asterisks (MS-Windows), or not echoed (X).

Example

The following example demonstrates how to use a TextIn.

CommandObject textInList[] =
  {
    ...
    {C_TextIn, txiId,0,"",NoList,CA_None,isSens,NoFrame,0,0},
    ...
    {C_EndOfList,0,0,0,0,CA_None,0,0,0}
  };
 ...
    vModalDialog md(this);      /// make a dialog
    int ans, val;
    char text_buff[255];        // get text back to this buffer
 ...
    md.AddDialogCmds(textInList);  // add commands
    ans = md.ShowModalDialog("Enter text.", val);  // Show it
    text_buff[0] = 0;          // make an empty string
    (void) md.GetTextIn(txiId, text_buff, 254); // get the string
 ...

C_ToggleButton


A C_ToggleButton is a combination of a button and a checkbox. When the toggle button is pressed, the vCmdWindow::WindowCommand method is called, just as with a regular command button. However, the system will change the look of the toggle button to indicate it has been pressed. Each click on a C_ToggleButton will cause the button to appear pressed in or pressed out.

The retVal field of the CommandObject definition is used to indicate the initial state of the toggle.

The behavior of a toggle button is like a check box, and not a radio button. This is more flexible, but if you need exclusive radio button like selection, you will have to enforce it yourself using SetValue(toggleId,val,Value).

 // Define a toggle button with id tbtToggle and
 // an initial state of 1, which means pressed in
 {C_ToggleButton,tbtToggle, 1,"", NoList,CA_None,
     isSens, NoFrame, 0, 0},
 ...

 // The case in WindowCommand should be like this:

    case tbtToggle:
      {
	// Always safest to retrieve current value
        ItemVal curval = GetValue(tbtToggle);
        // Now, do whatever you need to
        if (curval)
           ... it is pressed
        else
           ... it is not pressed
        break;
      }

C_ToggleFrame


A C_ToggleFrame is V's answer to the Windows Tab control. While Vdoesn't have real Tab controls, using a combination of C_ToggleFrames and either radio buttons or toggle buttons, you can design very nice multi-frame dialogs.

A Toggle Frame works just like a regular C_Frame except that you can use SetValue with a type Value to hide or make visible all controls contained or nested in the toggle frame. (Note: setting the Value of a toggle frame is not the same as setting its Hidden attribute.)

The strategy for using toggle frames follows. First, you will usually use two or more toggle frames together. In the dialog CommandObject definition, you first define one radio button or one toggle button for each toggle frame used in the dialog. You then define a regular bordered C_Frame positioned below the radio/toggle buttons. Then place CA_NoBorder toggle frames inside that outer frame. The outer frame will be the border for all the toggle frames. Inside each toggle frame, you define controls in the normal way.

You must select just one of the toggle frames to be initially visible. This will correspond to the checked radio button or pressed toggle button. The remaining toggle frames and their controls should all be defined using the CA_Hidden attribute.

You then hide and unhide toggle frames by responding to the vDialog::DialogCommand messages generated when a radio button or toggle button is pressed. You SetValue(togID, 1, Value) to show a toggle pane and all its controls, and SetValue(togID, 0, Value) to hide all its controls.

The following example shows how to define and control toggle frames:

    enum {lbl1 = 400, tbt1, tbt2, tbt3, frm1, tfr1, tfr2,
          btnA1, btnB1, btnA2, btnB2 };
    static CommandObject DefaultCmds[] =
      {
        // A label, then 2 toggle buttons to select toggle frames
        {C_Label,lbl1,0,"Tab Frame Demo",NoList,CA_None,isSens,
                 NoFrame,0,0},
        {C_ToggleButton,tbt1,1,"Tab 1",NoList, CA_None, isSens, 
                 lbl1, 0, 0},
        {C_ToggleButton,tbt2,0,"Tab 2",NoList, CA_None, isSens, 
                 lbl1, tbt, 0},
        {C_ToggleButton,tbt3,0,"Tab 3",NoList, CA_None, isSens,
                 lbl1, tbt2 0},

        // A Master frame to give uniform border to toggle frames
        {C_Frame,frm1,0, "", NoList,CA_None,isSens,lbl1,0,tbt1},

        // Toggle Frame 1 - default frame on
        {C_ToggleFrame, tfr1,1,"",NoList, CA_NoBorder,isSens,frm1,0,0},
        {C_Button,btnA1,0,"Button A(1)",NoList,CA_None,isSens,tfr1,0,0},
        {C_Button,btnB1,0,"Button B(1)",NoList,CA_None,isSens,tfr1,
                  0,btnA1},

        // Toggle Frame 2 - default off (CA_Hidden!)
        {C_ToggleFrame,tfr2,0,"",NoList,CA_NoBorder | CA_Hidden,
                isSens,frm1,0,0},
        {C_Button,btnA2,0,"Button A(2)",NoList,CA_Hidden,isSens,tfr2,0,0},
        {C_Button,btnB2,0,"Button B(2)",NoList,CA_Hidden,isSens,tfr2,
                  btnA2,0},

        {C_EndOfList,0,0,0,0,CA_None,0,0,0}
      };


    ...

    // In the DialogCommand method:

    switch (id)         // We will do some things depending on value
      {
        case tbt1:       // For toggle buttons, assume toggle to ON
          {
            SetValue(id,1,Value);     // turn on toggle button
            SetValue(tbt2,0,Value);    // other one off
            SetValue(tfr2,0,Value);    // Toggle other frame off
            SetValue(tfr1,1,Value);    // and ours on
            break;
          }

        case tbt2:       // Toggle 2
          {
            SetValue(id,1,Value);     // turn on toggle button
            SetValue(tbt1,0,Value);    // other off
            SetValue(tfr1,0,Value);    // Toggle other off
	    SetValue(tfr2,1,Value);    // and ours on
            break;
          }

      }
    // All commands should also route through the parent handler
    vDialog::DialogCommand(id,retval,ctype);
  }

C_ToggleIconButton


A C_ToggleIconButton is a combination of an icon button and a checkbox. When the toggle icon button is pressed, the vCmdWindow::WindowCommand method is called, just as with a regular icon button. However, the system will change the look of the toggle icon button to indicate it has been pressed. This is useful for good looking icon based interfaces to indicate to a user that some option has been selected. An additional press will change the appearance back to a normal icon button. The retVal field of the CommandObject definition is used to indicate the initial state of the toggle.

The behavior of a toggle icon button is like a check box, and not a radio button. This is more flexible, but if you need exclusive radio button like selection, you will have to enforce it yourself using SetValue(toggleId,val,Value).

 // Define a toggle icon button with id tibToggle and
 // an initial state of 1, which means pressed
 {C_ToggleIconButton,tibToggle, 1,"", &anIcon,CA_None,
     isSens, NoFrame, 0, 0},
 ...

 // The case in WindowCommand should be like this:

    case tibToggle:
      {
        // Always safest to retrieve current value
        ItemVal curval = GetValue(tibToggle);
        // Now, do whatever you need to
        if (curval)
           ... it is pressed
        else
           ... it is not pressed
        break;
      }


Footnotes:

1 This is necessary keep things as chars and still allow a possible 256 entries, since 256 is 28+1, and a color map with 0 entries doesn't make sense.