How the drawing changes
You will notice that the Draw method is basically the same as the base class-the main difference is that it calls the Fill method, because it needs to be filled to complete the painting of a Fill object. Instead of overwriting the code for drawing the outline, we call the method of the base class again: MyBase. Draw (g) in Visual Basic. NET or base. Draw (g) in C );.
Because we are assigning a pen to draw the outline, we need to use using or Try/Finally and Dispose to ensure that Windows pen objects are quickly released. (Similarly, if you are very sure that the called method will not cause an exception, you can skip the Exception Processing after completing the processing, and only call Dispose. However, we must call Dispose, whether it is a direct call or a using statement.
Fill Implementation Method
The Fill method is simple: assign a paint brush, then Fill the object on the screen -- and make sure that the Dispose paint brush.
Note that in Visual Basic. NET, you must specify the method to implement an interface (... implements IFillable. in C #, the method or attribute in the implementation interface is determined by the signature of the method or attribute (because you have compiled a method called Fill, this method does not return any content and accepts a Graphics, so it must be IFillable. fill implementation ). Very strange, Dr. GUI usually prefers a concise programming structure (if it is not possible to simply write it), but actually tends to use the Visual Basic syntax, this syntax is clear and flexible (the method names in the Visual Basic implementation class do not need to match the names in the interface, and a given method can usually implement multiple interface methods ).
Implementation attributes
The IFillable interface also contains an attribute from which you can set and get paint colors. (This attribute is used in the Change fills to hot pink [Change fill color to pink] button handler .)
To implement public attributes, we need a private or protected field. Here we have selected a protected field to facilitate access to it from a derived class (without any class.
With this field, we can easily compile a simple set and get method pair to implement attributes.
Note that in Visual Basic. NET, you must specify the implemented attributes explicitly.
Interface or abstract (MustInherit) base class?
In object-oriented programming, one of the most common arguments is whether abstract base classes or interfaces are used.
The interface can provide some extra flexibility, but it also has to pay a certain price: for each class implementing this interface, all the content must be implemented. We can use a helper class to assist in this work (a related example will be provided later), but you still have to implement everything in all places. And interfaces cannot contain data (though, unlike in Brand J systems, they can contain attributes, so they can seem to contain data ).
In this example, Dr. GUI selects an abstract base class instead of an interface for DShape, because he does not want to implement data as attributes repeatedly in each class. In addition, because all content derived from DShape is a shape, it can also be filled because the object that can be filled is still a shape.
Your selection may be different, but Dr. GUI thinks that he has made a very correct choice here.
Container of the Drawing Object
Because we need to repeat the rendering of our objects (in Windows Forms, the image will be drawn each time; in ASP. in the. NET version, Web pages are reloaded every time. Therefore, you need to put them in a container so that they can be accessed repeatedly.
The Dr. GUI goes further and makes containers intelligent so that they know how to draw the contained objects. The C # code of this container class is as follows:
C #
Public class DShapeList {
ArrayList wholeList = new ArrayList ();
ArrayList filledList = new ArrayList ();
Public void Add (DShape d ){
WholeList. Add (d );
If (d is IFillable)
FilledList. Add (d );
}
Public void DrawList (Graphics g ){
If (wholeList. Count = 0)
{
Font f = new Font ("Arial", 10 );
G. DrawString ("NO content to be drawn; the list is empty ...",
F, Brushes. Gray, 50, 50 );
}
Else
{
Foreach (DShape d in wholeList)
D. Draw (g );
}
}
Public IFillable [] GetFilledList (){
Return (IFillable []) filledList. ToArray (typeof (IFillable ));
}
}
Similar Visual Basic. NET code is as follows:
Visual Basic
. NET Public Class DShapeList
Dim wholeList As New ArrayList ()
Dim filledList As New ArrayList ()
Public Sub Add (ByVal d As DShape)
WholeList. Add (d)
If TypeOf d Is IFillable Then filledList. Add (d)
End Sub
Public Sub DrawList (ByVal g As Graphics)
If wholeList. Count = 0 Then
Dim f As New Font ("Arial", 10)
G. DrawString ("NO content to be drawn; the list is empty ...",_
F, Brushes. Gray, 50, 50)
Else
Dim d As DShape
For Each d In wholeList
D. Draw (g)
Next
End If
End Sub
Public Function GetFilledList () As IFillable ()
Return filledList. ToArray (GetType (IFillable ))
End Function
End Class