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

Beginning Visual Basic 2005 (2006)

.pdf
Скачиваний:
226
Добавлен:
17.08.2013
Размер:
14.97 Mб
Скачать

Chapter 14

Responding to Clicks

Your control is going to fire an event whenever the left or right mouse button is clicked on a color button. To that end, in the next Try It Out you add some events to your ColorPalette control that the control will raise. The application using this control will be able to add the event handlers and take action when the event has been raised by this control.

Try It Out

Responding to Clicks

1.Go back to the Code Editor for ColorPalette. Add these events to the top of the class after your public members:

‘Public events

Public Event LeftClick(ByVal sender As Object, ByVal e As EventArgs) Public Event RightClick(ByVal sender As Object, ByVal e As EventArgs)

2.You need a general-purpose method that will return the button that’s positioned directly beneath the mouse. Add this method:

Public Function GetButtonAt(ByVal x As Integer, ByVal y As Integer) _ As ColorPaletteButton

‘Set the default return value GetButtonAt = Nothing

‘Go through each button in the collection

For Each objColorPaletteButton As ColorPaletteButton In Buttons ‘Is this button in the rectangle?

If objColorPaletteButton.Rectangle.Contains(x, y) Then Return objColorPaletteButton

End If

Next

End Function

3.Now, select (ColorPalette Events) in the Class Name combo box and then select the MouseUp event in the Method Name combo box. Your motivation for using MouseUp rather than MouseDown will become apparent soon. Add this highlighted code to the event handler:

Private Sub ColorPalette_MouseUp(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

‘Find the button that we clicked

Dim objColorPaletteButton As ColorPaletteButton = GetButtonAt(e.X, e.Y)

If Not objColorPaletteButton Is Nothing Then

‘Was the left button clicked

If e.Button = MouseButtons.Left Then

‘Set the color

LeftColor = objColorPaletteButton.Color

‘Raise the event

446

Programming Custom Graphics

RaiseEvent LeftClick(Me, New EventArgs())

ElseIf e.Button = MouseButtons.Right Then

‘Set the color

RightColor = objColorPaletteButton.Color

‘Raise the event

RaiseEvent RightClick(Me, New EventArgs())

End If

End If

End Sub

4.To test the new method, open the Forms Designer for Form1. Select the PaintCanvas control and set its Name property to Canvas.

5.Now open up the Code Editor for Form1. Select paletteColor in the Class Name combo box, and select the LeftClick event in the Method Name combo box. Add this highlighted code to the event handler:

Private Sub paletteColor_LeftClick(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles paletteColor.LeftClick

Canvas.GraphicColor = paletteColor.LeftColor

End Sub

6.Now run your project. You should be able to use the color palette to change the color laid down by the left mouse button.

How It Works

Although you’ve called your buttons ColorPaletteButton, they don’t behave in the way you’re used to seeing buttons behave. Button controls, like the ones you have been using until now, have the intelligence to detect when they’ve been clicked and fire an event to tell you what happened. Your color palette buttons, on the other hand, have until now been areas on the control painted in a pretty color. Now you actually need to write the logic to determine when a button is clicked.

The key to this is the GetButtonAt method. This method takes a set of client coordinates and returns the ColorPaletteButton object that contains the point you asked for. In this case, you use the Contains method of the Rectangle object to see whether the coordinates are contained within the rectangle.

Public Function GetButtonAt(ByVal x As Integer, ByVal y As Integer) _ As ColorPaletteButton

‘Set the default return value GetButtonAt = Nothing

‘Go through each button in the collection

For Each objColorPaletteButton As ColorPaletteButton In Buttons ‘Is this button in the rectangle?

447

Chapter 14

If objColorPaletteButton.Rectangle.Contains(x, y) Then

Return objColorPaletteButton

End If

Next

End Function

Of course, it could be the case that there is no button under the coordinates if the user clicks the mouse on a blank area of the control. If this is the case, GetButtonAt will return Nothing:

As you know, the Button property of MouseEventArgs tells you which button was used, or in this case, released. If it’s the left button, you update LeftColor and raise the LeftClick event:

Private Sub ColorPalette_MouseUp(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

‘Find the button that we clicked

Dim objColorPaletteButton As ColorPaletteButton = GetButtonAt(e.X, e.Y)

If Not objColorPaletteButton Is Nothing Then

‘Was the left button clicked

If e.Button = MouseButtons.Left Then

‘Set the color

LeftColor = objColorPaletteButton.Color

‘Raise the event

RaiseEvent LeftClick(Me, New EventArgs())

Alternatively, it could be the right mouse button:

ElseIf e.Button = MouseButtons.Right Then

‘Set the color

RightColor = objColorPaletteButton.Color

‘Raise the event

RaiseEvent RightClick(Me, New EventArgs())

End If

End If

End Sub

At the moment, PaintCanvas can deal with only one color, which is why you’ve only hooked up the LeftClick event. When you receive this event, you set the appropriate property on Canvas, and this new color will be used when creating new GraphicsCircle objects:

Private Sub paletteColor_LeftClick(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles paletteColor.LeftClick

Canvas.GraphicColor = paletteColor.LeftColor

End Sub

448

Programming Custom Graphics

Dealing with Two Colors

In the next Try It Out you extend PaintCanvas so that it can deal with two colors. You’ll do this by adding two public members that will track the color chosen for the left mouse button and the right mouse button. You’ll also be modifying your existing code to determine whether the left mouse button was clicked or whether the right mouse button was clicked.

Try It Out

Dealing with Two Colors

1.You need an additional property in PaintCanvas that will let you store the alternative color. For the sake of clarity, you’ll also change the name of the existing GraphicColor property to GraphicLeftColor. Open the Code Editor for the PaintCanvas class and make these changes:

‘Public members

Public GraphicsItems As New ArrayList()

Public GraphicTool As GraphicTools = GraphicTools.CirclePen Public GraphicSize As GraphicSizes = GraphicSizes.Medium

Public GraphicLeftColor As Color = Color.Black

Public GraphicRightColor As Color = Color.White

2.In the DoMousePaint method you need to examine the Button property of MouseEventArgs to determine which color you want to use. Make these two changes to DoMousePaint as highlighted:

Private Sub DoMousePaint(ByVal e As MouseEventArgs) ‘Store the new item somewhere

Dim objGraphicsItem As GraphicsItem

‘What color do we want to use?

Dim objColor As Color = GraphicLeftColor

If e.Button = MouseButtons.Right Then objColor = GraphicRightColor

End If

‘What tool are you using? Select Case GraphicTool

‘Circlepen

Case GraphicTools.CirclePen

‘Create a new graphics circle

Dim objGraphicsCircle As New GraphicsCircle()

‘Set the point for drawing

objGraphicsCircle.SetPoint(e.X, e.Y, GraphicSize, _ objColor, True)

‘Store this for addition objGraphicsItem = objGraphicsCircle

449

Chapter 14

End Select

‘Were you given an item?

If objGraphicsItem IsNot Nothing Then

‘Add it to the list GraphicsItems.Add(objGraphicsItem)

‘Invalidate the Control

Me.Invalidate(objGraphicsItem.Rectangle)

End If

End Sub

3.At the moment, MouseDown and MouseMove events will call DoMousePaint only if the left button is pressed. You need to change this so that it will accept either the left or right button. Make these changes as highlighted:

Private Sub PaintCanvas_MouseDown(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

‘Is the left or right mouse button down?

If e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right Then DoMousePaint(e)

End If End Sub

Private Sub PaintCanvas_MouseMove(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

‘Is the left or right mouse button down?

If e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right Then DoMousePaint(e)

End If End Sub

4.Next, you need to change the event handler in Form1 to set the GraphicLeftColor property rather than the GraphicColor property. Open the Code Editor for Form1 and make this change as highlighted:

Private Sub paletteColor_LeftClick(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles paletteColor.LeftClick

Canvas.GraphicLeftColor = paletteColor.LeftColor

End Sub

5.Finally, you need to add an event handler for the RightClick event. Select paletteColor in the Class Name combo box and the RightClick event in the Method Name combo box. Add this highlighted code:

Private Sub paletteColor_RightClick(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles paletteColor.RightClick

Canvas.GraphicRightColor = paletteColor.RightColor

End Sub

450

Programming Custom Graphics

Now, if you run the project, you should be able to assign different colors to the left and right mouse buttons and use both of the buttons to paint on the form.

Indicating the Assigned Buttons

You’ve no doubt noticed that, at this point, using WroxPaint is a little confusing. There’s no indication as to which color is assigned to which button. You need to resolve this issue, so in the next Try It Out you’ll display the letter L on the color assigned to the left button and the letter R on the color assigned to the right button.

Try It Out

Indicating the Assigned Buttons

1.First, you’ll make the ColorPaletteButton objects aware of which button they’re assigned to, if any. Open the Code Editor for the ColorPaletteButton class and add this enumeration to the top of the class:

Public Class ColorPaletteButton

‘Public enumerations

Public Enum ButtonAssignments As Integer None = 0

LeftButton = 1

RightButton = 2

End Enum

2.Next, add this new member (highlighted), which will keep track of the button’s assignment:

‘Public members

Public Color As Color = System.Drawing.Color.Black Public Rectangle As Rectangle

Public ButtonAssignment As ButtonAssignments = ButtonAssignments.None

3.After the button has a way of storing what it’s assigned to, you can change the Draw method to draw the L or R as appropriate. Add the following highlighted code to Draw:

‘Draw the button

Public Sub Draw(ByVal graphics As Graphics) ‘Draw the color block

Dim objSolidBrush As New SolidBrush(Color) graphics.FillRectangle(objSolidBrush, Rectangle)

‘Draw an edge around the control

Dim objPen As New Pen(System.Drawing.Color.Black) graphics.DrawRectangle(objPen, Rectangle)

‘Are you selected?

If ButtonAssignment <> ButtonAssignments.None Then

‘Create a font

Dim objFont As New Font(“verdana”, 8, FontStyle.Bold)

‘Set the default button assignment Dim strButtonText As String = “L”

451

Chapter 14

‘Update the button assignment if necessary

If ButtonAssignment = ButtonAssignments.RightButton Then strButtonText = “R”

End If

‘What brush do you want?

If Color.R < 100 Or Color.B < 100 Or Color.G < 100 Then objSolidBrush = New SolidBrush(System.Drawing.Color.White)

Else

objSolidBrush = New SolidBrush(System.Drawing.Color.Black)

End If

‘Draw the text ‘L’ or ‘R’ graphics.DrawString(strButtonText, objFont, objSolidBrush, _

Rectangle.Left, Rectangle.Top)

End If End Sub

4.To keep track of which button is selected, you need to add some private members to the ColorPalette class. Open the Code Editor for this class and add this code:

‘Private members

Private LeftButton As ColorPaletteButton Private RightButton As ColorPaletteButton

5.The next wrinkle you have to fix is quite verbose but relatively straightforward. Basically, you have to make sure that a button cannot be assigned to both the left and right buttons — for no other reason than that you just don’t have a way of reporting that information to the user. Also, you have to muddle with the invalidation code. You’ll detail that once you have the example working. Make these changes to ColorPalette_MouseUp as highlighted:

Private Sub ColorPalette_MouseUp(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

‘Find the button that we clicked

Dim objColorPaletteButton As ColorPaletteButton = GetButtonAt(e.X, e.Y)

If Not objColorPaletteButton Is Nothing Then

‘Was the left button clicked

If e.Button = MouseButtons.Left Then

‘Make sure that this button is not the current right button

If objColorPaletteButton IsNot RightButton Then

‘Set the color

LeftColor = objColorPaletteButton.Color

‘Clear the existing selection. If LeftButton IsNot Nothing Then

LeftButton.ButtonAssignment = _

ColorPaletteButton.ButtonAssignments.None

452

Programming Custom Graphics

Me.Invalidate(LeftButton.Rectangle)

End If

‘Mark the button objColorPaletteButton.ButtonAssignment = _

ColorPaletteButton.ButtonAssignments.LeftButton

Me.Invalidate(objColorPaletteButton.Rectangle)

LeftButton = objColorPaletteButton

‘Raise the event

RaiseEvent LeftClick(Me, New EventArgs())

End If

ElseIf e.Button = MouseButtons.Right Then

‘Make sure this button is not the current left button

If objColorPaletteButton IsNot LeftButton Then

‘Set the color

RightColor = objColorPaletteButton.Color

‘Clear the existing selection

If RightButton IsNot Nothing Then

RightButton.ButtonAssignment = _

ColorPaletteButton.ButtonAssignments.None

Me.Invalidate(RightButton.Rectangle)

End If

‘Mark the button objColorPaletteButton.ButtonAssignment = _

ColorPaletteButton.ButtonAssignments.RightButton

Me.Invalidate(objColorPaletteButton.Rectangle)

RightButton = objColorPaletteButton

‘Raise the event

RaiseEvent RightClick(Me, New EventArgs()) End If

End If

End If

End Sub

453

Chapter 14

6.Finally, you have to set up the first two colors added to the control as being the selected buttons when the control is started. This involves updating your leftButton and rightButton members as well as setting the ButtonAssignment property on the button itself. Add the highlighted code to AddColor:

‘Add a new color button to the control Public Sub AddColor(ByVal newColor As Color)

‘Create the button

Dim objColorPaletteButton As New ColorPaletteButton(newColor)

‘Add it to the list Buttons.Add(objColorPaletteButton)

‘Do we have a button assigned to the left button yet? If LeftButton Is Nothing Then

objColorPaletteButton.ButtonAssignment = _ ColorPaletteButton.ButtonAssignments.LeftButton

LeftButton = objColorPaletteButton

ElseIf RightButton Is Nothing Then ‘How about the right button?

objColorPaletteButton.ButtonAssignment = _ ColorPaletteButton.ButtonAssignments.RightButton

RightButton = objColorPaletteButton

End If

End Sub

7.Run the project now, and you should see that when you change the color selection, an L and R appear on the buttons, as shown in Figure 14-4.

Figure 14-4

454

Programming Custom Graphics

How It Works

The first thing you did was add an enumeration to the ControlPaletteButton class that could be used to set the state of the button:

‘Public enumerations

Public Enum ButtonAssignments As Integer None = 0

LeftButton = 1

RightButton = 2 End Enum

As you can see from the enumeration, a palette button can either be assigned to no mouse buttons, the left mouse button, or the right mouse button. You also added members to the ControlPalette class to keep track of which button was selected. This makes your life a little easier when it comes to changing the selection. When you select a new palette button, you have to set the ButtonAssignment property of the old button to ButtonAssignments.None. Just being able to look in the LeftButton or RightButton member, as appropriate, saves you from having to look through the entire list of buttons to find the one you need to change. The ColorPalette_MouseUp method starts to look a little more complex when you add this new functionality. When you want to assign the left mouse button to a palette button, you have to make sure that the palette button is not already assigned to the right mouse button:

Private Sub ColorPalette_MouseUp(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

‘Find the button that we clicked

Dim objColorPaletteButton As ColorPaletteButton = GetButtonAt(e.X, e.Y)

If Not objColorPaletteButton Is Nothing Then

‘Was the left button clicked

If e.Button = MouseButtons.Left Then

‘Make sure that this button is not the current right button If objColorPaletteButton IsNot RightButton Then

If you can set the color, you update the LeftColor property as you did before:

‘Set the color

LeftColor = objColorPaletteButton.Color

If another button is already assigned to the left mouse button, you need to set its ButtonAssignment property back to None. You also have to invalidate this button so that the button is redrawn and the L is removed:

‘Clear the existing selection. If LeftButton IsNot Nothing Then

LeftButton.ButtonAssignment = _

ColorPaletteButton.ButtonAssignments.None

Me.Invalidate(LeftButton.Rectangle)

End If

455