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

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

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

438 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

//

//bnCancel

this->bnCancel->DialogResult = System::Windows::Forms::DialogResult::Cancel;

this->bnCancel->Location = System::Drawing::Point(205, 60); this->bnCancel->Name = L"bnCancel";

this->bnCancel->Size = System::Drawing::Size(75, 23); this->bnCancel->TabIndex = 7;

this->bnCancel->Text = L"Cancel";

//bnAbort

//

this->bnAbort->DialogResult = System::Windows::Forms::DialogResult::Abort;

this->bnAbort->Location = System::Drawing::Point(110, 60); this->bnAbort->Name = L"bnAbort";

this->bnAbort->Size = System::Drawing::Size(75, 23); this->bnAbort->TabIndex = 6;

this->bnAbort->Text = L"Abort";

//

//bnOK

this->bnOK->DialogResult = System::Windows::Forms::DialogResult::OK; this->bnOK->Location = System::Drawing::Point(13, 60);

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

this->bnOK->Size = System::Drawing::Size(75, 23); this->bnOK->TabIndex = 5;

this->bnOK->Text = L"OK";

//tbPassedValue

//

this->tbPassedValue->Location = System::Drawing::Point(13, 20); this->tbPassedValue->Name = L"tbPassedValue"; this->tbPassedValue->Size = System::Drawing::Size(267, 20); this->tbPassedValue->TabIndex = 4;

//

// myDialog

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 102); this->Controls->Add(this->bnCancel); this->Controls->Add(this->bnAbort); this->Controls->Add(this->bnOK); this->Controls->Add(this->tbPassedValue);

this->Name = L"myDialog"; this->Text = L"My Custom Dialog"; this->ResumeLayout(false); this->PerformLayout();

}

#pragma endregion };

}

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

439

Figure 10-15 shows what the preceding example looks like when you execute it.

Figure 10-15. A custom dialog box

Now let’s take a look at the code to implement a custom dialog box (see Listing 10-13). The example calls the dialog box by clicking anywhere in the form.

Listing 10-13. Implementing a Custom Dialog Box

#include "MyDialog.h"

namespace

CustomDialog

{

 

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

{

public:

Form1(void)

{

InitializeComponent();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::Windows::Forms::Label^ lbRetString; System::Windows::Forms::Label^ lbRetVal; System::ComponentModel::Container ^components;

440 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

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->lbRetString = (gcnew System::Windows::Forms::Label()); this->lbRetVal = (gcnew System::Windows::Forms::Label()); this->SuspendLayout();

//

//lbRetString

this->lbRetString->Location = System::Drawing::Point(34, 119); this->lbRetString->Name = L"lbRetString";

this->lbRetString->Size = System::Drawing::Size(225, 19); this->lbRetString->TabIndex = 3;

//lbRetVal

//

this->lbRetVal->Location = System::Drawing::Point(34, 77); this->lbRetVal->Name = L"lbRetVal";

this->lbRetVal->Size = System::Drawing::Size(225, 19); this->lbRetVal->TabIndex = 2;

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 273); this->Controls->Add(this->lbRetString); this->Controls->Add(this->lbRetVal);

this->Name = L"Form1";

this->Text = L"Click Form to get dialog"; this->Click +=

gcnew System::EventHandler(this, &Form1::Form1_Click); this->ResumeLayout(false);

}

#pragma endregion

private:

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

{

MyDialog ^mydialog = gcnew MyDialog(); mydialog->PassedValue = "This has been passed from Form1";

if (mydialog->ShowDialog() == System::Windows::Forms::DialogResult::OK) lbRetVal->Text = "OK";

else if (mydialog->DialogResult == System::Windows::Forms::DialogResult::Abort) lbRetVal->Text = "Abort";

else

lbRetVal->Text = "Cancel";

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

441

lbRetString->Text = mydialog->PassedValue;

}

};

}

Figure 10-16 shows what the preceding example looks like when you execute it.

Figure 10-16. Calling a custom dialog box

Not much of a change, is there? First, you include the include file for the definition of the MyDialog class using the standard include statement:

#include "MyDialog.h"

You need to do this because C++/CLI requires (like standard C++) that classes be defined before you use them. Next, you create an instance of the dialog box:

MyDialog ^mydialog = gcnew MyDialog();

Optionally, you can pass all the data you want to the dialog box:

mydialog->PassedValue = "This has been passed from Form1";

Then you call the dialog box in one of two ways:

ShowDialog()

Show()

The first mode, ShowDialog(), is modal. In this mode, you wait for the dialog box to finish before you continue processing. Normally, you would check the DialogResult upon exit, as you do in the example, but that is not necessary:

if (mydialog->ShowDialog() == System::Windows::Forms::DialogResult::OK) lbRetVal->Text = "OK";

else if (mydialog->DialogResult == System::Windows::Forms::DialogResult::Abort) lbRetVal->Text = "Abort";

else

lbRetVal->Text = "Cancel";

The second mode, Show(), is modeless. In this mode, the dialog box opens and then returns control immediately back to its caller. You now have two threads of execution running. (I cover threads in Chapter 16.) I usually use modeless dialog boxes for displaying information and not retrieving information. A classic example is the about box:

442 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

AboutBox->Show();

This is not to say that you can’t use a modeless dialog box to retrieve information, but you just need to be aware that the code that opens the dialog box is still executing, and it will not be waiting for a result from the dialog box. If this confuses you, you might want to consult Chapter 16 on how to code for two (or more) threads of execution.

The final thing you might do (again, this is optional) is grab the changed data out of the dialog box:

lbRetString->Text = mydialog->PassedValue;

By the way, I have been using Strings to pass data back and forth between the dialog box and the main application. This is not a restriction, though—you can use any data type you want.

Common .NET Framework–Provided Dialog Boxes

When you’ve worked with Windows for any length of time, you soon come to recognize some common dialog boxes that many applications use. The .NET Framework class library provides you easy access to using these same Windows dialog boxes in your programs. Table 10-3 shows a list of the available common dialog boxes.

Table 10-3. The Common Dialog Boxes

Dialog Box

Description

ColorDialog

A dialog box to select a color

FolderBrowserDialog

A dialog box that allows the user to choose a folder

FontDialog

A dialog box to select a font

OpenFileDialog

A common Open File dialog box

PageSetupDialog

A dialog box that manipulates page settings, such as margins

PrintDialog

A dialog box to select a printer and the portion of the document

 

you want to print

SaveFileDialog

A common File Save dialog box

 

 

You call the common dialog boxes in the same way you do the custom dialog box you just built. Listing 10-14 shows just how simple it is to call the ColorDialog. Calling all the other custom dialog boxes is done the same way.

Listing 10-14. Calling a Common ColorDialog

namespace

ColorDialogEx

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;

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

443

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

{

public:

Form1(void)

{

InitializeComponent();

}

protected:

~Form1()

{

if (components)

{

delete components;

}

}

private:

System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code

void InitializeComponent(void)

{

this->SuspendLayout();

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(292, 273);

this->Name = L"Form1";

this->Text = L"Common Color Dialog - Click Form"; this->Click +=

gcnew System::EventHandler(this, &Form1::Form1_Click); this->ResumeLayout(false);

}

#pragma endregion

private:

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

{

ColorDialog^ colordialog = gcnew ColorDialog();

if (colordialog->ShowDialog() == System::Windows::Forms::DialogResult::OK)

{

BackColor = colordialog->Color;

}

}

};

}

444 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

There is nothing new or special here. First, check to make sure that the dialog box exited with the DialogResult of OK, and then set the color of the object you want changed with the value in the

Color property of the ColorDialog.

Figure 10-17 shows what the example looks like when you execute it.

Figure 10-17. Calling a common ColorDialog

Summary

In this chapter, you’ve encountered many of the more powerful controls available to the Win Forms developer. You started off with a couple of views and then moved on to container controls. Next, you looked at the strip controls ToolStrip, StatusStrip, and MenuStrip. Then, to finish off the coverage of controls, you took a look at some of the more fun controls available. After your whirlwind tour of controls, you ended Windows Form development with examining dialog boxes.

You should now be able to build a commercial-grade GUI interface that will impress all of your peers.

In the next chapter, you’ll continue to examine the GUI interface provided by the .NET Framework class library, but this time you’ll look at working with things such as fonts and prebuilt images, and drawing your own images from scratch.

C H A P T E R 1 1

■ ■ ■

Graphics Using GDI+

Using the .NET Framework class library’s Windows Form controls is not the only way to graphically present data to the user. There is no doubt that Win Form controls are powerful, but occasionally you may want more control over what exactly is displayed by the computer than these controls can provide. This chapter covers another major method of displaying data to Windows applications: GDI+.

Unlike in a Win Forms application, when you write GDI+ code, you do it from scratch. There are no GUI drag-and-drop tools available to ease development, though you still lay out the form on which you plan to use GDI+ with the GUI design tool. The entire form does not need to be the target of the GDI+ images. Instead, GDI+ images can be painted on any control. Thus, you can develop a complex form and designate only a small portion of the form to working with GDI+.

In this chapter you will see just how easy it is to develop applications using GDI+. You will start with a high-level overview of GDI+ by looking at what it is and what it consists of. You will then look in detail at some of its functionality, such as fonts, pens, colors, and lines. Once you have covered the basics of GDI+, you will then look at more advanced topics, such as scrolling, optimization, and double buffering. Finally, to round off the discussion, you will discover that GDI+ is not just for displaying data to your monitor—you can also use it on printers.

At first glance, you might think this chapter is solely for the graphics guru. This is somewhat true, but many of the topics presented in this chapter are used by other areas of the .NET Framework class library such as Win Forms and Web Forms. For example, the Font class and the Color, Size, and Position structures are used frequently in Win Forms and Web Forms. Graphics gurus will want to read this chapter, and the average Win Forms or Web Forms developer should probably skim this chapter as well.

What Is GDI+?

In the simplest terms, GDI+ is a set of namespaces that provides for the rendering of 2D graphics. For example, GDI+ provides support for colors, pens, fonts, image transformations, and anti-aliasing. GDI+ contains none of the advanced animation and 3D rendering features found in DirectX.

Notice that I didn’t include the phrase “render to the video adapter” in the preceding paragraph, because the device GDI+ renders to is immaterial. Well, almost immaterial—some differences have to be accounted for between some devices. For example, video adapters don’t have to worry about form feeds, whereas printers obviously do. GDI+ is designed to support almost any graphical display device.

GDI+ originated from the Windows Graphical Device Interface (GDI), which has been around since Microsoft Windows 3.0. GDI+ shares many of the features of its predecessor, but with the .NET Framework class library there have been several improvements, thus the new name of GDI+.

445

446

C H A P T E R 1 1 G R A P H I C S U S I N G G D I +

A Quick Look at the GDI+ Namespaces

You can find the core functionality of GDI+ in the .NET Framework class library namespaces listed in Table 11-1.

Table 11-1. GDI+ Core Namespaces

Namespace

Description

System::Drawing

This namespace is the core of GDI+. It consists of numerous

 

classes to handle basic 2D rendering. It is also the location of

 

the Graphics class from which all GDI+ functionality springs.

System::Drawing::Drawing2D

This namespace extends the 2D rendering capabilities of

 

GDI+ by providing more advanced 2D rendering and vector

 

graphics.

System::Drawing::Imaging

This namespace provides classes that allow direct manipula-

 

tion of graphical images.

System::Drawing::Printing

This namespace provides classes that allow printing to a

 

printer. It also provides classes to interact with the printer.

System::Drawing::Text

This namespace provides advanced font and font family

 

functionality.

 

 

Primarily, most of the functionality that you’ll be working with is found in the classes and structures in the System::Drawing namespace (see Table 11-2).

Table 11-2. Key System::Drawing Namespace Classes and Structures

Class/Structure

Description

Bitmap

A class that represents and provides limited manipulation capabili-

 

ties for an image file with formats such as .bmp, .gif, and .jpg

Brush

A class used to specify the color and pattern to fill the interior of a

 

shape such as a rectangle, ellipsis, or polygon

Brushes

A class made up of several static properties of predefined brushes

Color

A structure that represents a color

Font

A class that represents a font

FontFamily

A class that defines a group of fonts with the same basic design

Graphics

The core class of GDI+ that represents a drawing surface where you

 

will place your text, shapes, and images

Icon

A class that represents a Windows icon

Image

An abstract base class used in all image type classes such as bitmaps

 

and icons

Pen

A class used to specify the color, thickness, and pattern used to

 

outline shapes

Pens

A class made up of several static properties of predefined pens

C H A P T E R 1 1 G R A P H I C S U S I N G G D I +

447

Table 11-2. Key System::Drawing Namespace Classes and Structures

Class/Structure

Description

Point, PointF

A structure that represents an x, y coordinate as either a pair of

 

Int32s or Singles

Rectangle, RectangleF

A structure that represents the size and location of a rectangle using

 

either Int32 or Single values

Region

A sealed class that describes a geometric shape using rectangles

Size, SizeF

A structure that represents a size as either a pair of Int32s or Singles

SolidBrushes

A class that defines a Brush that fills a shape with a solid color

StringFormat

A sealed class that specifies the layout information such as align-

 

ment, formatting, and line spacing for a set of text

SystemBrushes

A class made up of several static properties of SolidBrushes using

 

system colors

SystemColors

A class made up of several static properties of system colors

SystemFonts

A class made up of several static properties of system fonts

SystemIcons

A class made up of several static properties of Windows system icons

SystemPens

A class made up of several static properties of Pens using system colors

TextureBrush

A class that represents a Brush that uses an image to fill a shape interior

 

 

All of the functionality of GDI+ is located within the System.Drawing.dll assembly. Thus, you need to reference it at the top of your source code with the following #using statement:

#using <System.Drawing.dll>

Note If you are using Visual Studio 2005 to do your Win Forms development, System.Drawing.dll is automatically added as a reference.

“Hello World!” GDI+ Style

Why break a trend I’ve set in the book? Here’s “Hello World!” again (see Listing 11-1). This time it’s using GDI+ to render the “Hello World” text.

Listing 11-1. “Hello World!” GDI+ Style

namespace

HelloGDI

{

 

using

namespace System;

using

namespace System::ComponentModel;

using

namespace System::Collections;

using

namespace System::Windows::Forms;

using

namespace System::Data;

using

namespace System::Drawing;