Toolbars and Status Bars

 

Toolbars started out as a graphical alternative to menus.   A toolbar was (and is) a row of buttons, usually with graphical icons on the buttons to represent common tasks in the program.   These buttons normally duplicate certain commands that can be issued through the menu of the program, but the idea is to put the more common commands in easy one-click reach.    In the years since that time, menus have gotten more graphical and more flexible in their appearance and placement, and  in Visual Studio 2005,  they are treated almost the same from the programmer’s point of view.  That’s a change, since until 2005, it was assumed that every program would have a menu but a toolbar was optional, so the “client area” of the window didn’t include the menu, but it did include the toolbar.  

 

A status bar is a window,  just one line of text high,  across the bottom of a window,  used for informative messages.   Status bars existed before “tool tips” were invented, and they served (and still can serve) a similar purpose;  but in my opinion they should really be replaced by tool tips.   In my experience people often don’t even see the information at the bottom of the window in a status bar.  That, of course, is why tool tips were invented—to make the extra information pop up where people are already looking.   Nevertheless status bars sometimes may be useful, and they’re easy to program. 

 

ToolStripContainer

 

Menus and toolbars both occupy part of your form, below the title bar.  That creates a certain annoyance in that coordinates in your form do include the area covered by the menu and title bar.   The remedy for this is to create a separate window that just fills the area not used by the menu and title bar.  The FCL  provides an easy way of doing this:  the ToolStripContainer.

 

When you’re starting out,  instead of first adding a MenuStrip to your form,  add a ToolStripContainer.    You’ll see something like this:

 

 

Remove the checks from all but “top”, and then drag your MenuStrip onto the container’s top panel.   Now right-click in what appears to be the main window,  and choose Properties.   Observe that you’re not in Form1 but in a Panel object.  What has happened is that the ToolStripContainer window contains five smaller windows, called “panels”.   The top panel contains your menu, and the center one, with the name ContentPanel,  is available for you to draw in, as you formerly drew in Form1.   Now, you won’t have to adjust coordinates for the height of the menu.

 

The ClipboardDemo program

 

Add a Clipboard menu with three menu items, Cut, Copy, and Paste.   We’ll add a toolstrip with three buttons to duplicate those menu commands.

 

Adding a ToolStrip

 

Add a ToolStrip item into that top panel.   (You can click that little tab below the menu to make it open in the design windows enough to be able to drag-and-drop a toolstrip there.)    Right-click your toolstrip and choose Insert Standard Items:

 

 

Then delete all but the three items shown here:

 

 

Observe that Visual Studio was kind and smart enough to enter something in the ToolTipText property of those buttons.   You could change it, and if this were a custom button, you would want to enter it.   This should usually be the same text as the corresponding menu item.   Observe also the AutoToolTip property, which controls the automatic appearance of tool tips when the user mousse over a button on the toolbar.   It’s true by default, so you don’t need to change it.

 

 

Adding an ImageList

 

If, however, you wanted some custom items,  you would do something more complex.   You would add an ImageList.  Here’s how (but we don’t do that in this demo):

 

Drag and drop an ImageList to your form.   We want the ImageList  to contain a list of bitmaps to be used for the buttons.  On the property sheet of the image list, you will see the Images property. Press the button labeled “…” and then the Add button.  Then you can browse for image files.  Browse to where your custom image files are, and add them one by one.   In Visual Studio 2003, you had to employ this method even to add the standard items, but now this is easier, as shown above.  Still, a serious commercial program will need its own custom toolbar, so in your future work you may need to know about ImageList. 

 

Examining the source code

 

  Examine the code in InitializeComponent that the form editor wrote for you.   Find the code that causes the bitmaps for your buttons to be incorporated in your executable file, so the .bmp files won’t need to be there at run time.    It looks something like this:

 

// copyToolStripButton

this.copyToolStripButton.DisplayStyle =

      System.Windows.Forms.ToolStripItemDisplayStyle.Image;

this.copyToolStripButton.Image =

((System.Drawing.Image)(resources.GetObject(

                        "copyToolStripButton.Image")));

this.copyToolStripButton.ImageTransparentColor =

            System.Drawing.Color.Magenta;

this.copyToolStripButton.Name = "copyToolStripButton";

this.copyToolStripButton.Size = new System.Drawing.Size(23,  

                                22);

this.copyToolStripButton.Text = "&Copy";

 

 

In the Tag property of each button,  put the name of the corresponding menu item.   This is how we will tell the program what menu item corresponds to what toolbar button.   Specifically, these tags should be

cutToolStripMenuItem, copyToolStripMenuItem,  and pasteTooStripMenuItem, unless you changed what Visual Studio wrote for you.   Actually, the Tag property can be anything at all—its type is just Object.  Just entering a Tag property doesn’t make anything at all happen, by itself, but we are going to use those Tag properties in our code.  

 

 

 Now check the source code.  You will find that the Tag properties have not been set as you intended—they have been set to strings, for example “cutToolStripMenuItem” instead of the menu item itself.  Both qualify as objects, and the form editor didn’t know which you meant.  Fine, delete the quote marks in your source code, and it will still compile fine, and the form editor seems to retain this code rather than writing over it.    

 

 

 Now you can build and run the program.  Both menu and toolbar should be visible:

 

 

 

Also, the tooltips should be working when you mouse over the toolbar. 

 

Handlers for the Toolbar Buttons

 

We don’t want to give each individual button on the toolbar its own handler.    On the property sheet of each toolbar button, select “events” (the lightning bolt) and look at the Click event.   Select the following handler (which should already be there, but contains no code) and add the following two lines of code:

 

private void toolStripContainer1_TopToolStripPanel_Click(object sender, EventArgs e)

        {

            ToolStripMenuItem mi =     

                  (ToolStripMenuItem)(((ToolStripButton)sender).Tag);

            mi.PerformClick();

 

        }

 

These two lines, together with our assignment of the Tag properties to the toolbar buttons, will ensure that the buttons duplicate the corresponding menus items.  Of course, since we didn’t put in any code for the menu items yet, we can’t test that.

 

Finishing the program

 

 Add a TextBox to your form. Set its properties as follows:

Multiline should be true; ScrollBars should be Both; AcceptsTab should be true.  Dock  should be Fill  (you set that by clicking the middle box).  The Text property should be blank. Check that you can build and run.

 

 Add handlers for your menu items, and write code for the Cut, Paste, and Copy items as follows:

 

 private void CutItem_Click(object sender, System.EventArgs e)

        {

            textBox1.Cut();

        }

 

        private void PasteItem_Click(object sender, System.EventArgs e)

        {

            textBox1.Paste();

        }

 

        private void CopyItem_Click(object sender, System.EventArgs e)

        {

            textBox1.Copy();

        }

 

 

 

Now, at last you can test something:  both your menu items and your toolbar buttons for Copy, Cut,  and Paste should be working.  Type some text into the textbox and cut and paste it to Notepad to see if it works.   Change it, and paste the changed text back from Notepad to your program. 

 

Writing your own code

 

 In Chapter 20 of Petzold, a similar program is created, without using the design editor.  You should, after class, compare the two approaches.  On page 987 there is a discussion of how to disable the Cut and Copy buttons when no text is selected, and to disable the Paste button when there is nothing on the clipboard. 

 

Status Bars

 

Now, let’s put a status bar on this program.   Select your toolStripContainer object in the form designer (by right-clicking in the main part of the form ).  Make the bottom panel’s Visible property True and click to make it visible in the form editor.  Then you can drag a Status Strip onto that panel.

 

On the property sheet of the status strip, go to the Items property and add one item.  Give that panel the text menu help.  Set the AutoSize property to False and the Size property to give it a width of 250.   Run the program:  you should see the status bar and the text menu help.   

 

The status bar is often used to provide a fuller explanation of the selected menu item.   To do that we need to use the Select event that a menu item can generate.  Pick one of your menu items, bring up its property sheet,  click the lightning bolt to look at events, and double-click the MouseHover event to add a handler.   I chose the Cut item, so I got CutToolStripItem_MouseHover as my handler.  Then select that same handler for the other two menu items.

 

 

 

14.  Here’s the code for MenuItemSelect:   (don’t cut and paste because there are line breaks inserted in quoted strings for readability).

 

private void cutToolStripMenuItem_MouseHover(

              object sender, EventArgs e)

{ ToolStripMenuItem mi = (ToolStripMenuItem)sender;

  switch (mi.Text)

  { case "Cut":

      toolStripStatusLabel1.Text = "Copy selected text to the clipboard and delete it from the textbox.";

    break;

    case "Copy":

       toolStripStatusLabel1.Text = "Copy selected

               text to the clipboard.";

       break;

    case "Paste":

       toolStripStatusLabel1.Text = "Paste selected  

            text from the clipboard at the current                

             cursor location.";

       break;

    default:

       toolStripStatusLabel1.Text = "oops!";

       break;

  }

}

 

After this, test the program:  When the menu is in use, the status line text should change.

 

 One problem with this code is that the status line text remains in place after the menu is closed, instead of resetting to the initial text.    For the solution to that problem,  see Petzold, p. 970. 

 

 Another problem with this code is that it will be really hard to maintain when the menu item text is edited, because then the menu item text has to be duplicated in two places, and you’ll never be able to keep them in sync.  In MathXpert, I solved this problem by using the position of the menu item in an array, but it was still difficult to keep them in sync.   Petzold suggests another solution on page 971.  

 

Further explorations:   Look at the properties of your toolbar buttons, and add some text to the Text property of the buttons (it can be the same as the menu text).  Run the program and see how this looks.   Then change the TextAlign property of the toolbar to Right and see how that looks.   As usual in Visual Studio, there are many, many properties in the classes we’ve studied here;  at least look at their names.