Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro Visual C++-CLI And The .NET 2.0 Platform (2006) [eng]

.pdf
Скачиваний:
46
Добавлен:
16.08.2013
Размер:
24.18 Mб
Скачать

378 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

Figure 10-1. The Images Collection Editor dialog box

3.Click the Add button, and then navigate to and open the image file within the present Open File dialog box.

4.Repeat step 3 for all desired images.

5.Click the OK button.

Once you have added the images to the ImageList, you may need to configure these three ImageList properties:

ColorDepth is a ColorDepth object that represents the color depth of the icon. The default is 8-bit color, so most likely you will not need to change this property.

ImageSize is a Size object that represents the size of the images contained in the list. The default is 16×16 but the maximum is 256×256. Note that all images in the list are the same size.

TransparentColor is a Color object that represents the transparent color. You probably will be able to ignore this property, as the default is Transparent.

Now that the ImageList is available, it will be selectable from the properties list of all controls within the form that use ImageLists. For a control to get access to the ImageList, simply select the ImageList from this property list.

The final step differs from control to control, but usually to select the specific image to use out of the ImageList, you update an image index property within the control with the corresponding index to the image within the ImageList.

What happens behind the scenes is not quite as easy, and it’s fortunate that you don’t have to worry about it. First, the ImageList that you created is added to the Form1.resx file. At the same time, code is also added to the Form1.h file for a control to access the ImageList. Next, when the program is compiled, the ImageList is serialized and placed within a resource file. The resource file then gets embedded in the executable assembly.

If you examine the code added to the Form1.h file to get access to the ImageList, you will notice that program actually gets the ImageList from the executable assembly:

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

379

System::ComponentModel::ComponentResourceManager^ resources =

gcnew System::ComponentModel::ComponentResourceManager(typeid<Form1>); // ...

this->imFruitSmall->ImageStream = (stdcli::language::safe_cast<System::Windows::Forms::ImageListStreamer^ >

(resources->GetObject(L"imageList.ImageStream")));

You will examine resources and how the preceding code works in much more detail in Chapter 18.

Views

Now that our detour is over, it is finally time to continue on with some advanced, and I think more fun, Window Form controls. Let’s start off with two of the views provided by the .NET Framework: ListView and TreeView. There is a third view, DataGridView, but since this view is so closely integrated with database development, I’ll hold off discussing it until we tackle database development in Chapter 12. If you have used Windows for any amount of time, then you have seen ListView and TreeView, quite extensively, maybe without knowing it. The reason is that these views, when used correctly, provide a better way of displaying data to the user. Because of this, Microsoft uses them within a large portion of the applications and tools they provide.

A point that may not be readily apparent about views, because of all the underlying functionality they provide, is that they are also controls. This means that they are inheritable and derive from components and then the control class. Thus, any place that you could use a simple control from the previous chapter, you could also use one of these feature rich views. What this means, for example, is that instead of displaying data using rows and rows of Label and TextBox controls, you could plug in one of these views instead.

ListView

The ListView is a powerful (but slightly complicated) control that displays a list of items. You can see what a ListView control looks like by opening up Windows Explorer. The ListView is the right-hand panel if two panels are being displayed. The items can consist of a combination of a record (array) of text, a large icon, and/or a small icon.

You can display a ListView in one of four different View property modes:

View::LargeIcon displays a large icon with text underneath in a grid layout.

View::SmallIcon displays a small icon with text along the side in columns.

View::List displays the root text associated with the item in a single column.

View::Details displays the root text and subtext in multiple columns.

Providing the functionality of the ListView requires a number of properties, many of which you have seen before. Here are some of the common ones unique to the ListView:

Activation is an ItemActivation enum that represents whether one or two clicks are required to activate an item. The default is two clicks or ItemActivation::Standard.

AllowColumnReorder is a Boolean that represents whether the headings can be dragged to reorder the columns. The default is false.

380 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

AutoArrange is a Boolean that represents whether the icons are automatically arranged. The default is true.

Columns is a ListView::ColumnHeaderCollection that represents a collection of column headers to be used if the View property mode is set to View::Details.

FocusItem is a ListViewItem that represents the item that currently has focus. If no item has focus, null is returned.

FullRowSelect is a Boolean that represents whether clicking an item selects all its subitems as well. The default is false.

GridLines is a Boolean that represents whether grid lines are displayed. The default is false.

HeaderStyle is a ColumnHeaderStyle enum that represents whether the header is displayed and if it is clickable. The default is displayed and clickable: ColumnHeaderStyle::Clickable.

HoverSelection is a Boolean that represents whether the item is automatically selected when the cursor hovers over it for a few seconds. The default is false.

LabelEdit is a Boolean that represents whether the label of an item can be edited. The default is false.

LabelWrap is a Boolean that represents whether the label wraps when displayed. The default is true.

LargeImageList is an ImageList of the large icons to be used if the View property is set to

View::LargeIcon.

SmallImageList is an ImageList of the small icons to be used if the View property is set to

View::SmallIcon.

Along with these properties, the ListView provides a number of methods. These are some of the common methods unique to ListView:

ArrangeIcons() arranges the icons in large and small icon views.

EnsureVisible() ensures that an item is visible even if the ListView must scroll to make it visible.

GetItemAt() gets an item at a specified x and y location.

Listing 10-1 shows a ListView of fruit, their price, and the month when they are available for harvest. (The data was derived using a high-tech research facility. Okay, you caught me—I made it up.) When an item is selected, its price is displayed in a label. The example also shows how you can switch to any of the four ListView views based on the check value of radio buttons.

Listing 10-1. A ListView of Fruit

#pragma once

namespace

ListViewEx

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

public ref class Form1 : public System::Windows::Forms::Form

{

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

381

public:

Form1(void)

{

InitializeComponent();

FillListView();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::Windows::Forms::ImageList^ imFruitSmall; System::Windows::Forms::ImageList^ ilFruitLarge; System::Windows::Forms::RadioButton^ rbDetails; System::Windows::Forms::RadioButton^ rbList; System::Windows::Forms::RadioButton^ rbSmallIcon; System::Windows::Forms::RadioButton^ rbLargeIcon; System::Windows::Forms::Label^ label; System::Windows::Forms::ListView^ lView; System::Windows::Forms::ColumnHeader^ Fruit; System::Windows::Forms::ColumnHeader^ Price; System::Windows::Forms::ColumnHeader^ Available; System::ComponentModel::IContainer^ components;

#pragma region Windows Form Designer generated code

///<summary>

///Required method for Designer support - do not modify

///the contents of this method with the code editor.

///</summary>

void InitializeComponent(void)

{

this->components = (gcnew System::ComponentModel::Container()); System::ComponentModel::ComponentResourceManager^ resources =

(gcnew System::ComponentModel::ComponentResourceManager(Form1::typeid)); this->imFruitSmall =

(gcnew System::Windows::Forms::ImageList(this->components)); this->ilFruitLarge =

(gcnew System::Windows::Forms::ImageList(this->components)); this->rbDetails = (gcnew System::Windows::Forms::RadioButton()); this->rbList = (gcnew System::Windows::Forms::RadioButton()); this->rbSmallIcon = (gcnew System::Windows::Forms::RadioButton()); this->rbLargeIcon = (gcnew System::Windows::Forms::RadioButton()); this->label = (gcnew System::Windows::Forms::Label());

this->lView = (gcnew System::Windows::Forms::ListView()); this->Fruit = (gcnew System::Windows::Forms::ColumnHeader()); this->Price = (gcnew System::Windows::Forms::ColumnHeader()); this->Available = (gcnew System::Windows::Forms::ColumnHeader()); this->SuspendLayout();

382 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

//

//imFruitSmall

this->imFruitSmall->ImageStream = (cli::safe_cast<System::Windows::Forms::ImageListStreamer^> (resources->GetObject(L"imFruitSmall.ImageStream")));

this->imFruitSmall->Images->SetKeyName(0, L"apple.ico"); this->imFruitSmall->Images->SetKeyName(1, L"banana.ico");

this->imFruitSmall->Images->SetKeyName(2, L"orange.ico");

//ilFruitLarge

//

this->ilFruitLarge->ImageStream = (cli::safe_cast<System::Windows::Forms::ImageListStreamer^> (resources->GetObject(L"ilFruitLarge.ImageStream")));

this->ilFruitLarge->Images->SetKeyName(0, L"apple.ico"); this->ilFruitLarge->Images->SetKeyName(1, L"banana.ico"); this->ilFruitLarge->Images->SetKeyName(2, L"orange.ico");

//

//rbDetails

this->rbDetails->Anchor = static_cast<System::Windows::Forms::AnchorStyles> ((System::Windows::Forms::AnchorStyles::Bottom |

System::Windows::Forms::AnchorStyles::Right)); this->rbDetails->AutoSize = true;

this->rbDetails->Checked = true;

this->rbDetails->Location = System::Drawing::Point(154, 201); this->rbDetails->Name = L"rbDetails";

this->rbDetails->Size = System::Drawing::Size(53, 17); this->rbDetails->TabIndex = 17;

this->rbDetails->Text = L"Details"; this->rbDetails->CheckedChanged +=

gcnew System::EventHandler(this, &Form1::rbType_CheckedChanged);

//rbList

//

this->rbList->Anchor = static_cast<System::Windows::Forms::AnchorStyles> ((System::Windows::Forms::AnchorStyles::Bottom |

System::Windows::Forms::AnchorStyles::Right)); this->rbList->AutoSize = true;

this->rbList->Location = System::Drawing::Point(154, 177); this->rbList->Name = L"rbList";

this->rbList->Size = System::Drawing::Size(37, 17); this->rbList->TabIndex = 16;

this->rbList->Text = L"List"; this->rbList->CheckedChanged +=

gcnew System::EventHandler(this, &Form1::rbType_CheckedChanged);

//

// rbSmallIcon

//

this->rbSmallIcon->Anchor = static_cast<System::Windows::Forms::AnchorStyles>

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

383

((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Right));

this->rbSmallIcon->AutoSize = true;

this->rbSmallIcon->Location = System::Drawing::Point(154, 153); this->rbSmallIcon->Name = L"rbSmallIcon"; this->rbSmallIcon->Size = System::Drawing::Size(70, 17); this->rbSmallIcon->TabIndex = 15;

this->rbSmallIcon->Text = L"Small Icon"; this->rbSmallIcon->CheckedChanged +=

gcnew System::EventHandler(this, &Form1::rbType_CheckedChanged);

//

//rbLargeIcon

this->rbLargeIcon->Anchor = static_cast<System::Windows::Forms::AnchorStyles> ((System::Windows::Forms::AnchorStyles::Bottom |

System::Windows::Forms::AnchorStyles::Right)); this->rbLargeIcon->AutoSize = true;

this->rbLargeIcon->Location = System::Drawing::Point(154, 129); this->rbLargeIcon->Name = L"rbLargeIcon";

this->rbLargeIcon->Size = System::Drawing::Size(72, 17); this->rbLargeIcon->TabIndex = 14;

this->rbLargeIcon->Text = L"Large Icon"; this->rbLargeIcon->CheckedChanged +=

gcnew System::EventHandler(this, &Form1::rbType_CheckedChanged);

//label

//

this->label->Anchor = static_cast<System::Windows::Forms::AnchorStyles> ((System::Windows::Forms::AnchorStyles::Bottom |

System::Windows::Forms::AnchorStyles::Left)); this->label->BorderStyle =

System::Windows::Forms::BorderStyle::FixedSingle; this->label->Location = System::Drawing::Point(19, 162); this->label->Name = L"label";

this->label->Size = System::Drawing::Size(64, 21); this->label->TabIndex = 13;

this->label->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

//

// lView

//

this->lView->Anchor = static_cast<System::Windows::Forms::AnchorStyles>

((((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom) | System::Windows::Forms::AnchorStyles::Left) | System::Windows::Forms::AnchorStyles::Right));

this->lView->Columns->AddRange(

gcnew cli::array< System::Windows::Forms::ColumnHeader^>(3)

{

this->Fruit, this->Price, this->Available

});

384 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

this->lView->FullRowSelect = true; this->lView->GridLines = true; this->lView->LabelEdit = true; this->lView->LargeImageList = this->ilFruitLarge;

this->lView->Location = System::Drawing::Point(0, 0); this->lView->MultiSelect = false;

this->lView->Name = L"lView";

this->lView->Size = System::Drawing::Size(270, 109); this->lView->SmallImageList = this->imFruitSmall; this->lView->TabIndex = 12;

this->lView->View = System::Windows::Forms::View::Details; this->lView->SelectedIndexChanged +=

gcnew System::EventHandler(this, &Form1::lView_SelectedIndexChanged);

//

//Fruit

this->Fruit->Text = L"Fruit"; this->Fruit->Width = 115;

//Price

//

this->Price->Text = L"Price"; this->Price->Width = 50;

//

//Available

this->Available->Text = L"Available"; this->Available->Width = 100;

//Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(269, 229); this->Controls->Add(this->rbDetails); this->Controls->Add(this->rbList); this->Controls->Add(this->rbSmallIcon); this->Controls->Add(this->rbLargeIcon); this->Controls->Add(this->label); this->Controls->Add(this->lView);

this->Name = L"Form1";

this->Text = L"List View Example"; this->ResumeLayout(false); this->PerformLayout();

}

#pragma endregion

private:

void FillListView()

{

array<String^>^ itemRec1 = gcnew array<String^> { "Apple", "1.50", "September"

};

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

385

lView->Items->Add(gcnew ListViewItem(itemRec1, 0));

array<String^>^ itemRec2 = gcnew array<String^> { "Banana", "3.95", "November"

};

lView->Items->Add(gcnew ListViewItem(itemRec2, 1));

array<String^>^ itemRec3 = gcnew array<String^> { "Orange", "2.50", "March"

};

lView->Items->Add(gcnew ListViewItem(itemRec3, 2));

}

System::Void lView_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)

{

if (lView->FocusedItem != nullptr)

label->Text = lView->FocusedItem->SubItems[1]->Text;

}

System::Void rbType_CheckedChanged(System::Object^ sender, System::EventArgs^ e)

{

if (rbLargeIcon->Checked) lView->View = View::LargeIcon;

else if (rbSmallIcon->Checked) lView->View = View::SmallIcon;

else if (rbList->Checked) lView->View = View::List;

else if (rbDetails->Checked) lView->View = View::Details;

}

};

}

Working with the ListView is a little tricky because the GUI designer doesn’t place things in the code where you expect them (or at least I don’t think so). So I’ll group the code together so that you can see what’s happening more clearly.

First, like any control, you create the ListView and then configure it using its properties. The example ListView is anchored and uses full row selection, display gridlines, no multiple selections, editable labels, large image list, small image list, and is preset to the detailed view.

private: System::Windows::Forms::ListView^ lView; //...

this->lView = gcnew System::Windows::Forms::ListView();

this->lView->Anchor = System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Left | System::Windows::Forms::AnchorStyles::Right;

this->lView->FullRowSelect = true; this->lView->GridLines = true; this->lView->LabelEdit = true; this->lView->LargeImageList = this->ilFruitLarge;

this->lView->Location = System::Drawing::Point(0, 0);

386 C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

this->lView->MultiSelect = false;

this->lView->Size = System::Drawing::Size(270, 109); this->lView->SmallImageList = this->imFruitSmall; this->lView->View = System::Windows::Forms::View::Details; this->lView->SelectedIndexChanged +=

gcnew System::EventHandler(this, &Form1::lView_SelectedIndexChanged);

this->Controls->Add(this->lView);

Next, because the detailed view is available, you need to create headers for the ListView’s items. Notice that you add the headers to the ListView control’s Column property.

//Fruit System::Windows::Forms::ColumnHeader^ Fruit;

this->Fruit = gcnew (gcnew System::Windows::Forms::ColumnHeader()); this->Fruit->Text = L"Fruit";

this->Fruit->Width = 115;

//Price

System::Windows::Forms::ColumnHeader^ Price;

this->Price = (gcnew System::Windows::Forms::ColumnHeader()); this->Price->Text = L"Price";

this->Price->Width = 50;

//Available System::Windows::Forms::ColumnHeader^ Available;

this->Available = (gcnew System::Windows::Forms::ColumnHeader()); this->Available->Text = L"Available";

this->Available->Width = 100;

//Add header to ListView

this->lView->Columns->AddRange (

gcnew array<System::Windows::Forms::ColumnHeader^ >(3) { this->Fruit, this->Price, this->Available

}

);

Finally, once the ListView is ready for the world to see, you add the list items to the view. I showed this being done manually, but you could also use the designer to add list items. Notice the last parameter of the ListViewItem constructor is an integer index to the image within both image lists (large and small) assigned to the ListView.

// Add an Apple to the listview

array<String^>^ itemRec1 = gcnew array<String^> { "Apple", "1.50", "September"

};

lView->Items->Add(gcnew ListViewItem(itemRec1, 0));

Figure 10-2 shows what ListViewEx.exe looks like when you execute it.

C H A P T E R 1 0 A D V A N C E D W I N D O W S F O R M S A P P L I C A T I O N S

387

Figure 10-2. A ListView of fruit

TreeView

If you have worked with Visual Studio 2005, then you should be familiar with the TreeView control. It is used in numerous places—Solution Explorer, Server Explorer, and Class View, just to name a few. It is a control that displays a hierarchy of items in a tree format.

The TreeView, like the ListView just covered, can be a little complicated when you first try to develop code for it. Once you get the hang of it, though, you will realize that it is worth the effort of learning. The TreeView is a powerful tool that you will probably use several times in your coding career.

Configuring the TreeView control requires setting properties, just as with every other control. Here are the common properties you will likely use:

CheckBoxes is a Boolean that represents whether check boxes are displayed next to each node in the tree. The default is false.

ImageIndex is a zero-based Int32 index to the ImageList that represents the position of the default image used by all nodes of the tree. The default is 0. A value of –1 specifies that no image will be used.

ImageList is a collection of bitmaps, icons, and metafiles that will be used to display the images on the tree control. If the Image list is nullptr, which is the default, no images are displayed on the tree.

Indent is an Int32 that represents the distance in pixels to indent for each tree hierarchy level. The default is 19.

LabelEdit is a Boolean that represents whether the label is editable. The default is false.

Nodes is a TreeNodeCollection that represents all the TreeNodes that make up the tree. You will always have to populate this property and there is no default.

SelectedImageIndex is a zero-based Int32 index to the ImageList that represents the position of the default selected image used by the tree. The default is 0. A value of –1 specifies that no image will be used.

SelectedNode is a TreeNode that represents the currently selected node. The default is null, which means no node has been selected.

ShowLines is a Boolean that represents whether lines will be displayed between nodes. The default is true, which means that lines will be displayed.