Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# ПІДРУЧНИКИ / c# / Manning - Windows.forms.programming.with.c#.pdf
Скачиваний:
108
Добавлен:
12.02.2016
Размер:
14.98 Mб
Скачать

UPDATE THE MENUIMAGE_CHILDCLICK METHOD TO USE THE NEW PANEL

 

Action

Result

 

 

 

3

Modify the code for the

case DisplayMode.ActualSize:

 

ActualSize display mode in a

SetStyle(ControlStyles.ResizeRedraw,

 

similar manner.

false);

 

pnlPhoto.AutoScroll = true;

 

 

 

 

pnlPhoto.Invalidate();

 

 

break;

 

 

. . .

 

 

}

 

 

 

That’s it for our menu handlers. The SetStyle method is a protected member and cannot be modified for our Panel class, so we just force the redraw to happen at the Form level as we did before. This will redraw the entire form and not just our panel, but it gets the job done. In this case, the drawing required outside of our panel is not overly complex, so this extra drawing should not be a problem.

On a more complex form, it would make sense to handle the Resize event for the pnlPhoto object instead of setting a form-level style as we do here. Handling the Resize event would allow us to only redraw the panel itself, and not the other parts of the Form.

The AutoScroll property is a public member of the ScrollableControl class, so we can set its value for the pnlPhoto object directly.

As you can see, because the Panel and Form classes are based on a similar class hierarchy, design changes like this are very easy to make in .NET. Let’s move on to our owner-drawn status bar.

7.4.3DRAWING THE STATUS BAR PANEL

Our status bar is drawn in the statusBar1_DrawItem method. This method must calculate the percentage of the image shown in the window. Since the image will now be displayed inside the Panel object, we must modify this routine to use the Panel client area rather than the MainForm one.

UPDATE THE STATUSBAR1_DRAWITEM METHOD TO USE THE PANEL

 

Action

Result

 

 

 

1

Locate the

protected void statusBar1_DrawItem

 

statusBar1_DrawItem

(object sender,

 

StatusBarDrawItemEventArgs sbdevent)

 

method in the

 

{

 

MainForm.cs file.

 

. . .

 

 

 

PANELS

219

UPDATE THE STATUSBAR1_DRAWITEM METHOD TO USE THE PANEL (continued)

 

Action

Result

 

 

 

2

Modify the calculation of

// Calculate percent of image shown

 

the percent variable to

int percent = 100;

 

use the panel rather than

if (_selectedMode == DisplayMode.ActualSize)

 

{

 

the form.

 

Photograph photo = _album.CurrentPhoto;

 

 

Rectangle dr = pnlPhoto.ClientRectangle;

 

 

int imgWidth = photo.Image.Width;

 

 

int imgHeight = photo.Image.Height;

 

 

percent = 100

 

 

* Math.Min(dr.Width, imgWidth)

 

 

* Math.Min(dr.Height, imgHeight)

 

 

/ (imgWidth * imgHeight);

 

 

}

 

 

. . .

 

 

}

 

 

 

Once again this change simply uses our private Panel field rather than the this keyword. Our last change is to draw the image inside the panel rather than on the form itself.

7.4.4DRAWING THE IMAGE

When drawing the image on the form, we were able to override the protected

OnPaint method that raises the Paint event. For the Panel object, we do not have access to protected members, so we must use the public Paint event to update the panel. Internally in the Windows Forms library, of course, the Panel control will use its own version of the OnPaint method to invoke our event handler.

ADD A PAINT HANDLER FOR THE PNLPHOTO OBJECT

 

Action

Result

 

 

 

1

Add a Paint event handler for the

Visual Studio generates the appropriate code in the

 

panel.

source file.

 

How-to

protected void pnlPhoto_Paint

 

Double-click the Panel control.

(object sender,

 

Note: The Paint event is the default

System.Windows.Forms.PaintEventArgs e)

 

{

 

event for the panel control in Visual

}

 

Studio. Other events can be added

 

 

via the Properties window.

 

 

 

 

Note that the Paint event handler receives a PaintEventArgs instance containing the event data. As we saw earlier in the chapter, this class contains the Graphics object for drawing inside the panel. Our code uses this object in the same way as when the image was drawn in the form. Continuing our previous steps:

220

CHAPTER 7 DRAWING AND SCROLLING

TRANSFER THE DRAWING CODE INTO THE NEW PAINT HANDLER

 

Action

Result

 

 

 

2

In the pnlPhoto_Paint method,

protected void pnlPhoto_Paint

 

use the given Graphics to draw

(object sender,

 

the image when the album is not

System.Windows.Forms.PaintEventArgs e)

 

{

 

empty.

 

if (_album.Count > 0)

 

 

{

 

 

// Paint the current photo

 

 

Photograph photo = _album.CurrentPhoto;

 

 

Graphics g = e.Graphics;

 

 

 

3

Copy the switch statement for

switch (_selectedMode)

 

drawing the image from the

{

 

existing OnPaint method.

. . .

 

}

 

 

 

 

}

 

 

else

 

 

{

 

 

// No image to paint

 

 

}

 

 

}

 

 

 

4

Update this switch block to use

switch (_selectedMode)

 

the pnlPhoto object as

{

 

appropriate.

default:

 

case DisplayMode.ScaleToFit:

 

 

 

 

// Preserve aspect ratio of image

 

 

g.DrawImage(photo.Image,

 

 

photo.ScaleToFit(

 

 

pnlPhoto.DisplayRectangle));

 

 

break;

 

 

case DisplayMode.StretchToFit:

 

 

// Fill entire panel with image

 

 

g.DrawImage(photo.Image,

 

 

pnlPhoto.DisplayRectangle);

 

 

break;

 

 

case DisplayMode.ActualSize:

 

 

// Draw portion of image

 

 

g.DrawImage(photo.Image,

 

 

pnlPhoto.AutoScrollPosition.X,

 

 

pnlPhoto.AutoScrollPosition.Y,

 

 

photo.Image.Width,

 

 

photo.Image.Height);

 

 

pnlPhoto.AutoScrollMinSize

 

 

= photo.Image.Size;

 

 

break;

 

 

}

 

 

 

5

If the album is empty, draw the

else

 

standard system control color

{

 

onto the panel.

// No image to paint

 

e.Graphics.Clear(SystemColors.Control);

 

 

 

 

}

 

 

}

 

 

 

PANELS

221

TRANSFER THE DRAWING CODE INTO THE NEW PAINT HANDLER (continued)

 

Action

Result

 

 

 

6

Remove the corresponding

The OnPaint method now looks as follows:

 

drawing code from the existing

protected override void OnPaint

 

OnPaint method.

 

(PaintEventArgs e)

 

 

{

 

 

if (_album.Count > 0)

 

 

{

 

 

// Paint the current image

 

 

Photograph photo = _album.CurrentPhoto;

 

 

// Update the status bar.

 

 

pnlFileName.Text = photo.Caption;

 

 

pnlFileIndex.Text

 

 

= String.Format("{0:#}/{1:#}",

 

 

_album.CurrentIndex+1,

 

 

_album.Count);

 

 

pnlImageSize.Text

 

 

= String.Format("{0:#} x {1:#}",

 

 

photo.Image.Width,

 

 

photo.Image.Height);

 

 

statusBar1.ShowPanels = true;

 

 

}

 

 

else

 

 

{

 

 

// Indicate the album is empty

 

 

statusBar1.Text = "No Photos in Album";

 

 

statusBar1.ShowPanels = false;

 

 

}

 

 

 

7

At the end of this method,

// Ensure contained controls are redrawn

 

invalidate the panel to ensure it is

pnlPhoto.Invalidate();

 

redrawn.

statusBar1.Invalidate();

 

base.OnPaint(e);

 

 

 

 

}

 

 

 

It may look like a lot of code, but the number of changes is actually quite small, as indicated by the few number of bolded lines. The program is all set now. Verify that your code compiles and runs properly. Change display modes, use different-sized images, and resize the form to observe the effect.

TRY IT! If you are feeling brave, try adding a Fit to Width menu item to the Image submenu. This should preserve the aspect ratio of the image by scaling the image to match the width of the panel window. You will need to add a FitToWidth enumeration value to the DisplayMode enumeration. Calculate the height using code similar to the Photograph.ScaleToFit method where the width is preserved. The tricky part is setting the pnlPhoto.AutoScrollMinSize property appropriately and drawing the image into this same rectangle.

7.5RECAP

This chapter has looked at some drawing and scrolling aspects of the Form class. In particular, we removed the PictureBox control from our application and learned

222

CHAPTER 7 DRAWING AND SCROLLING

how to draw our image directly onto the form. We used the protected OnPaint method and made use of the automated scroll bars inherited by the Form class to scroll our image. This did not work exactly as we wanted, so we modified our code to use the Panel class instead as a way to draw the image independent of the rest of the form.

The next chapter will continue our investigation of the Form class by looking at dialog boxes.

RECAP

223

Соседние файлы в папке c#