Built-in Controls

Topics in this chapter:

Label Control

The label control is used to display text in any font. A common use of a label control is to place it to the left of a text box to tell the user about what goes in the text box.

Labels can be aligned left or right, or centered horizontally and/or vertically. If you do not need to align the label, set the p_auto_size property to TRUE to ensure that the text fits inside the window. To center the label to a text box, select the label control and use the Up, Down, Left, and Right arrow keys.

On the Dialog Editor, click the Insert Label Control button to place a label control on a form.

For a complete list of label control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Spin Control

The most common use of a spin control is to increment or decrement a number displayed in a text box. This can be performed WITHOUT writing any code, by making the tab_index property of the text box one less than the tab_index property of the spin control. An error is displayed if there is no text box with a tab index one less than the spin control, unless the increment property of the spin control is set to zero. To create a spin control, complete the following steps:

  1. Create the text box and then create the spin control.

  2. Turn off the auto_size property of the text box so you can make the height of the text box larger than the font.

  3. Use the spin control to increment or decrement the value in a gauge or scroll bar control or increment or decrement a hexadecimal number displayed in a text box. The default increment is 1. Set the increment property of the spin control to zero and process the on_spin_up and on_spin_down events. The on_change event is called with a reason set to CHANGE_NEW_FOCUS, before an on_spin_up or on_spin_down event, to allow you to return the window ID of the control you want to get focus, after spinning is completed. Return an empty string ('') if you do not want to change the event.

Example:

#include "slick.sh"
 
// This example requires form name form1 with a text box and spin control.
// The spin control should be named ctlspin1 and the increment property
// should be zero. The tab index of the text box MUST be one less than
// the spin control. This code does not reference the name of the text box
// so that you can use Clipboard Inheritance(R) to create multiple working
// copies of a spin control capable of incrementing/decrementing the value in
// a text box control without writing any new code.
defeventtab form1;
ctlspin1.on_change(reason)
{
    if (reason==CHANGE_NEW_FOCUS) {
       return(p_prev);
    }
}
ctlspin1.on_spin_up()
{
    new_dec_value=hex2dec(p_prev.p_text)+1;
    p_prev.p_text=dec2hex(new_dec_value);
}
ctlspin1.on_spin_down()
{
    new_dec_value=hex2dec(p_prev.p_text)-1;
    p_prev.p_text=dec2hex(new_dec_value);
}

For a complete list of spin control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Text Box Control

The text box control enables the user to enter a single line of text. Editor control determines the number of lines that can be entered. Text boxes support completion with the spacebar and question mark keys. Set the completion property of the text box.The FILE_ARG completion type is the most common. It provides completion on file names. New commands can be written that operate in all text boxes, edit windows, and editor controls.

Example:

#include "slick.sh"
_command void upcase_line() name_info(','VSARG2_TEXT_BOX|VSARG2_REQUIRES_EDITORCTL)
{
    init_command_op();
    get_line(line);
    replace_line(upcase(line));
    retrieve_command_results();
}

Bind the upcase_line command in the previous example to Alt+F12. This command works in all text boxes, edit windows, and editor controls. The key binding might not work in a text box if you bind the upcase_line to one of the CUA keys Alt+A, Alt+Z, Ctrl+X, Ctrl+C, or Ctrl+V. Use the Redefine Common Keys dialog box (Window → SlickEdit Preferences → Keyboard → Redefine Common Keys) to allow all key bindings to be inherited into text box controls.

For a complete list of text box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Editor Control

Editor control is used to enter multiple lines, view clipboards, to work with the calculator, and for version control comments. Almost all of the key bindings for an MDI edit window work in an editor control even when the emulation is changed. Use macro recording to write a new command that works in an edit window and editor control. Mark the Allow in non-MDI editor control check box when you finish recording the macro.

For a complete list of editor control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Frame Control

Frame control is used to group a set of related controls. Radio buttons are placed inside of a frame control to indicate to the dialog manager that only one of the radio buttons in the group can be turned on at a time. There are two ways to place a control inside of a frame control:

  • Click the left mouse button on the bitmap in the Properties dialog box of the control that you want to place inside the frame. Click and drag with the left mouse button inside the frame control to create the control with the size of the rectangle displayed.

  • Copy or cut the control you want to place inside the frame to the clipboard. Select the frame control and press Ctrl+V to paste the control inside the frame control.

For a complete list of frame control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Command Button Control

The command button control is most typically used to create an OK, Cancel, or Help button.

For a complete list of command button control properties, methods, and events, from the menu, select Help → Macro Functions by Category.

Radio Button Control

Radio buttons must be grouped. When one radio button is enabled, the other radio buttons in the same group are not available. Radio buttons are considered in the same group if they have the same parent. Usually, radio buttons are grouped by placing them inside a picture box or frame control. A picture box can have its border_style property set to BDS_NONE to display that the picture box control does not exist. Use one of the methods described under Frame Control to place a radio button inside a frame.

For a complete list of radio button control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Check Box Control

A check box is used to set up a true or false option. Check boxes can be displayed to the left or right of the caption.

For a complete list of check box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

List Box Control

A list box provides a way to select from a fixed set of items. Multiple items from the list can be selected at one time by setting the multi_select property to MS_SIMPLE_LIST or MS_EXTENDED (used by Open dialog box). A list box receives an on_change event, with a reason argument set to CHANGE_SELECTED, when items are selected or deselected because of a key press or mouse event. None of the _lbxxx functions cause an on_change event. Use the _find_longest_line() function to find the longest line in a list box.

The following example requires a form named "form1", a command button named "ok", and a list box named "ctllist1":

#include "slick.sh"
defeventtab form1;
ctllist1.on_change(reason)
{
    // Check the reason value. In the future we may add more reason values
    // for the list box.
    if (reason==CHANGE_SELECTED) {
       // IF any items in the list box is selected.
       if (p_Nofselected) {
          ctlok.p_enabled=1;						// Enable the OK button.
       } else if(!ctlok.p_enabled){
          ctlok.p_enabled=0;						// Disable the OK button.
       }
    }
}

The following example illustrates how to resize a dialog box based on the longest item in a list box:

#include "slick.sh"
defeventtab form1;
ctllist1.on_create()
{
    _lbadd_item("Line1");
    _lbadd_item("This is a longer line2");
    _lbadd_item("This is the longest item in the list box");
    longest=_find_longest_line();
 
    // Add on a little to account for the left and right borders of the
    // list box. Have to convert client width because it's in pixels.
    list_width=longest+ p_width-_dx2lx(p_xyscale_mode,p_client_width);
    form_wid=p_active_form;
 
    // Again we have to account for the left and right borders.
    // Multiply p_x of list box by two to show equal amounts of spacing on
    // each side of the list box.
    form_width=2*p_x+ list_width+ form_wid.p_width-
    _dx2lx(form_wid.p_xyscale_mode,form_wid.p_client_width);
 
    p_width=list_width;
    form_wid.p_width=form_width;
 
    // Now make sure the whole dialog box can be seen on screen.
    form_wid._show_entire_form();
}

The example below illustrates adding pictures to a list box.

#include "slick.sh"
#define PIC_LSPACE_Y 60    // Extra line spacing for list box.
#define PIC_LINDENT_X 60   // Indent before for list box bitmap.
 
defeventtab form1;
ctllist1.on_create()
{
    // Add some extra line height.
    p_pic_space_y=PIC_LSPACE_Y;
    // _pic_xxx arguments are global variables defined in "slick.sh" which are
    // name table indexes to pictures. You can create and load your own pictures.
    // All the bitmaps are shipped with the editor. Use the bitmap file
    // "_drremov.bmp" as a template for creating your own bitmap for a list box.
    // You can load your own bitmap files with the _update_picture function.
    _lbadd_item("a:",PIC_LINDENT_X,_pic_drremov);
    _lbadd_item("b:",PIC_LINDENT_X,_pic_drremov);
    _lbadd_item("c:",PIC_LINDENT_X,_pic_drfixed);
    // The p_picture property must be set to indicate that this list box is
    // displaying pictures and to provide a scaling picture for the
    // p_pic_point_scale property. The p_pic_point_scale property allows the
    // picture to be resized for fonts larger or smaller than the value of the
    // p_pic_point_scale point size. If p_pic_point_scale is 0, the picture is
    // not scaled.
    p_picture=picture;
    p_pic_point_scale=8;
}

Finally, the example below illustrates how to disable a list box and make the items in the list box appear grayed.

#include "slick.sh"
defeventtab form1;
ctllist1.on_create()
{
    _lbadd_item("item1");
    _lbadd_item("item2");
    p_no_select_color=1;
    p_enabled=0;
    p_forecolor=_rgb(80,80,80);
}

For a complete list of list box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Combo Box Control

A combo box is used in place of a text box for combo box retrieval, when only a fixed set of responses is permitted, or when a common set of responses are known and a different response may be typed in. Combo box retrieval is a mechanism in that the combo list box displays the previous responses entered in the text box of the combo box. The combo box has two style properties:

  • The PSCBO_NOEDIT style is used when only a fixed set of responses are allowed. Combo boxes support completion with the spacebar and question mark keys. Set the completion property of the combo box if there is an existing completion type that suits the needs.

  • The FILE_ARG completion type is the most common. It provides completion on file names.

The following example illustrates combo box retrieval. The example requires a form named "form1", an OK button named "ctlok", and combo box named "ctlcombo1":

defeventtab form1;
ctlok.lbutton_up()
{
    // When the OK button is pressed, you need to save combo box retrieve
    // information.
    _append_retrieve(_control ctlcombo1,ctlcombo1.p_text);
}
ctlok.on_create()
{
    // Fill in the combo box list.
    ctlcombo1._retrieve_list();
}

A combo box consists of four controls: the root window, text box, picture box, and list box. The properties and methods of the sub-controls may be accessed individually with the p_cb, p_cb_text_box, p_cb_picture, p_cb_list_box instance handle properties. The p_cb_picture property is only available when the control is displayed.

Example:

defeventtab form1;
ctlcombo1.on_create()
{
    // To make the loop a little more efficient, activate the list box of the
    // combo box control
    p_window_id=p_cb_list_box;
    for (i=1;i<=100;++i){
       // Add an item to the active list box.
       _lbadd_item("line="i);
    }
    // Activate the root window of the combo box.
    p_window_id=p_cb;
}

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_create()
{
    // Show a picture which indicates that clicking on the picture box
    // button displays a dialog box. _pic_cbdots is a global
    // variable defined in "slick.sh" which is a handle to a picture.
vp_cb_picture.p_picture=_pic_cbdots;
}
ctlcombo1.lbutton_down()
{
    // Check if the left mouse button was clicked inside the picture box
    // of the combo box.
    if (p_cb_active==p_cb_picture) {
       result=show("-modal form2");
       // Process result here.
    return("");
    }
    // Skip user level 1 inheritance and execute the default event handler
    // defined by user level 2 inheritance.
    call_event(p_window_id,lbutton_down,2);
}

The following example requires a form named "form1", command button named "ctlok", a combo box named "ctlcombo1", and another command button named "ctlcommand1":

#include "slick.sh"
defeventtab form1;
ctlok.lbutton_up()
{
    // Check if text in combo box text is valid. You might think you could
    // use a non-editable style combo box. However, many users prefer typing
    // in names using completion rather than using the mouse to select an item
    // out of a list box.
    status=ctlcombo1._cbi_search("","$");
    if (status) {
       _message_box("Combo box contains invalid input");
       return("");
    }
    // Have valid input.
}
ctlcommand1.lbutton_up()
{
    // Add some items to the combo box list.
    ctlcombo1.p_cb_list_box._lbadd_item("Hello")
    ctlcombo1.p_cb_list_box._lbadd_item("Open");
    ctlcombo1.p_cb_list_box._lbadd_item("New");
    // Make the correct item in the combo box list current so combo box
    // retrieval works better. _cbi_search searches for p_text in the combo
    // list box. The "$" specifies that an exact match should be found and
    // not a prefix match.
    int status=ctlcombo1._cbi_search("","$");
    if (!status) {
       messageNwait("Found it!");
       // Select the line in the combo box so that an up or down arrow
       // selects the line above or below and not the current line.
       ctlcombo1.p_cb_list_box._lbselect_line();
    }
}  

A combo box receives an on_change event with a reason argument under the circumstances listed in the table below.

Reason

Description

CHANGE_OTHER

The p_text property changed, probably because of typing.

CHANGE_CLINE

The p_text property changed because selected line in list box changed and the list was visible.

CHANGE_CLINE_NOTVIS

The p_text property changed because a key was pressed which scrolls the list (Up, Down, PgUp, PgDn) while the list was invisible.

CHANGE_CLINE_NOTVIS2

Same as CHANGE_CLINE_NOTVIS. Sent to user level 2 inheritance only. User level 2 inheritance will receive the CHANGE_CLINE_NOTVIS reason as well if the user level 1 inheritance does not catch the on_change event.

The on_drop_down event is sent to a combo box with a reason argument. The reason argument specifies one of the conditions listed in the table below.

Reason

Description

DROP_UP

After combo list box is made invisible.

DROP_DOWN

Before combo list box is made visible.

DROP_INIT

Before retrieve next/previous. Used to initialize list box before it is accessed.

DROP_UP_SELECTED

Mouse released while on valid selection in list box and list is visible.

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_drop_down(reason)
{
    if (reason==DROP_INIT) {
       if (p_user=="") {
          p_user=1;   // Indicate that the list box has been filled.
          // Insert a lot of items.
          p_cb_list_box._insert_name_list(COMMAND_TYPE);
          p_cb_list_box._lbsort();
          p_cb_list_box._lbtop();
       }
    }
}

For a complete list of combo box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Scroll Bar Controls

There are two scroll bar controls that operate similarly: vscroll and hscroll (vertical and horizontal, respectively). The scroll bar controls are used to provide the user an avenue for selecting an integer that has a fixed range or a way for displaying the completion status of a process. Set the min, max, small_change, and large_change properties to define the minimum integer value, maximum integer value, increment/decrement that occurs when arrows are pressed, and increment/decrement that occurs when you click the left button between the arrow and thumb box respectively.

The on_change event is sent after dragging the thumb box is completed. The p_value property contains the new scroll position and will be in the range p_min..p_max.

The on_scroll event is sent while you click and drag the thumb box of a scroll bar.

Example:

#include "slick.sh"
defeventtab form1;
ctlvscroll1.on_scroll()
{
    message("on_scroll p_value="p_value);
}
ctlvscroll1.on_change()
{
    message("on_change p_value="p_value);
}

For a complete list of scroll bar control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Drive List Control

The drive list is a combo box that allows selection of different disk drives. The Open dialog box uses this control.

The drive list control receives an on_change event with a reason argument of CHANGE_DRIVE when the drive is changed by selecting a different drive from the combo list box.

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_change(reason)
{
    if (reason==CHANGE_DRIVE) {
       message("Item selected from list. Current drive is now "_dvldrive());
    }
}

For a complete list of drive list control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

File List Box Control

The file list box control displays a list of files. Multiple files can be selected by setting the multi_select property to MS_SIMPLE_LIST or MS_EXTENDED used by Open dialog box. A file list box receives an on_change event with a reason argument under the circumstances listed in the table below.

Reason

Description

CHANGE_SELECTED

Occurs when items are selected or cleared because of a key press or mouse event. None of the _lb??? functions cause an on_change event.

CHANGE_FILENAME

The _filename() function was called which changed the file names listed.

Example:

#include "slick.sh"
defeventtab form1;
ctlcommand1.lbutton_up()
{
    ctllist1._flfilename("*.bat","c:\\");
}
ctllist1.on_change(reason)
{
    if (reason==CHANGE_FILENAME) {
       message("File list display directory "_flfilename());
    }
}

For a complete list of file list box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Directory List Box Control

The directory list box control displays a list of directories. A file list box receives an on_change event with one of the reason arguments listed in the table below.

Reason

Description

CHANGE_SELECTED

Occurs when items are selected or cleared because of a key press or mouse event. None of the_lb??? functions cause an on_change event.

CHANGE_PATH

The _dlfilename() function was called which changed the file names listed, the left mouse button was double-clicked, or Enter was pressed.

The following example requires a form named "form1", a text box named "ctltext1", and a directory list box named "ctllist1":

#include "slick.sh"
defeventtab form1;
ctllist1.on_change(reason)
{
    if (reason==CHANGE_PATH) {
       // Set the text in the text box to current directory. Changing
       // directories with the directory list box control changes the
       // editor's current directory.
       ctltext1.set_command(_dlpath(),1);
    }
}

For a complete list of directory list box control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Picture Box Control

The picture box is used to place other controls inside of it, like the frame control. The picture box is capable of displaying bitmaps, displaying bitmap buttons, and all the features of the image control. To display bitmaps and bitmap buttons, use the image control feature described in the topic Image Control.

For a complete list of picture box control properties, methods, and events, from the menu item select Help → Macro Functions by Category.

Gauge Control

Gauge control is typically used to indicate the completion status of a process.

Example:

// Create a form with a command button named ctlcancel, and gauge named
// ctlgauge1. Set the cancel and default properties of the command button
// to true.
 
#include "slick.sh"
static boolean gcancel;
_command test()
{
    // Need to tell compiler ctlgauge1 is a control because the 
    // form1_wid.ctlgauge1 is too ambiguous.
    _control ctlgauge1;
 
    // Show the form modeless so there is no modal wait.
    form1_wid=show("form1");
    // Disable all forms except form1_wid.
 
    disabled_wid_list=_enable_non_modal_forms(0,form1_wid);
    gcancel=0;
    for (i=1;i<=100;++i) {
       // Read mouse, key, and all other events until none are left or until
       // the variable gcancel becomes true.
       process_events(gcancel);
       if (gcancel) {
          break;
       }
       // Do work here. Replace the delay below with the operation you want to do.
       // The delay makes this example look more real.
       delay(10);
 
       form1_wid.ctlgauge1.p_value=i;
    }
    // Enable all forms that were disabled.
    _enable_non_modal_forms(1,0,disabled_wid_list);
    form1_wid._delete_window();
}
defeventtab form1;
ctlcancel.lbutton_up()
{
    gcancel=1;
}

For a complete list of gauge control properties, methods, and events, from the main menu, select Help → Macro Functions by Category.

Image Control

Image control is for creating bitmap buttons or toolbar buttons. The image control performs a subset of the features of the picture box control.

Adding a Bitmap Command Button or Check Box

Perform the steps below to add a bitmap button to a dialog box. The same steps can also be used to add a check box.

  1. Create a new form for editing. From the main menu, select Macro → New.

  2. Create an image control. Double-click the Image Control bitmap.

  3. Set the p_picture property to bbfind.bmp. Make sure that you specify the full path (the default path used by the installation program is c:\vslick\bitmaps on Windows or /usr/lib/vslick/bitmaps on UNIX). In this step you enter the bbfind.bmp bitmap as an example.

  4. Set the p_command property to gui_find. The Down arrow of the combo box displays all the editor commands.

  5. Set the p_message property to Searches for a string you specify.

  6. Set the p_style property to PSPIC_FLAT_BUTTON or PSPIC_BUTTON.

Tip

The bb prefix indicates that this is a bitmap that can be used by a toolbar. You can edit the bbfind.bmp file with Paintbrush (pbrush.exe). Use bbblank.bmp as a template for creating your own bitmap buttons.

The following example illustrates how to load your own picture like a toolbar button:

#include "slick.sh"
defeventtab form1;
ctlimage1.on_create()
{
    index=_update_picture(-1,bitmap_path_search("bbfind.bmp"));
    if (index<0) {
       if (index==FILE_NOT_FOUND_RC) {
          _message_box("Picture bbfind.bmp was not found");
       } else {
          _message_box("Error loading picture bbfind.bmp\n\n"get_message(index));
       }
          return("");
    }
    p_picture=index;
    p_command="gui_find";
    p_message="Searches for a string you specify";
    p_style=PSPIC_FLAT_BUTTON;
}

The following example illustrates how to give the appearance of a button being pushed in. While you can do this by setting styles, here you can see how some other functions accomplish this task. For this example, create a form named "form1" and an image control named "ctlimage1".

#include "slick.sh"
defeventtab form1;
ctlimage1.on_create()
{
    index=_update_picture(-1,bitmap_path_search("bbfind.bmp"));
    if (index<0) {
       if (index==FILE_NOT_FOUND_RC) {
          _message_box("Picture bbfind.bmp was not found");
       } else {
          _message_box("Error loading picture bbfind.bmp\n\n"get_message(index));
       }
       return("");
    }
    p_picture=index;
    p_command="gui_find";
    p_message="Searches for a string you specify";
    p_style=PSPIC_BUTTON;
}
ctlimage1.lbutton_down()
{
    // Reset the button counter so we don't get double and triple click events.
    get_event('B');
    mou_mode(1)
    mou_capture();
    done=0;   
    event=MOUSE_MOVE;
    for (;;) {
       switch (event) {
       case MOUSE_MOVE:
          mx=mou_last_x("m"); // "m" specifies mouse position in current scale mode
          my=mou_last_y("m");
 
          if (mx>=0 && my>=0 && mx<p_width && my<p_height) {
             if (!p_value) {
                p_value=1;    // Show the button pushed in.
             }
          } else {
             if (p_value) {
                p_value=0;    // Show the button up.
             }
          }
          break;
       case LBUTTON_UP:
       case ESC:
          p_value=0;  // Restore the button state.
          done=1;
       }
       if (done) break;
       event=get_event();
    }
    mou_mode(0);
    mou_release();
    say('out');
    return("");
}

Adding Dialog Box Retrieval

Dialog box retrieval enables previous responses for check boxes, radio buttons, spin boxes, text boxes, and combo boxes to be retrieved. Press F7 to retrieve the previous response, and F8 to retrieve the next response. For example, the Insert Literal dialog box contains a spin box that is used to enter the character code of the character to insert. If you use it to enter a Hex value of 0xAE (to insert a registered trademark symbol), then later use it to enter a Hex value of 0x99 (to insert an unregistered trademark symbol), the next time you use the dialog you can press F7 to retrieve the previous entry of 0xAE, and then F8 to retrieve the next entry of 0x99.

The responses to dialog boxes are saved for the next session when you exit the editor and auto-restore is enabled.

The example below illustrates how to add dialog box retrieval to your own dialog boxes. Create a form named "form1", a text box (any name), a check box (any name), and a command button named "ok".

#include "slick.sh"
defeventtab form1;
ctlok.on_create()
{
    // Retrieve the previous response to this dialog box.
    _retrieve_prev_form();
}
ctlok.lbutton_up()
{
    _save_form_response();
    p_active_form._delete_window(1);
}