More About Controls


The System::Windows::Forms namespace provides you with a large number of controls that you can use to build program GUIs. The following table lists the major controls in the namespace.

Control

Description

Button

A Windows button control.

CheckBox

A Windows check box control.

CheckedListBox

A ListBox control with a CheckBox on each item.

Clipboard

Not strictly a control, but a class that lets you interact with the Windows clipboard.

ComboBox

A Windows combo box.

Cursor

Represents the image used for the mouse cursor.

DataGrid

A grid control that works with ADO.NET datasets

DateTimePicker

A control that lets the user select a date and time.

DomainUpDown

An up-down control that displays strings.

ErrorProvider

Works with other controls to show that a control has errors associated with it.

Help

Encapsulates the HTML Help engine.

ImageList

A control that manages a list of images; frequently used with toolbars and other controls that need multiple images.

Label

A Windows label control.

LinkLabel

A label that can display hyperlinks.

ListBox

A Windows list box control.

ListView

Displays a list of items in one of four views: small icon, large icon, list, and details. Think of the right panel of Windows Explorer.

Menu

The base class for all menu types.

MessageBox

Represents a Windows message box.

MonthCalendar

Lets the user select a date using a visual display.

NumericUpDown

An up-down control that displays numbers.

Panel

A control that can contain other controls.

PictureBox

A control that can display images from image files.

ProgressBar

A control that displays the progress of an operation.

PropertyGrid

A control that lets you browse the properties of an object.

RadioButton

A Windows radio button.

RichTextBox

A TextBox control that supports formatting and other word processing features.

ScrollBar

A control that encapsulates a standard Windows scrollbar. If you want a control to act as a slider, use a TrackBar instead of a ScrollBar.

Splitter

A control for resizing docked controls at run time.

StatusBar

A control that represents the status bar at the bottom of a window.

TabControl and TabPage

Controls that let you create and manage tabbed dialog boxes.

TextBox

A Windows textbox control.

Timer

A control that implements a timer.

ToolBar

A control that implements a standard toolbar.

TrackBar

A control that implements a slider.

TreeView

A control for displaying a hierarchical collection of items as a tree. Think of the left panel of Windows Explorer.

There are far too many controls to cover all of them in detail, so I’ll show you how to use some of the major ones.

Using the TreeView Control

Tree view controls, which display a hierarchy of items as a tree, will be familiar to anyone who has used Windows Explorer. The System::Windows::Forms:TreeView class wraps the Windows tree view control and makes it simple to create and manipulate trees of items. Let’s look at the methods and properties provided by the class, and then the exercise will show you how to create and use a TreeView.

A tree view is formed of nodes, represented by TreeNode objects, which exist in a parent/child relationship. Root nodes have no parent, and it’s possible for a TreeView to contain more than one root node. The following figure shows a typical TreeView.

In this example, Desktop is the root node. Each node can have a label and an icon associated with it, and each node might have lines joining it to sibling and parent nodes. If a node has child nodes, it might display a button next to it that shows a plus sign (+). Clicking the plus sign—or double-clicking the node label or icon—will expand the tree to show the child nodes, in which case the plus sign changes to a minus sign (-). Nodes can have a pair of images associated with them, which are used to show expanded and collapsed nodes.

Creating a TreeView is a matter of setting the control’s properties and then creating the TreeNode objects and linking them to form the tree. Both the TreeView and TreeNode classes have a Nodes property that holds a collection of child nodes.

TreeView controls are complex, so the class has a lot of properties, methods, and events; the most commonly used are summarized in the following tables.

Property

Description

BorderStyle

Represents the border style of the control. The default is Fixed3D.

CheckBoxes

Determines whether check boxes are displayed next to nodes. The default is false.

FullRowSelect

Determines whether selecting a node highlights the entire width of the control or only the label. The default is false.

HideSelection

Determines whether the selected node will remain highlighted when the control loses the focus. The default is true.

HotTracking

Determines whether labels take on the appearance of a hyperlink when the mouse pointer is over them. The default is false.

ImageIndex

Represents the zero-based index of the image in the associated ImageList that is used as the default image for nodes.

ImageList

Represents the ImageList control that holds the list of images used by the TreeView.

Indent

Represents the distance each level of child nodes is indented, in pixels.

LabelEdit

Determines whether the user can edit the labels on nodes. The default is false.

Nodes

Represents the collection of nodes in the control.

Scrollable

Determines whether the control displays scroll bars when they’re needed. The default is true.

SelectedImageIndex

Represents the zero-based index of the image in the associated ImageList that is used as the image for selected nodes.

SelectedNode

Gets or sets the currently selected node.

ShowLines

Determines whether lines are drawn between nodes in the tree.

ShowPlusMinus

Determines whether plus and minus signs are displayed next to nodes that have child nodes.

ShowRootLines

Determines whether lines are drawn between nodes at the root of the tree.

Sorted

Determines whether the nodes in the tree are sorted
alphabetically.

TopNode

Returns a reference to the first fully visible node.

VisibleCount

Gets the number of nodes that are fully visible in the tree.

Method

Description

BeginUpdate

Disables redrawing of the TreeView. Use this method if you’re going to add several items because it prevents the control from redrawing itself after each item is added.

CollapseAll

Collapses all nodes in the tree.

EndUpdate

Enables redrawing of the TreeView.

ExpandAll

Expands all nodes in the tree.

GetNodeAt

Gets the node at a particular set of coordinates.

GetNodeCount

Gets the number of nodes attached to the control.

Event

Description

AfterCheck

Occurs after a TreeNode check box is checked.

AfterCollapse

Occurs after a TreeNode is collapsed.

AfterExpand

Occurs after a TreeNode is expanded.

AfterLabelEdit

Occurs after a TreeNode label is edited.

AfterSelect

Occurs after a TreeNode has been selected.

BeforeCheck

Occurs before a TreeNode check box is checked.

BeforeCollapse

Occurs before a TreeNode is collapsed.

BeforeExpand

Occurs before a TreeNode is expanded.

BeforeLabelEdit

Occurs before a TreeNode label is edited.

BeforeSelect

Occurs before a TreeNode has been selected.

ItemDrag

Occurs when an item is dragged onto the TreeView control.

The following exercise will show you how to create and populate a TreeView control. We have several controls to discuss in the rest of this chapter, so you’ll use the controls to put together a Windows Explorer–like file browser. It’s not a very sophisticated one, to be sure, but it will serve to show you the basics of working with these controls in a real application.

  1. Start a new Visual C++ Windows Forms Application (.NET) project, and name it CppControls.

  2. Drag a TreeView from the Toolbox onto the form. Set its Dock property to Left by selecting the property in the editor and picking the leftmost bar from the graphical chooser that pops up. The TreeView will dock to the left side of the form and resize to use the full height of the form. Set the Text property to Browsing.

  3. A TreeView displays a collection of TreeNode objects, which you can set up using the Properties editor. Select the TreeView, bring up the Properties editor, and click the ellipses (...)button to the right of the Nodes property, which will display the TreeNode Editor.

    Add a root node to the TreeView by clicking the Add Root button, and edit the label to read Root. When you dismiss the editor, you should see the root node displayed in the TreeView.

  4. Build and run the program. You should see something like the following figure.

    The TreeView is docked to the left side and has one member, which is highlighted.

Adding Directory Browsing

Now that the TreeView has been set up, let’s make it display some useful information. Adding directory browsing capabilities will show you how to add nodes to the control and how to respond to TreeView events.

  1. Continue using the CppControls project you created in the previous exercise. Now that you know the TreeView displays correctly, use the property editor to remove the sample Root node.

  2. The first step in displaying directory information is to add a list of drive letters to the control, which you’ll need to do in the form source code. You’ll be using classes from the System::IO namespace, so add a using directive to the list at the top of the code, as shown here:

    using namespace System::IO;
  3. Add the following code to the end of the Form1 constructor after the call to InitializeComponent:

    // get the logical drives String* drives[] = Directory::GetLogicalDrives(); for(int i=0; i<drives->Count; i++) { String* name = dynamic_cast<String*>(drives->get_Item(i)); TreeNode* tn = new TreeNode(name); treeView1->Nodes->Add(tn); tn->Nodes->Add(new TreeNode("<dummy>")); } 

    The Directory class is one of the file system access classes provided in System::IO, and it has a number of static methods that help you work with directories. The first member of Directory that you’ll use is GetLogicalDrives, which returns an array of strings containing the names of all the logical drives. Note that the function returns a .NET managed array rather than a C++ native array, so you use the Count property to see how many elements the array contains and the get_Item method to access an element. Because get_Item returns a plain Object*, dynamic_cast is used to cast the pointer to a String*.

    Note

    In most cases, you ought to check the pointer returned by dynamic_cast at run time in case the cast has failed. Here I know that GetLogicalDrives always returns an array of Strings, so I’m not expecting the cast ever to fail.

    I construct a new TreeNode for every item in the array, initialized with the drive name and added to the TreeView. By adding each TreeNode object directly to the TreeView, I’m creating multiple root nodes, which is quite reasonable in this application.

    The final line of code adds one child element labeled <dummy> to each of the new nodes. You have seen tree controls showing the plus and minus signs, which you use to expand and collapse the tree. These signs aren’t displayed unless the TreeNode has child nodes. The problem is that I don’t want to create the child entries until the user clicks a plus sign, but the parent node doesn’t get a plus sign unless the child nodes are already in place. One quick and simple solution is to add a dummy child node. If coded correctly, the user will never see this node but the parent node will have a plus sign. When the user expands the node, the dummy node is deleted and replaced by the real child nodes.

  4. If you build and run the code at this point, you should see the TreeView containing a list of the logical drives, each of which has a plus sign next to it.

  5. The obvious next step is to add another level of detail when the user clicks one of the plus signs. Looking at the table of events shown earlier, you’ll probably agree that the best event to handle is the BeforeExpand event, which is fired before a TreeNode is expanded. Use the Properties editor to add an event handler for the BeforeExpand event.

  6. Add the handler function itself to the CppWindow class, like this:

    private: System::Void treeView1_BeforeExpand(System::Object * sender, System::Windows::Forms::TreeViewCancelEventArgs * e) { // First zap the dummy node, assuming there is one if (e->Node->Nodes->Count != 0) e->Node->Nodes->RemoveAt(0); }

    As usual, the function name reflects the control and the event, and the handler gets passed two arguments. Unlike the previous event handlers for buttons and menus that you’ve seen, this one gets passed a TreeViewCancelEventArgs object, which contains extra information about the event (specifically, the TreeNode that is about to be expanded).

    Before adding any child nodes to the tree, you need to remove the dummy node that was added to make the plus sign display. The Node property of the TreeViewCancelEventArgs object holds a pointer to the node that the event refers to. This node’s collection of children is accessed via the Nodes property, and an element can be removed by passing a zero-based index to the RemoveAt method. Before doing so, however, you need to check that there’s a node to be removed by checking the number of child nodes.

  7. Add the following code to display the contents of a directory:

    private: System::Void treeView1_BeforeExpand(System::Object * sender, System::Windows::Forms::TreeViewCancelEventArgs * e) { // First zap the dummy node, assuming there is one if (e->Node->Nodes->Count != 0) e->Node->Nodes->RemoveAt(0); // Get a list of subdirectories String* dirs[]; try { dirs = Directory::GetDirectories(e->Node->FullPath); } catch(System::Exception* pe) { MessageBox::Show(pe->Message, "Error"); return; } // Add a child node for each one for(int i=0; i<dirs->Count; i++) { String* dirName = dynamic_cast<String*>(dirs->get_Item(i)); TreeNode* tn = new TreeNode(Path::GetFileName(dirName)); e->Node->Nodes->Add(tn); // Add a dummy child node tn->Nodes->Add(new TreeNode("<dummy>")); } }

    Given a path that points to a directory, the Directory::GetDirectories function returns an array of strings containing the names of all subdirectories. As before, this array is a managed array and not a native C++ array. The FullPath property of TreeNode returns a string that represents the path from the root to the node, and it does so by concatenating all the labels of the node’s parents, separated by a separator character. This path string is very useful when dealing with directory trees because if every label is a directory name and the separator character is a backslash (\), the full path to the directory can be built with very little trouble when the user expands a node.

    Note the try and catch blocks around the call to GetDirectories. What if you click the drive letter for a CD or a floppy drive that doesn’t contain a disk? GetDirectories will throw a “device not ready” exception, so you need to be prepared to catch it if you don’t want the program to fail.

    The for loop creates a TreeNode for every directory name and adds it as a child of the current node. The names returned by Directory::GetDirectories are full path names, but you don’t want to use the full path as a name. The Path::GetFileName will strip off everything up to (and including) the final backslash in a path, leaving only the directory name.

    Finally a dummy node is added to each child so that the plus sign will display properly. You can compile the application and test it, and you should be able to see all the directories on your drives.

    Note

    You can, of course, remove TreeNodes from the Nodes collection by using Remove. If you’re going to add or remove a lot of nodes at one time, consider using the BeginUpdate and EndUpdate functions to stop the control from redrawing itself every time the Nodes collection changes.

  8. The application works as it is, but let’s add images to the items in the tree to make it look more professional. To do so, you need to use an ImageList control. As its name implies, an ImageList is simply a control that manages a series of images, and it’s used by controls that might end up using a lot of images, such as TreeViews, ListViews, and ToolBars. Drag an ImageList control from the Toolbox onto the form, where it will appear in the section at the bottom of the designer reserved for nongraphical controls.

  9. Select the ImageList, and then find the Images property in the Properties editor. Click the ellipses (...)button at the right side of the property to bring up the Image Collection Editor. Add the two bitmaps Folder.bmp and Folder_Open.bmp to the list. I created two small icons to represent open and closed folders by copying the icons from Windows Explorer; you can create your own or copy the bitmaps from the solution.

  10. Now select the TreeView, and set the ImageList property to refer to the ImageList control. You also need to set the ImageIndex property to 0 or 1, depending on which entry represents the closed folder bitmap, to ensure that the correct bitmaps get used for open and closed folders.

  11. Build and run the application. You should see the tree being displayed with images.

Using the ListView Control

A list view is a control that is used to display a list of items; unlike the tree view, there’s no hierarchical structure in the data being displayed. An item in a list view can have several items of text and icons associated with it and can be displayed in one of the following four views:

  • Large Icon view, which displays a large icon with text underneath. Items are arranged in a grid in Large Icon view.

  • Small Icon view, which displays a small icon with text alongside. Items are arranged in columns in Small Icon view.

  • List view, which displays the text associated with the item, one item per line.

  • Details view, which displays columns, each of which contains a text item.

You can see what these views look like by opening Windows Explorer and using the View menu to change the appearance of the list view.

Like TreeView, ListView is a complex class with many properties, methods, and events. The following tables summarize the most important ones.

Property

Description

Alignment

Represents how items align in the list view. The default is to align to the top of the control.

AllowColumnReorder

Determines whether the user can drag column headers to reorder the columns. This property is meaningful only in Details view. The default is false.

AutoArrange

Determines whether items are automatically arranged according to the alignment. The default is true.

BackColor

Represents the background color of the control.

BorderStyle

Represents the border style of the control. The default is Fixed3D.

CheckBoxes

Determines whether each item will have a check box next to it. The default is false.

CheckedIndices

Gets the indexes of the currently checked list items.

CheckedItems

Gets the currently checked list items.

Columns

The collection of columns used in Details view.

FocusedItem

Gets the item that currently has the focus.

ForeColor

Represents the foreground color of the control.

FullRowSelect

Determines whether clicking an item will select just the item or the entire row it’s in. This property is used only in Details view. The default is false.

GridLines

Determines whether gridlines are drawn between items. The default is false.

HeaderStyle

Gets or sets the column header style: clickable, non- clickable, or no header.

HideSelection

Determines whether the highlighting of selected items is hidden when the control loses the focus. The default is true.

HoverSelection

Determines whether items can be selected by hovering over them with the mouse. The default is false.

Items

The collection of items belonging to the ListView.

LabelEdit

Determines whether the user can edit item labels. The default is false.

LabelWrap

Determines whether item labels wrap in icon view. The default is true.

LargeImageList

The ImageList used in Large Icon view.

MultiSelect

Determines whether the ListView allows selection of more than one item at a time. The default is true.

Scrollable

Determines whether scroll bars are visible. The default is true.

SelectedIndices

A collection holding the indexes of currently selected items.

SelectedItems

A collection holding pointers to the currently selected items.

SmallImageList

The ImageList used in Small Icon view.

Sorting

Represents the sort order of the items: ascending, descending, or none.

StateImageList

The ImageList used for application-defined states.

TopItem

Returns the item at the top of the list.

View

Represents the view that the ListView is currently displaying: Large Icon, Small Icon, List, or Details.

Method

Description

ArrangeIcons

Arranges icons in Small Icon or Large Icon view.

BeginUpdate

Disables redrawing of the ListView. Use this method if you’re going to add several items because it prevents the control from redrawing itself after each item is added.

Clear

Removes all items and columns from the ListView.

EndUpdate

Re-enables redrawing of the ListView.

EnsureVisible

Ensures that a particular item is visible, scrolling the list if necessary.

GetItemAt

Gets the item at specific X,Y coordinates.

GetItemRect

Gets the bounding rectangle for an item.

IsInputKey

A protected method that handles special input keys, such as Page Down and the arrow keys.

Event

Description

AfterLabelEdit

Occurs after a label is edited.

BeforeLabelEdit

Occurs before a label is edited.

ColumnClick

Occurs when the user clicks a column.

ItemActivate

Occurs when an item is activated.

ItemCheck

Occurs when the user checks an item; applies only if the CheckBoxes property is set to true.

ItemDrag

Occurs when an item is dragged and dropped.

SelectedIndexChanged

Occurs when the user clicks an item.

The items displayed in a list view are represented by the ListViewItem class. A ListViewItem can contain a number of data items:

  • A label

  • An image index, which determines which image from the large and small ImageLists will be used for this item

  • Foreground and background colors

  • A tag, which can be any .NET object that you want to attach to the item

  • A collection of subitems, which are used to provide the data for the columns when the control is in Details view

To show you how to use a ListView, the following exercise continues working with the CppControls project and adds a list view control to the right side of the main form. The details of any directory you select in the tree view control will display.

  1. Continue using the CppControls project you created earlier. Drag a ListView from the Toolbox onto the form.

  2. Set its Dock property to Fill by selecting the property in the editor and picking the center bar from the graphical chooser that pops up. This property will cause the list view to fill the unused area of the form.

  3. As a test, create a couple of ListViewItem objects and add them to the ListView. Select the ListView and select the Items property in the Properties editor. Click the ellipses (...)button to the right of the property to bring up the ListViewItem Collection Editor. Press Add to add a new item, and set its Text property to Foo. Add a second item, and set its Text to Bar.

  4. Build and run the application. You should see the ListView and items displayed as shown in the following figure.

    The items are being displayed in the default Large Icon view, but because there are no icons, you see only the labels.

Displaying Directory Details

Now that you’ve seen how to create a ListView, let’s use it to display the details of the directory that’s currently selected in the TreeView. For simplicity, this example will support only the Details view, but you could add code to support the other three views.

  1. Continue using the CppControls project you created earlier. Bring up the ListViewItem Collection Editor, and delete the two sample items. Now that you know the application works, you no longer need the samples.

  2. Set the View property to Details to switch the control to Details view.

  3. To use Details view, you need to set up columns to display the data. This information is held in the Columns collection of the ListView, which holds ColumnHeader objects. You can bring up a ColumnHeader Collection Editor in the usual way, by selecting the Columns property and clicking the ellipses (...)button.

  4. Add three headers to the collection, with the text Type, Name, and Size, and widths of 40, 85, and 65 pixels, respectively.

    Each ColumnHeader has a label set through the Text property and a width in pixels. In this example, we display only the type of the item (file or directory), its name, and its size. You can add more columns if you want to display more information. When you close the editor, you’ll see the columns displayed in the designer view.

  5. That’s all the setting up. You can run the program now, and you’ll see an empty ListView on the form. The next step is to add the code to fill the ListView with file and directory information. Add a private member function named Fill_ListView to the Form1 class, like this:

    void Fill_ListView(String* path) { }

    The argument is the directory path whose contents we want to display.

  6. Add a call to Fill_ListView to the end of the BeforeExpand handler function, treeView1_BeforeExpand, as shown here:

    // Fill the ListView with details of the current node Fill_ListView(e->Node->FullPath);

    When the child nodes have been constructed and added to the TreeView, the full directory path is passed to Fill_ListView so that it can fill in the ListView.

  7. Now let’s start coding Fill_ListView. The first task is to clear out the existing items to make way for the new directory listing.

    // Clear everything from the ListView listView1->Items->Clear();

    Make sure that you call Clear on the Items property, and don’t call listView1->Clear instead because that will clear everything from the ListView, including the column headers you just added!

  8. In true Windows Explorer style, the ListView will list the directories first, followed by the files. Add this code to get the subdirectories of the current path:

    // Start with the directories String* dirs[]; try { dirs = Directory::GetDirectories(path); } catch(System::Exception* pe) { MessageBox::Show(pe->Message, "Error"); return; } 

    This code uses the same Directory::GetDirectories function that you used when creating TreeView entries. Once again, the call is enclosed in a try and catch block, although in this case, there’s much less chance that an exception will be thrown.

  9. Once you’ve got the list of directory names, create ListViewItems to represent them and add them to the ListView, as follows:

    // Create new ListViewItem objects to represent the directories for(int i=0; i<dirs->Count; i++) { String* pathName = dynamic_cast<String*>(dirs->get_Item(i)); String* dirName = Path::GetFileName(pathName); // Create an array of String* to hold the subitems String* subItems[] = new String*[3]; subItems[0] = S"Dir"; subItems[1] = dirName; subItems[2] = S" "; // Create the ListViewItems from the subitems ListViewItem* itm = new ListViewItem(subItems); // Add the ListViewItem to the ListView listView1->Items->Add(itm); }

    The get_Item function retrieves an item from the array, and GetFileName splits off the final component from the path. We need a ListViewItem that has three text fields, one for each of the three columns in the ListView. There’s a constructor for ListViewItem that takes an array of Strings, so it’s a simple matter to create an array of three Strings, initializing them to the type of item (Dir for directory), the name of the directory, and a blank string for the size because we don’t report sizes for directories.

Note

If you want to get more sophisticated, investigate creating ListViewSubItems and using them to build a ListViewItem. ListViewSubItem lets you assign icons, fonts, and colors to each individual item.

The last few lines create a ListViewItem from the String array and then add the ListViewItem to the ListView.

  1. Follow the same process to add details of the files. Here’s the code. It’s long, but there’s little here you haven’t seen before.

    // Now follow with the files String* files[]; try { files = Directory::GetFiles(path); } catch(System::Exception* pe) { MessageBox::Show(pe->Message, "Error"); return; } // Create new ListViewItem objects to represent the files for(int i=0; i<files->Count; i++) { String* pathName = dynamic_cast<String*>(files->get_Item(i)); String* dirName = Path::GetFileName(pathName); // Create an array of String* to hold the subitems String* subItems[] = new String*[3]; subItems[0]= S"File"; subItems[1] = dirName; // Find the file size FileInfo* f = new FileInfo(pathName); subItems[2] = __box(f->Length)->ToString(); // Create the ListViewItems from the subitems ListViewItem* itm = new ListViewItem(subItems); // Add the ListViewItem to the ListView listView1->Items->Add(itm); }

    The code is almost exactly the same as the code for adding directory details, except for the lines that find the file size. The System::IO::FileInfo class represents a file path, and it’s used to get the length of the file in bytes. The long value returned by the property is boxed so that you can call ToString on it, and the resulting String is added to the list of subitems.

  2. If you build and run the application, you should be able to list directory contents.

    click to expand

  3. The ListView gets updated only when you expand a tree node, but it would be good if it were updated whenever you select a node. Do so by adding a handler for the BeforeSelect event, but this time, do not simply double-click in the blank space next to the event name. Use the drop-down button to list the event handlers for the TreeView, and select the BeforeExpand handler; both events will trigger the same handler function. Linking both events to the same handler is what we want here because we want both events to take the same action. You’ll now find that the ListView gets updated whenever you select or expand a node.

Using Splitters

The application now works adequately, but it would be good if you could resize the TreeView and ListView controls rather than having to use the scroll bars. The splitter control gives users the ability to resize docked controls at run time, and you’ll see shortly how to add one to the main form so that users can resize the two view controls.

Splitter doesn’t have many properties or methods that you use in code. Once you’ve added a Splitter to a form, the user interacts with it by dragging it from side to side. When the mouse moves over the splitter, the cursor changes to a double- headed arrow to show that the splitter can be dragged. It’s possible to handle the events that are fired when the splitter is moved, but this isn’t often needed.

  1. Continue using the CppControls project you created earlier. Drag a Splitter from the Toolbox onto the form. You will find that it automatically positions itself between the ListView and the TreeView.

  2. Build and run the application. You’ll find that you can now move the splitter bar to resize the tree view control.

    click to expand

Using Toolbars

Toolbars are a standard feature of just about every GUI application, and the ToolBar class provides everything you need to add toolbar functionality to an application. The ToolBar class has a number of properties, as summarized in the following table.

Property

Description

Anchor

Determines which edge of the container the toolbar is anchored to.

Appearance

Represents the appearance of the ToolBar, which can be Normal or Flat. The default is Normal.

AutoSize

Determines whether the ToolBar automatically resizes itself to fit the buttons. The default is true.

BorderStyle

Represents the border style of the ToolBar. The default is None.

Buttons

Gets the collection of ToolBarButton objects hosted by this ToolBar.

ButtonSize

A Size value that represents the size of the buttons on the ToolBar. The default is 24 pixels wide by 22 pixels high, or large enough for the button’s image and text, whichever is larger.

Divider

Determines whether this ToolBar displays a divider. The default is true.

DropDownArrows

Determines whether arrows are displayed next to drop-down buttons. The default is true.

ImageList

The list of images used on this ToolBar.

ImageSize

Gets a Size object representing the size of the images in the ImageList.

ShowToolTips

Determines whether ToolTips are shown for buttons.

TextAlign

Represents how the text aligns with respect to the images on buttons. The default is ToolBarTextAlign::Underneath.

Wrappable

Determines whether buttons will wrap to the next line if the ToolBar becomes too narrow. The default is true.

Buttons on a toolbar are represented by ToolBarButton objects, and this class also has several useful properties, which are summarized in the following table.

Property

Description

DropDownMenu

Represents the menu associated with a drop-down button.

Enabled

Determines whether the button is enabled. The default is true.

ImageIndex

Represents the index of the image in the ToolBar’s ImageList that will be used for this button. The default is -1 (no image).

Parent

Gets a pointer to the ToolBar that is hosting a button.

PartialPush

Determines whether a toggle-style button is partially pushed. The default is false.

Pushed

Determines whether a button is currently pushed. The default is false.

Rectangle

Gets the bounding rectangle for a button.

Style

Represents the button’s style. The default is PushButton.

Tag

Represents any object that you want to be associated with the button.

Text

Represents the text on the button, if any.

ToolTipText

Represents the text to be displayed for this button’s ToolTip. The parent ToolBar’s ShowToolTips property must be true for ToolTips to be displayed.

Visible

Determines whether the button is visible. The default is true.

ToolBarButtons can be displayed with one of the following four styles:

  • PushButton (the default), where the button simply acts as a pushbutton.

  • DropDownButton, where clicking the button drops down a menu.

  • ToggleButton, where the button toggles between its up and down states.

  • Separator, where the button acts as a separator between two other buttons. Like the separator on a menu, this style of button can’t be selected.

The ToolBar class has two commonly used events: ButtonClick, which is fired when a button is clicked, and ButtonDropDown, which is fired when the menu of a drop-down button is about to be displayed.

This exercise will add a ToolBar to the form. The bar will host two buttons: the first is a drop-down button with a menu, and the second is a standard pushbutton. You’ll also add a handler for the second button to learn how handlers are used with ToolBars.

  1. Continue using the CppControls project you created earlier. Drag a ToolBar onto the form. No matter where you drop it, you will find that it doesn’t size itself to fit completely along the top of the form, but instead only sits at the top of the ListView, obscuring the column headers.

    The problem is that the designer decides who gets priority based on the order in which controls are added to the form. If you had added the ToolBar first and then the TreeView and ListView, everything would fit together.

    Fix the problem by opening the form source code and looking in the code for the InitializeComponent function. Toward the end of the function, you will see the following four lines:

    this->Controls->Add(this->toolBar1); this->Controls->Add(this->splitter1); this->Controls->Add(this->listView1); this->Controls->Add(this->treeView1);

    Move the toolBar1 entry to the end of this list of statements. When you switch back to the designer view, you should see that the ToolBar is properly displayed at the top of the form, with the TreeView and ListView beneath it.

  2. The next task is to create an ImageList object that will hold the bitmaps displayed on the toolbar buttons. Drag a second ImageList onto the form, and use the property editor to add the View.bmp and Exit.bmp bitmap files to its Images collection. Set the ImageList property of the ToolBar to refer to the new ImageList.

  3. Check that the ShowToolTips property of the ToolBar is set to true so that ToolTips will be displayed when the cursor hovers over the buttons.

  4. One of the toolbar buttons is going to display a drop-down menu when clicked, so create a new menu by dragging a ContextMenu from the Toolbox onto the form. Add one or two items to the menu so that you can see how the button works at run time.

  5. Create the buttons by finding the Buttons property of the ToolBar in the Properties editor and clicking the ellipses (...)button to bring up the ToolBarButton Collection Editor.

  6. Press the Add button to add a new button to the collection. Set its Style to DropDownButton, its ToolTipText to View, and its ImageIndex to 0. Using an index of 0 means that the button will use the first image from the ImageList, which should be View.bmp. Set the DropDownMenu property to refer to the ContextMenu you just created.

  7. Add a second button that will function as a separator by setting its Style to Separator. Setting the style to Separator makes this button display as a gap in the button set, and this object doesn’t play any more part in the program’s user interface. It can’t fire events, and the user can’t interact with it.

  8. Add a third button that will display as a normal pushbutton. Leave the Style as PushButton, set the ToolTipText to Exit, and set the ImageIndex to 1. You’ll soon add a handler for this button that will cause the application to exit.

  9. To handle button events, use the Properties editor to locate the ButtonClick event and double-click in the blank space to the right of the event name.

  10. The ButtonClick function handles events coming from all the buttons on the ToolBar, so you need to check which button has sourced the event.

    private: System::Void toolBar1_ButtonClick(System::Object * pSender, System::Windows::Forms::ToolBarButtonClickEventArgs* e) { if (e->Button == toolBarButton3) { Application::Exit(); } }

    The handler function gets passed a ToolBarButtonClickEventArgs object that contains details of which button was clicked. The function checks the Button member of this object, which holds a pointer to the button that originated the event. If it was the third button, which has the default name toolBarButton3, the application exits.

    Note that you don’t check the pSender argument; this argument holds a pointer to the ToolBar itself, not to the button. It would be useful if the application contained more than one ToolBar.

    Note

    To handle a user selection of an item from the menu associated with a drop-down button, simply attach an event handler to the menu item, just as you would for any menu item. We covered how to do this in Chapter 16.

  11. Build and run the application. You should see a ToolBar, which should contain two buttons with a gap between them. Clicking the right-hand button should cause the application to exit.

    click to expand

Using Status Bars

The StatusBar class represents the standard status bar that you see at the bottom of many application windows. As its name implies, the purpose of a status bar is to present status information to the user. Simple status bars display one or more text items, and if you want a more advanced display, you can take over part or all of the drawing of the status bar to display bitmaps, progress controls, or other UI elements. Because this chapter is presenting an introduction to controls, I’ll concentrate on showing you how to display text on a status bar.

Note

Although you can add a status bar to any form, they’re not usually added to dialog boxes.

The following exercise shows how to add a status bar to a form and how to use the status bar to display information.

  1. Drag a StatusBar from the Toolbox onto the form. As with the ToolBar, you’ll find that it doesn’t stretch right across the bottom of the form. The solution is the same as for the ToolBar: edit the code in InitializeComponent so that the StatusBar is the last control added to the Controls collection, rather than the first.

  2. You can easily use the StatusBar to display the path whose contents are currently being listed in the ListView. To do so, add a line to the start of the Fill_ListView function, like this:

    void Fill_ListView(String* path) { // Put the path in the status bar statusBar1->Text = path; ...

    Whatever is assigned to the Text property of the StatusBar will be displayed left justified on the control.

  3. Build and run the application, and select a directory. You should see the path displayed on the status bar.

A StatusBar can display a sizing grip to the lower right, which allows users to resize the window. The sizing grip is displayed by default, but you can turn it off by setting the SizingGrip property to false.

Note

You might notice that the path displayed has two backslashes as the first separator. These appear because the root directory name is returned as C:\, and when the TreeView builds the full path for you, it uses a backslash as the path separator. Having two backslashes instead of one makes no difference to using the path, but if you want to tidy up the path, you can easily remove one from the root name.

You can display more than one piece of information on a status bar, as shown here:

click to expand

Each of the sunken areas on the status bar is called a panel, and you can add as many panels as you want to the bar. A StatusBar object will display either text or panels, and you use the ShowPanels property to determine which is to be displayed at any given time. By default, ShowPanels is false, so text is displayed.

Here’s how to modify the StatusBar to support two panels and display the current path in one of them.

  1. Use the Properties editor to locate the Panels property for the StatusBar, and click the ellipses (...)button to bring up the StatusBarPanel Collection Editor.

  2. Add two panels to the collection, giving the first a width of 200 pixels and the second a width of 100. Delete the default text for both panels. Dismiss the editor, and set the ShowPanels property for the StatusBar to true.

  3. Display the path in the first panel by changing the code in Fill_ListView to set the Text property of the StatusBarPanel rather than the StatusBar.

    // Put the path in the first panel on the statusbar statusBarPanel1->Text = path;
  4. If you build and run the application now, you’ll see the StatusBar displaying two panels.




Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
EAN: N/A
Year: 2003
Pages: 208

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net