User Tools

Site Tools


creating_20a_20rebar_20control

Creating a rebar control

by Richard Russell, August 2006

A rebar control acts a bit like a toolbar, but instead of being a simple bar it consists of a number of bands each of which can contain a child window. Typically the child window can itself be a toolbar or a combo box or indeed any other Windows control. A simple rebar control looks like this (in the Windows XP Visual Style):



This control has two bands, the first containing a combo box and the second a toolbar. Each band contains a gripper (the dotted vertical line in this case), a background bitmap (not used here) an optional text string and a child control. The user can dynamically resize and reposition each of the bands by dragging the gripper; if necessary the rebar control can extend over two or more strips.

Rebar controls are very flexible, and are often used in Microsoft products instead of simple toolbars.

The remainder of this article will describe the steps needed to create a rebar control in BBC BASIC for Windows; the code listed will create the control shown above. Firstly we must install the WINLIB5A library file which is needed by the program:

        INSTALL @lib$+"WINLIB5A"

Note that version 1.2 or later of the library is required for this application.

Next we must define some data structures used by the program; an INITCOMMONCONTROLSEX structure, a REBARINFO structure and a REBARBANDINFO structure:

        DIM icex{dwSize%, dwICC%}
        DIM rbi{cbSize%, fMask%, himl%}
        DIM rbBand{cbSize%, fMask%, fStyle%, clrFore%, clrBack%, lpText%, cch%, \
        \          iImage%, hwndChild%, cxMinChild%, cyMinChild%, cx%, hbmBack%, wID%}

InitCommonControlsEx is now called to enable the classes required by the rebar control:

        ICC_COOL_CLASSES = &400
        ICC_BAR_CLASSES = 4
        icex.dwSize% = DIM(icex{})
        icex.dwICC%  = ICC_COOL_CLASSES OR ICC_BAR_CLASSES
        SYS "InitCommonControlsEx", icex{}

Now we are ready to create the rebar control itself:

        RBS_VARHEIGHT = &200
        CCS_NODIVIDER = &40
        WS_EX_TOOLWINDOW = &80
        WS_CLIPSIBLINGS = &4000000
        WS_CLIPCHILDREN = &2000000
        hRB% = FN_createwindow(@hwnd%, "ReBarWindow32", "", 0, 0, 0, 0, 0, \
        \      WS_CLIPSIBLINGS OR WS_CLIPCHILDREN OR \
        \      RBS_VARHEIGHT OR CCS_NODIVIDER, WS_EX_TOOLWINDOW)
        IF hRB% = 0 ERROR 100, "Couldn't create ReBar window"

The RB_SETBARINFO message is sent to specify an image list, if any (none is used in this example):

        RB_SETBARINFO = &404
        rbi.cbSize% = DIM(rbi{})
        rbi.fMask% = 0
        rbi.himl% = 0
        SYS "SendMessage", hRB%, RB_SETBARINFO, 0, rbi{} TO res%
        IF res% = 0 ERROR 100, "Couldn't send ReBar info"

If you do want to specify an image list set “rbi.fMask%” to “_RBIM_IMAGELIST” (=1) and set “rbi.himl%” to the handle of the image list.

Next we initialise the REBARBANDINFO structure members which are common to all the bands:

        RBBIM_STYLE = 1
        RBBIM_TEXT = 4
        RBBIM_CHILD = &10
        RBBIM_CHILDSIZE = &20
        RBBIM_SIZE = &40
        RBBIM_BACKGROUND = &80
        RBBS_CHILDEDGE = 4
        RBBS_FIXEDBMP = &20
        rbBand.cbSize% = DIM(rbBand{})
        rbBand.fMask%  = RBBIM_TEXT OR RBBIM_STYLE OR \
        \                RBBIM_CHILD OR RBBIM_CHILDSIZE OR RBBIM_SIZE
        rbBand.fStyle% = RBBS_CHILDEDGE OR RBBS_FIXEDBMP

If you want to specify a background bitmap include “_RBBIM_BACKGROUND” in the “rbBand.fMask%” value and set “rbBand.hbmBack%” to the handle of the required image.

At this stage we have a rebar control, but have not yet created any bands. The first band will contain a combo box, so we first create a combo box in the usual way:

        CBS_DROPDOWN = 2
        hCB% = FN_combobox(hRB%, "", 0, 0, 0, 100, 200, CBS_DROPDOWN)
        IF hCB% = 0 ERROR 100, "Couldn't create combobox"

The height of the combo box (100 in this example) should be set large enough for the drop-down section; it is necessary when XP Visual Styles are not in use. The value 200 is the ID number of the combo box.

For the purposes of demonstration we will populate the combo box with a couple of items:

        CB_ADDSTRING = 323
        SYS "SendMessage", hCB%, CB_ADDSTRING, 0, "Combo box item 0"
        SYS "SendMessage", hCB%, CB_ADDSTRING, 0, "Combo box item 1"

Now set the REBARBANDINFO structure members that are relevant to the combo box:

        DIM rc{l%, t%, r%, b%}
        SYS "GetWindowRect", hCB%, rc{}
        text$ = "Combo Box"+CHR$0
        rbBand.lpText%     = !^text$
        rbBand.hwndChild%  = hCB%
        rbBand.cxMinChild% = 0
        rbBand.cyMinChild% = rc.b% - rc.t%
        rbBand.cx%         = 220

Note the use of GetWindowRect to discover the height of the combo box; the rebar control uses that to determine the height of the band. The value 220 is the initial width of the band in pixels.

We are now ready to add the first band, containing the combo box:

        RB_INSERTBAND = &401
        SYS "SendMessage", hRB%, RB_INSERTBAND, -1, rbBand{}

The value -1 tells Windows to insert the band at the end of the rebar control.

The second band, containing the toolbar, can now be created. First create the toolbar itself:

        TBSTYLE_TRANSPARENT = &8000
        CCS_NORESIZE = 4
        CCS_NODIVIDER = 64
        hTB% = FN_createwindow(hRB%, "ToolbarWindow32", "", 0, 0, 0, 0, 0, \
        \      TBSTYLE_TRANSPARENT OR CCS_NORESIZE OR CCS_NODIVIDER, 0)
        IF hTB% = 0 ERROR 100, "Couldn't create toolbar"

For the purposes of demonstration we will add four buttons to the toolbar:

        nbuttons% = 4
        DIM tbb{(nbuttons%-1) iBitmap%, idCommand%, fsState&, fsStyle&, pad&(1), dwData%, iString%}
 
        TBSTATE_ENABLED = 4
        FOR N% = 0 TO nbuttons%-1
          READ tbb{(N%)}.iBitmap%
          READ tbb{(N%)}.idCommand%
          tbb{(N%)}.fsState& = TBSTATE_ENABLED
        NEXT N%
 
        DATA 0, 100, 1, 101, 2, 102, 7, 103
 
        TB_ADDBUTTONS = &414
        TB_BUTTONSTRUCTSIZE = &41E
        SYS "SendMessage", hTB%, TB_BUTTONSTRUCTSIZE, DIM(tbb{(0)}), 0
        SYS "SendMessage", hTB%, TB_ADDBUTTONS, nbuttons%, tbb{(0)}

Here the pairs of values in the DATA statement are the button's image index and the button's ID number respectively.

Rather than use custom button images we will use the standard set of large button images:

        IDB_STD_LARGE_COLOR = 1
        DIM tbab{hInst%, nID%}
        tbab.hInst% = -1
        tbab.nID% = IDB_STD_LARGE_COLOR
 
        TB_ADDBITMAP = &413
        SYS "SendMessage", hTB%, TB_ADDBITMAP, nbuttons%, tbab{}

Now set the REBARBANDINFO structure members that are relevant to the toolbar:

        TB_GETBUTTONSIZE = &43A
        SYS "SendMessage", hTB%, TB_GETBUTTONSIZE, 0, 0 TO btnsize%
        text$ = "Tool Bar"+CHR$0
        rbBand.lpText%     = !^text$
        rbBand.hwndChild%  = hTB%
        rbBand.cxMinChild% = 0
        rbBand.cyMinChild% = btnsize% >>> 16
        rbBand.cx%         = 250

Note that this time we find the size of the buttons; the rebar control uses this and the other height values to determine the height of the strip. The value 250 is the initial width of the band in pixels.

Finally we can add the second band, containing the toolbar:

        SYS "SendMessage", hRB%, RB_INSERTBAND, -1, rbBand{}

Again the -1 tells Windows to insert the band at the end, but we could instead have specified the value 0 to insert the toolbar band before the combo box band.

Once the rebar control has been created you can receive notifications from its child controls in the usual way using ON SYS.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
creating_20a_20rebar_20control.txt · Last modified: 2024/01/05 00:22 by 127.0.0.1