1. About MFC Rebar & ToolBar
The MFC Rebar Control acts as the hosting container for the Toolbar controls. Using the Rebar Control, we can float around the toolbar control in the same row and we can easily re-arrange the control. The Rebar control is not limited to host only the toolbars, it can also host controls like Edit Box, Combo box 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, we will explore how to create two toolbars and house that on the MFC Rebar.
2. About The Rebar & ToolBar Example
The example application that we will build in this article is shown in the below picture:
Our example is a Single Document Interface (SDI) application, which shows six toolbar buttons in two ToolBars. These two ToolBars are hosted 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. Let us start building this example.
3. Create ToolBar Resources
First, we create an MFC SDI Application. To create the Toolbar, we should use the Resource Editor. So we 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, we pick the Toolbar and hit the new button. Repeat this step one more time to add next toolbar. Remember, we will add these two toolbars to the Rebar.
After adding the Toolbars, we ‘Double Click’ on the toolbar from resource view and draw each button. Below is the screenshot of the Second toolbar:
Once drawing the Toolbar is finished, we right-click on each toolbar button and assign a Command ID. For example, in the Below picture, first we selected the button in the First Toolbar, then we picked its property and typed ID_TB1_CMD1 for the ID Property. 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’ by hooking that to a single handler function.
If you find difficulties in designing the toolbar, have a look at the below video which demonstrates creating a toolbar through visual studio editor.
Video 1: Creating ToolBar and ToolBar Buttons
4. Create Bitmap Resource For MFC Rebar Control
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 screenshot shows the bitmap used as the background of Rebar for this example:
Note, the height of the bitmap matches the height of the toolbar buttons, which 32 pixels tall. Also, note that we set each toolbar size to 32 x 32 pixels. This you can refer from the previous section’s property screen shot. The video below explains creating a bitmap using the visual studio resource editor.
Video 2: Creating Bitmap Resource
5. Stacking Toolbars Over the Rebar Control
When we created the ‘SDI Application’ accepting all the defaults in the wizard, MFC leaves us with default code. First, we will comment out some generated codes. Now go to the resource view and delete the default toolbar named as
IDR_MAINFRAME
.
5.1 Comment The Default ToolBar Code
The toolbars, Menus and status bar are created usually in the
CMainFrame::OnCreate
. We will navigate to this function and comment out the code for creating the default toolbar. Note, we deleted this resource from the resource editor. The code snippet is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Sample 01: Comment out the toolbar creation as we deleted it //if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD // | WS_VISIBLE | CBRS_TOP // | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY // | CBRS_SIZE_DYNAMIC) || // !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 //m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); //EnableDocking(CBRS_ALIGN_ANY); //DockControlBar(&m_wndToolBar); |
5.2 Member Variables For CToolBar, CRebar & CBitmap
In the CMainFrame class, we will add the private member variables for Tool Bars, Rebar and a Bitmap. We use the two
CToolBar
objects to load the Toolbars which we created using the Resource editor. The
CBitmap
object
m_bckBmp
will set the background for the Rebar. MFC
CRebar
object acting as a container will host the toolbar objects . The entire relationship goes like this: The Toolbar hosts the Toolbar buttons; The Rebar hosts the toolbar, and the Main-Frame hosts the MFC Rebar Control in it. Now we know why we are declaring all the objects here in the
CMainFrame
class.
1 2 3 4 5 6 |
private: //Sample 03: Declaration required for the Toolbar, Bitmap, and Rebar CToolBar m_FirstToolBar; CToolBar m_SecondToolBar; CBitmap m_bckBmp; CReBar m_rebar; |
5.3 Create ToolBar With Buttons
In the OnCreate function of the
CMainFrame
, we create both the toolbars by calling
CreateEx
function. Note, we are setting a
TBSTYLE_TRANSPARENT
flag while creating the
CToolBar
. 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 it with buttons by calling the function
LoadToolBar
and by giving the resource Id for the toolbar.
1 2 3 4 5 |
//Sample 04:Create both the toolbars m_FirstToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_TRANSPARENT ); m_FirstToolBar.LoadToolBar(IDR_FIRST_TB ); m_SecondToolBar.CreateEx(this, TBSTYLE_FLAT | TBSTYLE_TRANSPARENT ); m_SecondToolBar.LoadToolBar(IDR_SECOND_TB ); |
5.4 ToolBar Button Handler Declaration
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. The code is below:
1 2 3 |
//Sample 05: Declare a dummy Handler Function //for all the toolbar button void SomeFunction(UINT someparam); |
5.5 ToolBar Button Handler Implementation
The handler function implementation is below. This function does not require any explanation.
1 2 3 4 5 6 7 |
//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"); } |
5.6 Mapping Command Messages With Handler Function
Inside the message map entry, we place two entries of
ON_COMMAND_RANGE
macro. This macro maps a range of command Ids to a specific handler function. We will take the first message map entry for the explanation. In the macro, 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 of this by visiting the Resource.h file. The third parameter defines 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.
1 2 3 |
//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) |
5.7 Load Bitmap Resource
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 a param and loads the resource-edited bitmap into the bitmap object.
1 2 |
//Sample 08: Create the Bitmap m_bckBmp.LoadBitmap(IDB_TB_BACK); |
5.8 Display Rebar Control With Solid Background
Now we have everything ready. The toolbar is ready; bitmap for setting the background is ready. The code below loads the toolbar into the ReBar Control. First, we create the Rebar control by calling
Create()
function with the ‘this’ pointer as a param. The pointer specifies
CMainFrame
as the parent to the
m_rebar
.
Next, we add the toolbars one by one to the ReBar Control by calling
AddBar()
function. The second and third parameter specifies the ForeColor and BackColor for the ReBar control. While adding the toolbars we asked to display the edges and Grippers. The below code snippet sets a solid background color to the Rebar control:
1 2 3 4 5 6 7 8 9 10 11 12 |
//Sample 09: Create the Rebar and Add toolbars to it m_rebar.Create(this); 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); |
If we run the application now, the Rebar and Toolbar look like below:
5.9 Display Rebar Control With Bitmap Background
The below-commented code shows the Rebar with the bitmap as the background.
1 2 3 4 5 6 |
////Sample 10: Create the Rebar and Add toolbars to it //m_rebar.Create(this); //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 here shows the application’s appearance when code snippet Sample10 is executed and snippet Sample09 is commented out:
Video 3: Running the Example (Floating the Toolbar, Using Grippers, Display Toolbar in 2 Lines)
Source Code: Download MFC Rebar Example From Google Drive
Categories: MFC
Tags: AddBar, CRebar::Create, LoadBitmap, ON_COMMAND_RANGE, RBBS_GRIPPERALWAYS