Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Manning - Windows Forms Programming With CSharp.pdf
Скачиваний:
72
Добавлен:
24.05.2014
Размер:
14.98 Mб
Скачать

A number of classes are available in the System.Drawing namespace for drawing status bar panels, menu items, and other objects. An overview of this namespace is provided in .NET Table 4.5. Rather than provide detailed coverage of this namespace in any one chapter of the book, we will visit members of this namespace as required by our application. In particular, we will use this namespace again in chapter 7 when drawing on Form and Panel controls, and also in chapter 10 when discussing owner-drawn list boxes.

4.4.2DRAWING A PANEL

So let’s draw the panel in our application. If you recall, we want this panel to show what percentage of the image is shown in the PictureBox control. To do this, we need to handle the DrawItem event. We will build this code step by step. The complete code for the handler is shown following the table.

Set the version number of the application to 4.4.

 

 

ADD DRAWITEM HANDLER

 

 

 

 

 

Action

 

Result

 

 

 

 

1

Handle the DrawItem event

 

An event handler for the DrawItem event is added to the

 

for the StatusBar control in

 

control.

 

the MainForm.cs [Design]

 

protected void statusBar1_DrawItem

 

window.

 

 

 

(object sender,

 

How-to

 

StatusBarDrawItemEventArgs sbdevent)

 

 

{

 

In the Properties window for

 

 

 

 

 

the status bar, double-click

 

 

 

the DrawItem entry.

 

 

 

 

 

 

2

In this handler, check that the

 

if (sbdevent.Panel == sbpnlImagePercent)

 

panel to draw is the

 

{

 

sbpnlImagePercent panel.

 

// Calculate the percent of the image shown

 

 

// Calculate the rectangle to fill

 

 

 

 

Note: This if statement is

 

// Draw the rectangle in the panel

 

not strictly necessary. Still,

 

// Draw the text on top of the rectangle

 

 

}

 

since the event relates to the

 

 

 

}

 

entire status bar and not just

 

Note: The four comments here are the four steps that

 

this panel, this provides

 

 

 

must be performed to draw the panel. Each step is

 

some robustness against

 

 

 

performed in the subsequent four steps of this table.

 

future changes.

 

 

 

 

 

 

 

 

OWNER-DRAWN PANELS

121

ADD DRAWITEM HANDLER (continued)

 

Action

Result

 

 

 

3

Calculate what percentage of

// Calculate the percent of the image shown

 

the image appears in the

int percent = 100;

 

window.

if (pbxPhoto.SizeMode

 

!= PictureBoxSizeMode.StretchImage)

 

 

 

How-to

{

 

Rectangle dr = pbxPhoto.ClientRectangle;

 

a. If the SizeMode setting for

 

int imgWidth = pbxPhoto.Image.Width;

 

the image is StretchIm-

int imgHeight = pbxPhoto.Image.Height;

 

age, use 100% of the

percent = 100 * Math.Min(dr.Width, imgWidth)

 

panel.

* Math.Min(dr.Height, imgHeight)

 

/ (imgWidth * imgHeight);

 

b. Otherwise, divide the

 

}

 

smaller of the display area

 

 

and the image size by the

 

 

total image area.

 

 

c. For simplicity, use integer

 

 

percent values.

 

 

 

 

4

Calculate the rectangular

// Calculate the rectangle to fill

 

region to fill.

Rectangle fillRect = sbdevent.Bounds;

 

 

fillRect.Width = sbdevent.Bounds.Width

 

How-to

* percent / 100;

 

Use the event’s Bounds

 

 

property and adjust its Width

 

 

based on the calculated

 

 

percent.

 

 

 

 

5

Draw this rectangle in the

// Draw the rectangle in the panel

 

panel.

sbdevent.Graphics.FillRectangle(

 

 

Brushes.SlateGray, fillRect);

 

How-to

Note: We could also have used the ForeColor prop-

 

a. Use the Graphics object

 

erty of the event as the color here. This code illus-

 

for the event.

trates using the Brushes class, which provides access

 

b. Paint the rectangle with the

to a Brush object for all standard colors available in the

 

FillRectangle method,

framework.

 

using a SlateGray brush.

 

 

 

 

6

Draw the percentage value in

// Draw the text on top of the rectangle

 

the panel.

sbdevent.Graphics.DrawString(

 

 

percent.ToString() + "%",

 

How-to

sbdevent.Font,

 

Use the DrawString

Brushes.White,

 

sbdevent.Bounds);

 

method for the Graphics

 

Note: White is a good color choice if used with the

 

object.

 

default desktop colors. It may not be a good choice if

 

 

 

 

custom desktop colors are used.

 

 

 

The complete code for this handler is shown as follows:

protected void statusBar1_DrawItem (object sender, StatusBarDrawItemEventArgs sbdevent)

{

if (sbdevent.Panel == sbpnlImagePercent)

122

CHAPTER 4 STATUS BARS

{

// Calculate the percent of the image shown int percent = 100;

if (pbxPhoto.SizeMode != PictureBoxSizeMode.StretchImage)

{

Rectangle dr = pbxPhoto.ClientRectangle; int imgWidth = pbxPhoto.Image.Width;

int imgHeight = pbxPhoto.Image.Height; percent = 100 * Math.Min(dr.Width, imgWidth)

* Math.Min(dr.Height, imgHeight) / (imgWidth * imgHeight);

}

//Calculate the rectangle to fill Rectangle percentRect = sbdevent.Bounds;

percentRect.Width = sbdevent.Bounds.Width * percent / 100;

//Draw the rectangle in the panel sbdevent.Graphics.FillRectangle(Brushes.SlateGray, percentRect);

//Draw the text on top of the rectangle sbdevent.Graphics.DrawString(percent.ToString() + "%",

sbdevent.Font, Brushes.White, sbdevent.Bounds);

}

}

The Graphics class used in this handler provides a rich set of drawing capabilities, from circles, ellipses, and rectangles to polygons, pie shapes, and bezier curves. Here we use the FillRectangle method, which requires a Brush object to use when “painting” the rectangle. In chapter 7, we will make additional use of this class. See

.NET Table 4.6 for an overview of some of the more interesting members of this class. It should be noted that the statusBar1_DrawItem handler is invoked each time a panel must be redrawn. As a result, care should be taken in handlers such as this to avoid expensive calculations or other operations that might adversely affect the performance of the application. For example, if we had generated a custom Brush object while filling the rectangle here, such an operation would be performed each time the handler is invoked, potentially using an excessive amount of memory over the life of the application. Of course, our choice of the SlateGray color might not be the best choice either, as it might interfere with colors the user has selected for their desktop. A better option here might be to determine a color programmatically based on the user’s desktop settings, and generate a single Brush object the first time the

event handler is invoked that is reused for the life of the application.

You can compile and run this code so far if you like, but we do need to make one more change. When the PictureBox.SizeMode property is StretchImage, the complete image (100%) is always shown. When SizeMode is set to Normal, the amount of image shown varies as the size of the client area changes. As a result, when the user changes this setting, we need to make sure that our panel is redrawn by invalidating the contents of the status bar.

OWNER-DRAWN PANELS

123

.NET Table 4.6 Graphics class

The Graphics class is a drawing object that encapsulates a drawing surface , or more specifically a graphical device interface (GDI+) drawing surface. This class is part of the System.Drawing namespace, and inherits from the System.MarshalByRefObject class. Drawing the outline of a shape typically requires a Pen object, while drawing a filled-in shape typically requires a Brush object.

This class contains a large number of members, but the list here should provide some idea of the supported functionality.

 

FromHdc

Returns a Graphics instance from a given handle

Public Static

 

to a device context.

 

 

Properties

FromHwnd

Returns a Graphics instance from a given

 

 

 

window handle.

 

 

 

 

Clip

Gets or sets as a Region object the portion of the

 

 

graphics area available for visible drawing.

 

DpiX

Gets the horizontal resolution supported by the

 

 

object.

 

DpiY

Gets the vertical resolution supported by the

Public Properties

 

object.

PageUnit

Gets or sets the GraphicsUnit value specifying

 

 

 

the unit of measure for page coordinates.

 

SmoothingMode

Gets or sets the SmoothingMode value indicating

 

 

how shapes are rendered with this object.

 

TextRenderingHint

Gets or sets the TextRenderingHint value

 

 

indicating how text is rendered with this object.

 

 

 

 

Clear

Fills the entire drawing surface with a specified

 

 

color.

 

DrawCurve

Draws a curve specified as an array of points using

 

 

a given Pen.

 

DrawEllipse

Draws the outline of an ellipse (which might be a

 

 

circle) bounded by a given rectangle using a given

 

 

Pen.

 

DrawLine

Draws a line using a given Pen.

Public Methods

DrawRectangle

Draws the outline of a rectangle using a given Pen.

 

 

 

FillClosedCurve

Fills the interior of a closed curve specified as an

 

 

array of points using a given Brush.

 

FillEllipse

Fills the interior of an ellipse (which might be a

 

 

circle) bounded by a given rectangle using a given

 

 

Brush.

 

FillRectangle

Fills the interior of a rectangle using a given

 

 

Brush.

 

MeasureString

Returns the size a given string would occupy using

 

 

a given Font.

 

 

 

124

CHAPTER 4 STATUS BARS