Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Cheat's Outlook Bar

0.00/5 (No votes)
3 Mar 2005 1  
An alternative "minimal-code" Outlook-style menu bar.

Sample Image - CheatsOutlookBar.jpg

Introduction

I believe there's an old saying, "Clothes maketh the man", and this definitely applies to software too. No matter how clever and hard-working your applications are, if they're not wearing the latest well-designed clothes, people will think they are poorly written and out of date.

While working on a new project recently, I did a quick search on the web to see what the competition was up to. One of the features they had, which I didn't, was an Outlook-style menu bar, commonly referred to simply as an Outlook Bar. Deciding I wanted one too, I thought about writing my own. Searching the Code Project, I found two useful articles, Marc Clifton's An Outlook Bar Implementation, and Outlook XP bar by ACorbs. Both these articles were interesting and thought-provoking, and I downloaded each of them for a bit of a poke around, as one does!

I then found myself in a bit of a dilemma. I didn't want to simply copy someone else's code, but at the same time, I didn't want to spend hours and hours reinventing the wheel. I remembered a comment made by my manager at a previous job, many years ago. "What are we trying to do here? Achieve technical excellence, or get a job done?" Realising that Marc and ACorbs had done the former, I decided to go for the latter approach, and started doing some lateral thinking.

The eureka moment!

I proceeded to rummage around in the standard Windows Forms toolbox, and began to idly play around with splitters and panels. While doing this, I came across the Dock property, which specifies the justification for a control. In other words, does it attach itself to the top, bottom, left or right of its container, or does it fill all the available space. An idea occurred to me, so I added a Panel to my form, and added three Buttons to the panel. I set the Dock property of each button to Top, and "Lo!", I had created an Outlook Bar!

Well, almost...

Obviously, all I'd really done was stack three buttons one on top of the other, but they did resize themselves with the panel, which was decent of them. At this point, I realised I was going to have to write some code.

Some code

The only code I really needed is in the Click event handler for the buttons. They all share a common handler, as shown here:

        void ButtonClick(object sender, System.EventArgs e)
        {
            // Get the clicked button...

            Button clickedButton = (Button)sender;
            // ... and it's tabindex

            int clickedButtonTabIndex = clickedButton.TabIndex;

            // Send each button to top or bottom as appropriate

            foreach (Control ctl in panel1.Controls)
            {
                if (ctl is Button)
                {
                    Button btn = (Button)ctl;
                    if (btn.TabIndex > clickedButtonTabIndex)
                    {
                        if (btn.Dock != DockStyle.Bottom)
                        {
                            btn.Dock = DockStyle.Bottom;
                            // This is vital to preserve the correct order

                            btn.BringToFront();
                        }
                    }
                    else
                    {
                        if (btn.Dock != DockStyle.Top)
                        {
                            btn.Dock = DockStyle.Top;
                            // This is vital to preserve the correct order

                            btn.BringToFront();
                        }
                    }
                }
            }

            // Determine which button was clicked.

            switch (clickedButton.Text)
            {
                case "Cars":
                    CreateCarList();
                    break;

                case "Outlook Shortcuts":
                    CreateOutlookList();
                    break;

                case "Zip Files":
                    CreateZipList();
                    break;

                case "Miscellaneous":
                    CreateMiscList();
                    break;
            }

                        // Without this, the buttons will hide the items.

            listView1.BringToFront();
        }

Basically, when any of the buttons on the panel is clicked, we save the clicked button and its TabIndex, then go through all the controls on the panel in turn. If it's a button, we check the TabIndex against that of the clicked button. If the TabIndex is greater, then the current button must be below the clicked one, so we send it to the bottom by setting its Dock to DockStyle.Bottom. If the TabIndex is lower, then the button goes to the top.

At this stage, I should point out that to make this work, it's vital that the TabIndices of the buttons are set at design time to the correct order. In the supplied example, the "Cars", "Miscellaneous", "Zip Files" and "Outlook Shortcuts" buttons have their TabIndex set to 1, 2, 3 and 4 respectively.

Back to the main plot. Having set the Dock properties to send the buttons up and down, I noticed that all was not well. If I had buttons 1, 2, 3 and 4 at the top, and I clicked button 1, then buttons 2 to 4 went to the bottom, but they ended up in reverse order, like this:

All is not well...

In an attempt to correct this, I tried a few things, such as walking the panel's controls in reverse order, and altering the TabIndex values "on the fly", but without success. I decided to research the Dock property on MSDN, which told me about the z-order, and explained that it could be controlled by the SendToBack and BringToFront methods of a control. It's explained here and here, much more clearly that I can do in a few words. Suffice to say, by calling the SendToBack method on each button after I docked it, preserved the order of the buttons.

Finally...

The last piece of the jigsaw was another standard Windows Control, the ListView. I added this to the container panel, left its View property as the default LargeIcon, and set its Dock property to Fill, which means it will fill all the remaining space left by the buttons. I added some ImageLists, threw together some code to populate the ListView depending on which button was clicked, and I had a nice looking, functional Outlook bar, created from standard controls and a few lines of code. I then added a second ListView to provide some basic functionality to demonstrate that the menu bar worked.

Hopefully, this article will be of interest, and possibly show how sometimes it's useful to look at a problem from a few different angles before getting your code editor out!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here