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

8.4.4UPDATING THE PIXELDLG FORM

So far we have created and displayed our form as a modeless dialog. In this section we will implement the code to update this dialog based on the current location of the mouse pointer in the pnlPhoto control. We will account for the fact that a photo might not be displayed, and that the mouse pointer may be located outside of the panel.

This code for UpdatePixelData is a bit long, so let’s get to it.

IMPLEMENT UPDATEPIXELDATA METHOD

 

Action

Result

 

 

 

1

In the MainForm.cs window, add

protected void UpdatePixelData

 

an UpdatePixelData method to

(int xPos, int yPos)

 

the end of the file.

{

 

 

 

 

 

2

Return immediately if the

if (_dlgPixel == null || !_dlgPixel.Visible)

 

PixelDlg does not exist or is not

return;

 

visible.

 

 

 

 

3

Get the currently display photo.

Photograph photo = _album.CurrentPhoto;

 

 

 

4

Display all zeros if a Photograph

Rectangle r = pnlPhoto.ClientRectangle;

 

is not displayed or the given

if (photo == null

 

coordinates are outside the

|| !(r.Contains(xPos,yPos)))

 

{

 

display area.

 

_dlgPixel.Text = ((photo == null)

 

Note: The question mark ‘?’ syn-

? " " : photo.Caption);

 

_dlgPixel.XVal = 0;

 

tax here works the same as in

 

_dlgPixel.YVal = 0;

 

C++.

_dlgPixel.RedVal = 0;

 

 

_dlgPixel.GreenVal = 0;

 

 

_dlgPixel.BlueVal = 0;

 

 

_dlgPixel.Update();

 

 

return;

 

 

}

 

 

 

5

Display the caption for the current

_dlgPixel.Text = photo.Caption;

 

image in the title bar of our dialog.

 

 

 

 

6

Use a switch statement to

// Calc x and y position in the photo

 

determine the current display

int x = 0, y = 0;

 

mode.

Bitmap bmp = photo.Image;

 

switch (this._selectedMode)

 

 

 

Note: The calculation here

{

 

depends on how the image is

 

 

displayed, so a switch state-

 

 

ment is required.

 

 

 

 

7

Implement the Actual Size display

case DisplayMode.ActualSize:

 

mode logic.

// Panel coords equal image coords

 

Note: In this mode, the display

x = xPos;

 

y = yPos;

 

area and image area are equiva-

break;

 

lent.

 

 

 

 

MODELESS DIALOGS

259

 

IMPLEMENT UPDATEPIXELDATA METHOD

(continued)

 

 

 

 

 

Action

 

Result

 

 

 

8

Implement the Stretch to Fit

case DisplayMode.StretchToFit:

 

display mode logic.

// Translate panel coords to image

 

Note: In this mode, the image

x = xPos * bmp.Width / r.Width;

 

y = yPos * bmp.Height / r.Height;

 

fills the entire display area, so we

break;

 

 

convert from display position to

 

 

 

image location.

 

 

 

 

 

9

Implement the Scale to Fit display

case DisplayMode.ScaleToFit:

 

mode logic.

// Determine image rectangle.

 

 

Rectangle r2 = photo.ScaleToFit(r);

 

How-to

if (!r2.Contains(xPos, yPos))

 

a. Calculate the rectangle contain-

 

return;

// Mouse outside image

 

ing the image using the

 

 

 

 

ScaleToFit method in the

// Translate r2 coords to image

 

Photograph class.

x = (xPos - r2.Left)

 

b. If the mouse pointer is outside

* bmp.Width / r2.Width;

 

y = (yPos - r2.Top)

 

this rectangle, it is not in the

* bmp.Height / r2.Height;

 

image.

break;

 

 

c. Otherwise, convert this rectan-

}

 

 

 

 

 

gle into image coordinates.

 

 

 

 

 

10

Retrieve the color of the pixel at

// Extract color at calculated location

 

the calculated image location.

Color c = bmp.GetPixel(x, y);

 

How-to

 

 

 

Use the Bitmap.GetPixel

 

 

 

method.

 

 

 

 

 

11

Finally, update the pixel dialog

// Update PixelDlg with new values

 

with the appropriate values.

_dlgPixel.XVal = x;

 

How-to

_dlgPixel.YVal = y;

 

_dlgPixel.RedVal = c.R;

 

For the RGB color values, use the

_dlgPixel.GreenVal = c.G;

 

R, G, and B properties in the

_dlgPixel.BlueVal = c.B;

 

_dlgPixel.Update();

 

Color structure.

 

}

 

 

 

 

 

And there you have it. This method updates the PixelDlg form each time it is called. Since the explanation of each step is embedded in the table, we will not discuss this code further.

Our final task is to make sure this method is called each time the mouse pointer moves or the displayed photograph changes.

8.4.5UPDATING PIXELDLG AS THE MOUSE MOVES

In the previous section we waded through the logic necessary to convert the current mouse pointer location in panel coordinates to the corresponding image coordinates to update the PixelDlg form correctly. Next, we need to ensure that UpdatePixelData is called whenever appropriate.

260

CHAPTER 8 DIALOG BOXES

The most obvious time is whenever the location of the mouse pointer changes. There is a MouseMove event inherited from the Control class for this purpose. The protected OnMouseMove method raises this event, so we could override OnMouseMove in our Form class. In this case, we would have to convert from Form coordinates to Panel coordinates, so handling the event for the Panel class is probably a better choice. More importantly, by handling mouse pointer movements in the Panel object directly, our code is only called when the movement occurs inside the panel.

CALL THE UPDATEPIXELDATA METHOD WHEN THE MOUSE MOVES

 

ACTION

RESULT

 

 

 

1

In the MainForm.cs

protected void pnlPhoto_MouseMove

 

[Design] window, add a

(object sender,

 

MouseMove event handler

System.Windows.Forms.MouseEventArgs e)

 

{

 

for the pnlPhoto object.

 

 

 

 

 

2

Call the UpdatePixelData

UpdatePixelData(e.X, e.Y);

 

method with the current

}

 

mouse pointer coordinates.

 

 

 

 

The MouseMove event handler receives a MouseEventArgs parameter containing, among other event data, an X and Y property defining the current coordinates of the mouse pointer in the control’s coordinates. We will discuss this and other mouse events in chapter 12, so we will not go into more detail on this handler here.

The one other instance when the pixel values must be updated is when the displayed image changes. The easiest place to track this is when the Panel is painted in the pnlPhoto_Paint method. Continuing the previous steps:

CALL UPDATEPIXELDATA WHEN CURRENT PHOTO CHANGES

 

Action

Result

 

 

 

3

Locate the pnlPhoto_Paint

protected void pnlPhoto_Paint(. . .)

 

method in the MainForm.cs

{

 

source file.

 

 

 

 

4

Call UpdatePixelData if a new

// Update PixelDlg if photo has changed

 

photo is displayed.

if ((_dlgPixel != null) && (_nPixelDlgIndex

 

 

!= _album.CurrentPosition))

 

 

{

 

 

_nPixelDlgIndex = _album.CurrentPosition;

 

 

Point p = pnlPhoto.PointToClient(

 

 

Form.MousePosition);

 

 

UpdatePixelData(p.X, p.Y);

 

 

}

 

 

// Paint the current photo, if any

 

 

if (_album.Count > 0)

 

 

{

 

 

. . .

 

 

}

 

 

}

 

 

 

MODELESS DIALOGS

261

This code uses the same Form.MousePosition method and nonstatic Panel.PointToClient we saw earlier in this section.

Our modeless dialog is finished. Compile your code, show your friends, and otherwise verify that the dialog works properly. Note how both the form and the dialog can be manipulated at the same time, and how the dialog behaves when you display the next or previous image in an album, with the mouse cursor both inside and outside the panel control.

TRY IT! One nice change you could make here is to modify the cursor used for the Panel control to use a small cross-hair rather than the normal arrow. Do this by changing the Cursor property for the Panel class to use the Cross cursor.

Another interesting change is to allow the user to hide the PixelDlg window using the main application’s menu bars. One way to do this is to modify the Text displayed for the menuPixelData menu to be “Hide Pi&xel Data” whenever the dialog is displayed and back to “Pi&xel Data” whenever the dialog is hidden or closed. Set the appropriate menu text in the menuView_Popup handler, and use the Hide method or the Visible property to hide the dialog.

Before we move on to the next topic, let’s give a quick summary of what we covered in this chapter.

8.5RECAP

In this chapter we looked at dialog boxes. We began with simple dialogs using the MessageBox class, and then created a custom modal dialog based on the Form class, followed by a custom modeless dialog. Along the way we discussed the difference between modal and modeless dialog boxes, caught potential exceptions when opening and saving our album files, examined the relationship between the Close and Dispose methods, saw how to intercept a closing window using the OnClosing method, and learned how to track the mouse pointer within a panel control.

We are not done with dialog boxes. Since our main form is getting rather full, future topics will require dialogs in order to continue this book and expand the capabilities of our program. In particular, the next chapter will create a dialog for both our current album and the individual photos in the album as a way to introduce specific Windows Forms controls in more detail.

262

CHAPTER 8 DIALOG BOXES

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