May 12, 2013

[ MFC ] - Floating Toolbars using ReBar Control

1. What is Rebar?

The Rebar MFC control acts as the hosting container for the MFC Toolbar controls. Using the rebar control you can float around the toolbar control in the same row and you can easily re-arrange the control. The rebar control is not limited to host only the toolbars, it can host control like EditBox, Combobox etc. Have a look at the below depiction:

Here, we have two toolbars housed on the rebar. The Gripper is the one, which allows us to move the toolbar around the rebar. When we use the rebar, the user will have the facility of moving the toolbar using its gripper and even they can move the toolbar one below the other one. In this article, I will show how do you create two toolbars and house that using the MFC Rebar.

2. Example – Using the MFC Rebar Control

The example application that we are going to build in this article is shown in the below picture:

Our example is a Single Document Interface (SDI) application, which displays six toolbar buttons in two ToolBars. These two ToolBars are housed by the Rebar control. Placing the toolbar on the rebar allows the user to move the toolbar over the Rebar control using the Gripper. Using the grippers, we can also place a toolbar in separate rows.

OK. Let us start building this example.

3. Create ToolBar1 and ToolBar2

Create SDI MFC Application. To create the Toolbar we should use the resource Editor. Firstly, switch to the Resource view, then right click the project name to access the New Resource Dialog.

This will open an “Add Resource” dialog as shown below. From the dialog pick the Toolbar and hit the new button. Do this one more time to add next toolbar. Remember we are going to add two toolbars to the rebar.

Once the toolbars are added, Double click on the toolbar from resource view and draw each button. Below is the screen shot of the Second toolbar:

Once drawing the Toolbar is finished, Right click on each toolbar and assign the ID. The Below picture shows, First button in the First Toolbar is selected, then its property is accessed and ID_TB1_CMD1 is typed for the ID Field. Remember to set this property for each toolbar button from left to right. This will give ID number in ascending order, which will later help us in specifying the command range.

If you find difficulties in designing the toolbar, have a look at the below video which demonstrates creating a toolbar through visual studio editor.

4. Create Bitmap resource

To create a bitmap follow the same procedure explained in the previous section. In the “Add Resource” dialog instead of selecting the toolbar, we should select the Bitmap and hit new. This will add bitmap node in the resource explorer. Once the Bitmap is added, edit it using the resource editor. The below screen shot shows the bitmap used as the background for the example application:

Note that the height of the bitmap matches the height of the toolbar buttons which 32 pixels tall. Also, note that the each toolbar size is set to 32 x 32 pixels.  This you can refer from the previous section’s property screen shot. The video shown below explains creating a bitmap using the visual studio resource editor.

5.  Displaying Toolbar in a Rebar control

When you created a "SDI Application", accepting all the defaults in the wizard, MFC leaves default code that we are going to comment out now. First, go to the resource view and delete the default toolbar named as IDR_MAINFRAME.

1) Navigate to the Function CMainFrame::OnCreate. Comment out the code that creates the default toolbar that you deleted from the resource editor. The toolbars, Menus and status bar are created usually in the CMainFrame::OnCreaye. The code snippet shown below:

//Sample 01: Comment out the toolbar creation as we deleted it
//if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
//     !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
//     TRACE0("Failed to create toolbar\n");
//     return -1;      // fail to create

// TODO: Delete these three lines if you don't want the toolbar to be dockable
//Sample 02: Comment Out

2) In the CMainFrame class, add the below shown private member variables. The two CToolBar objects will be loaded with the toolbars created using the Resource editor. The CBitmap object m_bckBmp will be used to set the background for the Rebar. CReBar object will be used to host the toolbar objects. The entire relationship goes like this: Toolbar buttons are hosted by the toolbar, the toolbar is hosted by the ReBar and the ReBar is hosted by MainFrame. Now you know why we are declaring all the objects here in the CMainFrame class.

//Sample 03: Declaration required for the Toolbar, Bitmap, and Rebar
       CToolBar m_FirstToolBar;
       CToolBar m_SecondToolBar;
       CBitmap m_bckBmp;
       CReBar m_rebar;

3) In the OnCreate function of the CMainFrame, First, we create both the toolbars by calling CreateEx function. Note that we are setting a TBSTYLE_TRANSPARENT flag during the creation of the CToolBar. This is because we want to set the background for the ReBar control and to make it visible we are setting the toolbar as Transparent. You can run this example application without this flag to see how it works. After creating the Toolbar, we are loading the Toolbar buttons by calling the function LoadToolBar and by giving the resource Id for the toolbar.

//Sample 04:Create both the toolbars
m_FirstToolBar.LoadToolBar(IDR_FIRST_TB  );
m_SecondToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_TRANSPARENT );
m_SecondToolBar.LoadToolBar(IDR_SECOND_TB );

4) Next, we will add a handler function for each toolbar buttons coming from both the toolbars. The handler function declaration is made at the MainFrame.h file. This is shown below:

//Sample 05: Declare a dummy Handler Function for all the toolbar
//                        button
       void SomeFunction(UINT someparam);

5) The handler function definition is shown below. This function does not require any explanation.

//Sample 06: A do nothing toolbar handler
void CMainFrame::SomeFunction(UINT someparam)
       //Do Nothing. In real world there will be dedicated functions
       //for toolbar actions
       AfxMessageBox("Toolbar Clicked");

6) Next, inside the message map entry, Place two entries of ON_COMMAND_RANGE. This macro maps a range of command Ids to a specific handler function. Let us take the first message map entry for the explanation. The first two Ids ID_TB1_CMD1 and ID_TB1_CMD3 define the Range for all three buttons in the first toolbar. This ID number should be in ascending order. You can make sure this by visiting the Resource.h file. The third parameter defined the function mapped to the Command Ids. The code given below shows that all six toolbar buttons coming from two different toolbars mapped to a single handler function named SomeFunction.

//Sample 07: Handler for the toolbar buttons
       ON_COMMAND_RANGE(ID_TB1_CMD1, ID_TB1_CMD3, SomeFunction)
       ON_COMMAND_RANGE(ID_TB2_CMD1, ID_TB2_CMD3, SomeFunction)

7) OK. The toolbars are ready. Next, we load the bitmap resource into the CBitmap object m_bckBmp. The LoadBitmap function takes the bitmap resource id as the parameter and loads the resource-edited bitmap into the bitmap object.

//Sample 08: Create the Bitmap

8) Now we have everything ready. The toolbar is ready; bitmap for setting the background is ready. The code given below loads the toolbar into the ReBar Control. First, the rebar control is created calling Create function with the “this” pointer as a parameter. The pointer specifies CMainFrame as the parent to the m_rebar.

Next, we add the toolbars one by one. The second and third parameter specifies the ForeColor and BackClolor for the ReBar control. While adding the toolbars we asked to display the edges also asked to display the Gripper always. The below code snippet sets a solid color to the rebar control:

//Sample 09: Create the Rebar and Add toolbars to it
m_rebar.AddBar(&m_FirstToolBar, RGB(255,0,0), RGB(0,255,0),"TB 1", RBBS_GRIPPERALWAYS
                    | RBBS_CHILDEDGE);
m_rebar.AddBar(&m_SecondToolBar, RGB(255,0,0), RGB(0,255,0),"TB 2", RBBS_GRIPPERALWAYS
                          | RBBS_CHILDEDGE);

9) The below-commented code shows the rebar with the bitmap as the background.

////Sample 10: Create the Rebar and Add toolbars to it
//m_rebar.AddBar(&m_FirstToolBar, "TB 1", &m_bckBmp, RBBS_GRIPPERALWAYS
//                        | RBBS_CHILDEDGE);
//m_rebar.AddBar(&m_SecondToolBar, "TB 2", &m_bckBmp, RBBS_GRIPPERALWAYS
//                         | RBBS_CHILDEDGE);

The screenshot shows the application’s appearance when the Sample10 is executed and Sample09 is commented out:

The video given below shows the usage of the Rebar.

Source Code : Download


Leave your comment(s) here.

Like this site? Tell it to your Friend :)