As a Visual C++/MFC programmer, I’ve long preferred to use the various MFC classes to code user interfaces and the .NET Framework for areas where MFC doesn’t provide a lot of support (regular expressions, disconnected data, XML, etc.). In fact, I like this technique—called mixed-mode programming—so much that it was the focus of my latest book—Extending MFC Applications with the .NET Framework.
Having said that, I recently completed a project where the client wanted a Managed C++ Windows Forms system without any native, or unmanaged, code. During the process of coding this fairly complex set of GUI-rich applications, I came to realize that all the criticism of how difficult it is to write Managed C++ Windows Forms applications was greatly exaggerated. Please don’t misunderstand. I’m certainly not going to tell my fellow veteran MFC coders that writing UI code in Windows Forms is as easy as in MFC. In many instances, it’s not. For example, MDI applications are much easier to code using MFC than Windows Forms. However, plenty of standard user interfaces that we’re accustomed to can be accomplished easily enough with Windows Forms, and some interfaces are even much easier to develop using Windows Forms!
Since the majority of my previous Managed C++ articles have focused on non-UI topics (with the obvious exception of the GDI+ articles), I devote this article (and more depending on the feedback I receive) to exploring how to create standard user interfaces using Windows Forms (see Figure 1). This first tip will illustrate how easy it is to create a typical SDI application with the following elements:
- Main menu
- Status bar
- List view that consumes the entire client area
- Panel control that basically performs the same functionality as a dialog bar
Figure 1. Creating standard user interfaces can be done in seconds with Visual Studio .NET
Adding the Main Menu
Once you’ve created a Managed C++ Windows Forms application, one of your first tasks is adding a menu. Visual Studio .NET doesn’t do this via the Resource Editor any more. Instead, you drag a MainMenu control onto a form via the Toolbox as you would any UI control (see Figure 2). However, since the menu doesn’t have a visual representation on the form itself, you’ll see an icon with the menu’s name.
Figure 2. Adding a menu to a form
Creating the Menu Items
In order to add a new menu or submenu to the form, click on the menu at the top of the form where you want the text to appear and type in the value. Optionally, you can set the menu item’s Name property. You can name the menu item anything you want, but I prefer to create the menu item name from the fully qualified menu text. Therefore, if you have a menu item for Exit under the File menu, the menu item name would be FileExit. Previous versions of Visual Studio would do this for you automatically instead of naming your menu items menuItem1, menuItem2, and so on. Hopefully, something this basic will be addressed in future releases of Visual Studio.
Wiring the Menu Items to Event Handlers
To write an event handler for a menu item, double-click the menu item. This action will create a method for the Click event, with the method name taking the form [menuItemName]_Click. The fact that the menu name is used in the method name is why I recommend naming your menu items (and all other controls). Someone in one of my recent in .NET training seminars asked: “Why name the control if the editor is creating the method?” The answer is because a day or two from now, you’ll look through your code and won’t have any idea what a method name based on a default control name represents. In other words, FileExit_Click is going to be much easier to recognize than menuItem2_Click. Once Visual Studio .NET generates the method, it inserts the cursor into that method and you can code it to do what you need.
Adding the Status Bar
I typically define the status bar next as it can be difficult to add a status bar where you want on the form once you’ve already added other controls with docking abilities (more on that shortly). To add a status bar control, drag a StatusBar control from the toolbox onto the form (see Figure 3). Without other docking controls, VS.NET will place the status bar at the bottom of the form. The main properties to set here are the Name, Text (the default text that will default to the name property), and ShowPanels (a boolean value that indicates whether each panel in the status bar will be displayed as opposed to a 2D single flat panel). Once you’ve inserted the status bar control, you can update its text by changing its Text property.
Figure 3. Adding a status bar to a dialog/form is much easier than in previous versions of Visual Studio.
Adding and Docking a ListView Control
One of the major benefits that Visual Studio .NET has over previous versions of the editor is it enables you to dock controls when creating forms. Using this feature, you can place a control on a form, define to which side it docks (top, bottom, left, right, or fill), and the control will automatically be moved or sized appropriately when the form itself is resized by the user. This is especially useful when you wish to create what in MFC would have been a CCtrlView-derived view (such as a CListView) where the list control encompasses its parent view’s entire client area. To create this effect, you drag a ListView control onto the form and set its Dock property. (When you set the Dock property, you’ll see a graphical representation of the options with the middle option representing the “Fill” option.) Once you’ve done that, the control will take up the entire client area of the form and be dynamically resized with the form.
Of the many available properties, the following are ones you’ll find yourself setting most often, as well as the new ones that are most helpful:
- Full row select—This boolean property—missing in previous versions of Visual Studio—specifies that if the user selects any column in a listview that the entire row will be selected and highlighted.
- Hide selection—This boolean property specifies whether or not the highlighted (selected) row(s) should be highlighted even if the listview control doesn’t have focus.
- MultiSelect—This property allows you to specify whether the user can select more than one item from the listview.
- Sorting—By default, the listview is not sorted. This property allows you to specify whether it should be sorted and in which direction (ascending or descending).
- View—This one allows you to specify the type default view: Large Icon, Small Icon, Details, or List.
- Columns—A very welcome addition to Visual Studio, this property enables you to define at design time the columns that will make up the listview. In previous versions of Visual Studio, you had to define these in your code even if they never changed.
- Items—For situations where you know at design time the items that will be in the listview, this is a nice addition to the listview properties.
Adding a Panel
The Panel control is a little like the MFC CDialogBar in that it can be defined to dock on one or more sides and be the parent of one or more controls. As an example of that, you might have a listview control docked to fill the client area with a panel docked to the top or bottom that contains controls with buttons that perform actions on selected items. Another example is a header/detail-like form such as invoicing where you have a panel docked to the top containing controls for header information such as invoice number, customer, and so on, and a listview or data grid below that for the invoice detail lines. The possibilities are endless and allow you a great deal of flexibility in crafting your user interface.
To add the Panel control to your form, simply drag it from the toolbox onto a form and specify the Dock property. Any control dropped onto that panel becomes its child window and will move with the parent panel. You can also set the child control Dock properties as needed.
Figure 1 lists all Windows Services in a list view with a dock value of fill. The tree view control is a child of a panel with a dock value of left and the buttons are on yet another panel control with a dock value of bottom.
I intentionally kept this first article simple as the majority of my readers are C++ programmers who—while using Managed C++—haven’t necessarily used it in connection with creating user interfaces with Windows Forms. Based on the feedback I receive, I’ll decide whether to continue writing more UI tips like this. So drop me a line if there’s something in specific that you’d like me to cover in next week’s article!
About the Author
Tom Archer owns his own training company, Archer Consulting Group, which specializes in educating and mentoring .NET programmers and providing project management consulting. If you would like to find out how the Archer Consulting Group can help you reduce development costs, get your software to market faster, and increase product revenue, contact Tom through his Web site.