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

The .NET Framework defines a ControlStyles enumeration, summarized in

.NET Table 7.4, for customizing the behavior of a control. The values defined by this enumeration indicate how the control appears or responds in various situations related to desktop interaction with a user, and are useful for customizing the behavior of a Form or other custom control class.

The Control class provides a SetStyle method to set these styles, and a GetStyle method to retrieve the current setting for these styles. These methods are protected, so you must inherit from an existing control in order to modify these styles.

For our purposes, you may have noticed the ResizeRedraw style, which we can use to force our application to redraw itself every time the user resizes the window.

 

FORCE THE FORM TO REDRAW WHEN RESIZED

 

 

 

 

Action

Result

 

 

 

1

Locate the

protected void menuImage_ChildClick

 

menuImage_ChildClick

(object sender, System.EventArgs e)

 

{

 

method in the

 

. . .

 

MainForm.cs source file.

 

 

 

 

 

2

Modify the logic when the

switch (_selectedMode)

 

display mode is

{

 

ScaleToFit or

default:

 

case DisplayMode.ScaleToFit:

 

StretchToFit to force a

 

case DisplayMode.StretchToFit:

 

redraw whenever the form

SetStyle(ControlStyles.ResizeRedraw,

 

resizes.

true);

 

 

Invalidate();

 

 

break;

 

 

. . .

 

 

}

 

 

. . .

 

 

}

 

 

Note: Since the logic is the same for these two modes,

 

 

we have merged these two case labels into a single

 

 

block. C# allows a case label to fall through to the next

 

 

label only if it has no code associated with it.

 

 

 

We will make one other change here before testing our program. When the program begins, the ResizeRedraw style is not set to true. Only after the user makes a selection will this style be set appropriately. A simple solution would be to set the ResizeRedraw style in the constructor for our form. This works, but does not account for any future changes to the menuImage_ChildClick method. Since such changes will occur in the next section, a more robust solution is to simulate an Image menu selection directly from the constructor.

Simulating a call to an event handler during control initialization is a good way to ensure that future changes to the handler are dealt with during initialization. It also allows you to make such changes in only one place. We did this in the previous chapter for the New menu. Let’s do this here by continuing the previous steps.

IMAGE DRAWING

211

SIMULATE AN IMAGE MENU CLICK IN MAINFORM CONSTRUCTOR

 

Action

Result

 

 

 

3

Locate the MainForm

public MainForm()

 

constructor in the

{

 

MainForm.cs source

. . .

 

 

 

window.

 

 

 

 

4

Add a call to

menuImage_ChildClick(menuScale,

 

menuImage_ChildClick

EventArgs.Empty);

 

}

 

in this constructor.

 

 

 

How-to

Note: This call must occur after the InitializeCompo-

 

nent method has been called to ensure that the menu

 

a. Use the menuScale

 

objects have been initialized.

 

menu as the sender

 

 

 

parameter.

 

 

b. Use EventArgs.Empty

 

 

for the event parameter.

 

 

 

 

Now you can compile and run the application to see the amazing ResizeRedraw style in action. This code uses the static EventArgs.Empty property we saw in chapter 6 to provide a valid, albeit empty, event argument to the handler.

TRY IT! If you are tired of reading, modify your code to use the Resize event instead of the ResizeRedraw control style. This change reduces the processing required when an Image submenu item is selected, at the expense of additional processing whenever the window is resized. Do this by overriding the OnResize method for the form, and use the _selectedMode field to invalidate the window as required.

Another change you can make is to modify the form to do double buffering. This removes the flicker that currently occurs when resizing the image. To do this, use the following code in the menuImage_ChildClick method:

SetStyle(ControlStyles.UserPaint, true);

SetStyle(ControlStyles.DoubleBuffer, true);

SetStyle(ControlStyles.AllPaintingInWmPaint, true);

This completes the drawing of an image within the window. While we have lost our border, we are now able to draw the image in our window using either the Stretch to Fit or Scale to Fit display options. Our next task is to handle the Actual Size menu to draw the full-sized image in the window. This requires the use of scroll bars and will lead us into a discussion of the Panel class.

7.3AUTOMATED SCROLLING

The implementation of the Actual Size menu option allows us to look at the ScrollableControl class in more detail. As we have seen, the actual image is often larger than the form’s client area. In chapter 3, the PictureBox control did not support

212

CHAPTER 7 DRAWING AND SCROLLING

scrolling and we could only view the rest of the image by resizing the form. Here, we will use scroll bars via the ScrollableContainer class members to provide a more appropriate solution.

The result of our labors is shown in figure 7.4. As you can see, part of the image is shown, and scroll bars at the right and bottom of the image can be used to scroll to the remainder of the image. These scroll bars will appear and disappear automatically as needed. You may wonder where our status bar has gone. This is an unfortunate side effect drawing directly on our form, and is the reason a section 7.4 exists in this chapter. More on this later.

Figure 7.4

The scroll bars for the form appear automatically when the display area is larger than the client area.

7.3.1PROPERTIES FOR SCROLLING

We already have the Actual Size menu available, but we need to add the appropriate processing when this menu is clicked and in the OnPaint method. Before we write any code, let’s consider which properties we need from the ScrollableControl class.

ScrollableControl properties for scrolling our image

Property

Purpose

 

 

AutoScroll

Whether scrolling is enabled. We will set this to true for the Actual Size

 

mode, and false for other display modes.

AutoScrollMinSize

The minimum size for the scrollable window. This is the display size, and not

 

the actual client size seen by the user. We will set this to the size of the

 

current image to ensure that the scroll bars are sized appropriately for this

 

image.

AutoScrollPosition

The window position, in pixels, at the upper left corner of the window. This

 

property is adjusted automatically as the window scrolls.

 

 

7.3.2IMPLEMENTING AUTOMATED SCROLLING

Now that we have reviewed some of the properties used for automated scrolling, we can tackle the code required for the ActualSize display mode. We will start with the menu click, and handle the painting of the image in a moment.

AUTOMATED SCROLLING

213

When the user clicks the ActualSize display mode, we need to adjust not just the Actual Size display mode, but also our Scale to Fit and Stretch to Fit menus to ensure that scrolling is disabled when these modes are set. The following steps detail the changes required.

Set the version number of the MyPhotos application to 7.3.

MODIFY MENUIMAGE_CHILDCLICK FOR ACTUALSIZE DISPLAY MODE

 

Action

Result

 

 

 

1

Locate the menuImage_ChildClick

protected void menuImage_ChildClick

 

method in the MainForm.cs source

(object sender, System.EventArgs e)

 

window.

{

 

. . .

 

 

 

 

 

2

Turn scrolling off for the ScaleToFit

switch (_selectedMode)

 

and StretchToFit display modes.

{

 

 

default:

 

 

case DisplayMode.ScaleToFit:

 

 

case DisplayMode.StretchToFit:

 

 

// Display entire image in window

 

 

AutoScroll = false;

 

 

SetStyle(ControlStyles.ResizeRedraw,

 

 

true);

 

 

. . .

 

 

 

3

Turn scrolling on for the ActualSize

case DisplayMode.ActualSize:

 

display mode.

// Display image at actual size

 

 

AutoScroll = true;

 

How-to

SetStyle(ControlStyles.ResizeRedraw,

 

a. Set AutoScroll to true.

false);

 

Invalidate();

 

b. Turn off the ResizeRedraw style

break;

 

}

 

for the form.

 

. . .

 

 

 

 

}

 

 

 

Note here that we did not set AutoScrollMinSize to the size of the current image. Since different images may have different sizes, we will need to adjust this setting whenever the current image changes. One way to do this would be to modify this setting in all the places where the current image changes. This would include the Next, Previous, and Remove menu handlers, and possibly other locations in the future as well. That’s a lot to keep track off. Instead, we will set this property when the image is painted so that it is updated by default whenever the image changes.

For the Paint operation itself, another version of the Graphics.DrawImage method is used to account for drawing the image into a space larger than the client area. The DrawImage method has a number of overloads to handle various types of drawing. See the documentation for the complete list.

214

CHAPTER 7 DRAWING AND SCROLLING