Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 115 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
115
Dung lượng
1,73 MB
Nội dung
Petroutsos c11.tex V2 - 01/28/2008 1:36pm Page 425 WHO CAN INHERIT WHAT? 425 structure of Method4. It has no code, and the End Function statement is missing. Method4 is declared with the MustOverride keyword, so you can’t instantiate an object of the ParentClass type. A class that contains even a single member marked as MustOverride must also be declared as MustInherit. Place a button on the class’s test form, and in its code window attempt to declare a variable of the ParentClass type. VB will issue a warning that you can’t create a new instance of a class declared with the MustInherit keyword. Because of the MustInherit keyword, you must create a derived class. Enter the lines from Listing 11.12 in the ParentClass module after the end of the existing class. Listing 11.12: Derived Class Public Class DerivedClass Inherits ParentClass Overrides Function Method4() As String Return (”I’m the derived Method4”) End Function Public Function newMethod() As String Console.WriteLine(”<This is the derived Class’s newMethod ” & ”calling Method2 of the parent Class> ”) Console.WriteLine(” ” & MyBase.Method2()) End Function End Class The Inherits keyword determines the parent class. This class overrides the Method4 member and adds a new method to the derived class: newMethod. If you switch to the test form’s code window, you can now declare a variable of the DerivedClass type: Dim obj As DerivedClass This class exposes all the members of ParentClass except for the Method2 method, which is declared with the Protected modifier. Notice that the newMethod() function calls this method through the MyBase keyword and makes its functionality available to the application. Normally, we don’t expose Protected methods and properties through the derived class. Let’s remove the MustInherit keyword from the declaration of the ParentClass class. Because it’s no longer mandatory that the ParentClass be inherited, the MustInherit keyword is no longer a valid modifier for the class’ members. So, Method4 must be either removed or implemented. Let’s delete the declaration of the Method4 member. Because Method4 is no longer a member of the ParentClass, you must also remove the entry in the DerivedClass that overrides it. MyBase and MyClass The MyBase and MyClass keywords let you access the members of the base class and the derived class explicitly. To see why they’re useful, edit the ParentClass, as shown here: Public Class ParentClass Public Overridable Function Method1() As String Return (Method4()) Petroutsos c11.tex V2 - 01/28/2008 1:36pm Page 426 426 CHAPTER 11 WORKING W ITH OBJECTS End Function Public Overridable Function Method4() As String Return (”I’m the original Method4”) End Function Override Method4 in the derived class, as shown here: Public Class DerivedClass Inherits ParentClass Overrides Function Method4() As String Return(”Derived Method4”) End Function Switch to the test form, add a button, declare a variable of the derived class, and call its Method4: Dim objDerived As New DerivedClass() Debug.WriteLine(objDerived.Method4) What will you see if you execute these statements? Obviously, the string Derived Method4. So far, all looks reasonable, and the class behaves intuitively. But what if we add the following method in the derived class? Public Function newMethod() As String Return (Method1()) End Function This method calls Method1 in the ParentClass class because Method1 isnotoverriddeninthe derived class. Method1 in the base class calls Method4.ButwhichMethod4 gets invoked? Sur- prised? It’s the derived Method4! To fix this behavior (assuming you want to call the Method4 of the base class), change the implementation of Method1 to the following: Public Overridable Function Method1() As String Return (MyClass.Method4()) End Function If you run the application again, the statement Console.WriteLine(objDerived.newMethod) will print this string: I’m the original Method4 Is it reasonable for a method of the base class to call the overridden method? It is reasonable because the overridden class is newer than the base class, and the compiler tries to use the newest members. If you had other classes inheriting from the DerivedClass class, their members would take precedence. Petroutsos c11.tex V2 - 01/28/2008 1:36pm Page 427 WHO CAN INHERIT WHAT? 427 Use the MyClass keyword to make sure that you’re calling a member in the same class, and not an overriding member in an inheriting class. Likewise, you can use the keyword MyBase to call the implementation of a member in the base class, rather than the equivalent member in a derived class. MyClass is similar to MyBase, but it treats the members of the parent class as if they were declared with the NotOverridable keyword. The Class Diagram Designer Classes are quite simple to build and use, and so is OOP. There are even tools to help you design and build your classes, which I’ll describe briefly here. You can use the Class Diagram Designer to build your classes with point-and-click operations, but you can’t go far on this tool alone. The idea is that you specify the name and the type of a property, and the tool emits the Get and Set procedures for the property (the getters and setters, as they’re known in OOP jargon). The default implementation of setters and getters is trivial, and you’ll have to add your own validation code. You can also create new methods by specifying their names and arguments, but the designer won’t generate any code for you; you must implement the methods yourself. Tools such as the Class Diagram Designer or Visio allow you to visualize the classes that make up a large project and the relations between them, and they’re a necessity in large projects. Many developers, however, build applications of substantial complexity without resorting to tools for automating the process of building classes. You’re welcome to explore these tools, however. Right-click the name of a class in Solution Explorer and choose View Class Diagram from the context menu. You’ll see a diagram of the class on the design surface, showing all the members of the class. You can add new members, select the type of the properties, and edit existing members. The diagram of a trivial class like the Contact class is also trivial, but the class diagram becomes more helpful as you implement more interrelated classes. Figure 11.2, from earlier in the chapter, shows the Product, Book, and Supply classes in the Class Diagram Designer. You can use the commands of each class’s context menu to create new members and edit/remove existing ones. To add a new property, for example, you specify the property’s name and type, and the designer generates the outline of the Set and Get procedures for you. Of course, you must step in and insert your custom validation code in the property’s setter. To add a new class to the diagram, right-click on the designer’s surface and choose Add Class from the context menu. You’ll be prompted to enter the name of the class and its location: the VB file in which the autogenerated class’s code will be stored. You can specify a new name, or select the file of an existing class and add your new class to it. To create a derived class, you must double-click the box that represents the new class and manually insert the Inherits statement followed by the name of the base class. After you specify the parent class, a line will be added to the diagram joining the two classes. The end of the line at the parent class has an arrow. In other words, the arrow points to the parent class. In addition to classes, you can add other items, includ- ing structures, enumerations, and comments. Experiment with the tools of the Class Diagram Designer to jumpstart the process of designing classes. You can also create class diagrams from existing classes. At the very least, you should use this tool to document your classes, especially in a team environment. To add members to a class, right-click the box that represents the class and choose Add from the context menu. This will lead to a submenu with the members you can add to a class: Method, Property, Field, and Event. You can also add a constructor (although you will have to supply the arguments and the code for parameterized constructors), a destructor, and a constant. To edit a member, such as the type of a property or the arguments of a method, switch to the Class Details window, where you will see the members of the selected class. Expand any member to see its parameters: the type of a property and the arguments and the return value of a method. Petroutsos c11.tex V2 - 01/28/2008 1:36pm Page 428 428 CHAPTER 11 WORKING W ITH OBJECTS The Bottom Line Use inheritance. Inheritance, which is the true power behind OOP, allows you to create new classes that encapsulate the functionality of existing classes without editing their code. To inherit from an existing class, use the Inherits statement, which brings the entire class into your class. Master It Explain the inheritance-related attributes of a class’s members. Use polymorphism. Polymorphism is the ability to write members that are common to a number of classes but behave differently, depending on the specific class to which they apply. Polymorphism is a great way of abstracting implementation details and delegating the imple- mentation of methods with very specific functionality to the derived classes. Master It The parent class Person represents parties, and it exposes the GetBalance method, which returns the outstanding balance of a person. The Customer and Supplier derived classes implement the GetBalance method differently. How will you use this method to find out the balance of a customer and/or supplier? Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 429 Chapter 12 Building Custom Windows Controls Just as you can design custom classes, you can use Visual Studio to design custom controls. The process is very similar, in the sense that custom controls have properties, methods, and events, which are implemented with code that’s identical to the code you’d use to implement these mem- bers with classes. The difference is that controls have a visual interface and interact with the user. In short, you must provide the code to draw the control’s surface, as well as react to selected user actions from within the control’s code. In this chapter, you’ll learn how to enhance the functionality of existing controls, a common practice among developers. You’ve already seen in the preceding chapter how to inherit an exist- ing class and add custom members. You can do the same with the built-in controls. There are several methods of designing custom controls. In this chapter, you’ll learn how to do the following: ◆ Extend the functionality of existing Windows Forms controls with inheritance ◆ Build compound custom controls that combine multiple existing controls ◆ Build custom controls from scratch ◆ Customize the rendering of the items in a ListBox control On Designing Windows Controls Before I get to the details of how to build custom controls, I want to show you how they relate to other types of projects. I’ll discuss briefly the similarities and differences among Windows controls, classes, and Windows projects. This information will help you get the big picture and put together the pieces of the following sections. A standard application consists of a main form and several (optional) auxiliary forms. The auxiliary forms support the main form because they usually accept user data that are processed by the code in the main form. You can think of a custom control as a form and think of its Properties window as the auxiliary form. An application interacts with the user through its interface. The developer decides how the forms interact with the user, and the user has to follow these rules. Something similar happens with custom controls. The custom control provides a well-defined interface, which consists of properties and methods. This is the only way to manipulate the control. Just as users of your applications don’t have access to the source code and can’t modify the application, developers can’t see the control’s source code and must access it through the interface exposed by the control. After an instance of the custom control is placed on the form, you can manipulate it through its properties and methods, and you never get to see its code. Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 430 430 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS In preceding chapters, you learned how to implement interfaces consisting of properties and methods and how to raise events from within a class. This is how you build the interface of a cus- tom Windows control: You implement properties with Property procedures, and you implement methods as Public procedures. Although a class can provide a few properties and any number of methods, a control must provide a large number of properties. A developer who places your custom control on a form expects to see the properties that are common to all the controls (prop- erties to set the control’s dimensions, its color, the text font, the Index and Tag properties, and so on). Fortunately, many of the standard properties are exposed automatically. The developer also expects to be able to program all the common events, such as the mouse and keyboard events, as well as some events that are unique to the custom control. The design of a Windows control is similar to the design of a form. You place controls on a form-like object, called UserControl, which is the control’s surface. It provides nearly all the methods of a standard form, and you can adjust its appearance with the drawing methods. In other words, you can use familiar programming techniques to draw a custom control or you can use existing controls to build a custom control. The forms of an application are the windows you see on the desktop when the application is executed. When you design the application, you can rearrange the controls on a form and program how they react to user actions. Windows controls are also windows, only they can’t exist on their own and can’t be placed on the desktop. They must be placed on forms. The major difference between forms and custom controls is that custom controls can exist in two runtime modes. When the developer places a control on a form, the control is actually running. When you set a control’s property through the Properties window, something happens to the control — its appearance changes or the control rejects the changes. It means that the code of the custom control is executing, even though the project on which the control is used is in design mode. When the developer starts the application, the custom control is already running. However, the control must be able to distinguish when the project is in design or execution mode and behave accordingly. Here’s the first property of the UserControl object you will be using quite frequently in your code: the DesignMode property. When the control is positioned on a form and used in the Designer, the DesignMode property is True. When the developer executes the project that contains the control, the DesignMode property is False. This dual runtime mode of a Windows control is something you’ll have to get used to. When you design custom controls, you must also switch between the roles of Windows control developer (the programmer who designs the control) and application developer (the programmer who uses the control). In summary, a custom control is an application with a visible user interface as well as an invis- ible programming interface. The visible interface is what the developer sees when an instance of the control is placed on the form, which is also what the user sees on the form when the project is placed in runtime mode. The developer using the control can manipulate it through its properties and methods. The control’s properties can be set at both design time and runtime, whereas meth- ods must be called from within the code of the application that uses the control. The properties and methods constitute the control’s invisible interface (or the developer interface,asopposedtothe user interface). You, the control developer, will develop the visible user interface on a UserControl object, which is almost identical to the Form object; it’s like designing a standard application. As far as the control’s invisible interface goes, it’s like designing a class. Enhancing Existing Controls The simplest type of custom Windows control you can build is one that enhances the functionality of an existing control. Fortunately, they’re the most common types of custom controls, and many Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 431 ENHANCING EXISTING CONTROLS 431 developers have their own collections of ‘‘enhanced’’ Windows controls. The Windows controls are quite functional, but you won’t be hard-pressed to come up with ideas to make them better. The TextBox control, for example, is a text editor on its own, and you have seen how easy it is to build a text editor by using the properties and methods exposed by this control. Many programmers add code to their projects to customize the appearance and the functionality of the TextBox control. Let’s say you’re building data-entry forms composed of many TextBox con- trols. To help the user identify the current control on the form, it would be nice to change its color while it has the focus. If the current control has a different color from all others, users will quickly locate the control that has the focus. Another feature you can add to the TextBox control is to format its contents as soon as it loses focus. Let’s consider a TextBox control that must accept dollar amounts. After the user enters a numeric value, the control could automatically format the numeric value as a dollar amount and perhaps change the text’s color to red for negative amounts. When the control receives the focus again, you can display the amount without any special formatting, so that users can edit it quickly. As you will see, it’s not only possible but actually quite easy to build a control that incorporates all the functionality of a TextBox and some additional features that you provide through the appropriate code. You already know how to add features such as the ones described here to a TextBox from within the application’s code. But what if you want to enhance multiple TextBox controls on the same form or reuse your code in multiple applications? The best approach is to create a new Windows control with all the desired functionality and then reuse it in multiple projects. To use the proper terminology, you can create a new custom Windows control that inherits the functionality of the TextBox control. The derived control includes all the functionality of the control being inherited, plus any new features you care to add to it. This is exactly what we’re going to do in this section. Building the FocusedTextBox Control Let’s call our new custom control FocusedTextBox. Start a new VB project and, in the New Project dialog box, select the template Windows Control Library. Name the project Focused- TextBox. The Solution Explorer for this project contains a single item, the UserControl1 item. UserControl1 (see Figure 12.1) is the control’s surface — in a way, it’s the control’s form. This is where you’ll design the visible interface of the new control using the same techniques as for designing a Windows form. Start by renaming the UserControl1 object to FocusedTextBox. Then save the project by choos- ing File Save All. To inherit all the functionality of the TextBox control into our new control, we must insert the appropriate Inherits statement in the control’s code. Click the Show All button in the Solution Explorer to see all the files that make up the project. Under the FocusedTextBox.vb file is the FocusedTextBox.Designer.vb file. Open this file by double-clicking its name and you’ll see that it begins with the following two statements: Partial Public Class FocusedTextBox Inherits System.Windows.Forms.UserControl The first statement says that the entire file belongs to the FocusedTextBox class; it’s the part of the class that contains initialization code and other statements that the user does not need to see because it’s left unchanged in most cases. To design an inherited control, we must change the second statement to the following: Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 432 432 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS Inherits System.Windows.Forms.TextBox Figure 12.1 A custom control in design mode This statement tells the compiler that we want our new control to inherit all the functionality of the TextBox control. You must also modify the InitializeComponent method in the Focused- TextBox.Designer.vb file by removing the statement that sets the control’s AutoSizeMode property. This statement applies to the generic UserControl object, but not to the TextBox control. As soon as you specify that your custom control inherits the TextBox control, the UserControl object will disappear from the Designer. The Designer knows exactly what the new control must look like (it will look and behave exactly like a TextBox control), and you’re not allowed to change it its appearance. If you switch to the FocusedTextBox.vb file, you’ll see that it’s a public class called Focused- TextBox. The Partial class by the same name is part of this class; it contains the code that was generated automatically by Visual Studio. When compiled, both classes will produce a single DLL file. Sometimes we need to split a class’s code into two files, and one of them should contain the Partial modifier. This keyword signifies that the file contains part of the class. The Focused- TextBox.vb file is where you will insert your custom code. The Partial class contains the code emitted by Visual Studio, and you’re not supposed to touch it. Inherited controls are an exception to this rule, because we have to be able to modify the Inherits statement. Let’s test our control and verify that it exposes the same functionality as the TextBox control. Figure 12.2 shows the IDE while developing an inherited control. Notice that the FocusedTextBox control has inherited all the properties of the TextBox control, such as the MaxLength and Pass- wordChar properties. To test the control, you must add it to a form. A control can’t be executed outside the context of a host application. Add a new project to the solution (a Windows Application project) with the File Add New Project command. When the Add New Project dialog box appears, select the Windows Application template and set the project’s name to TestProject.Anewfolder will be created under the FocusedTextBox folder — the TestProject folder — and the new Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 433 ENHANCING EXISTING CONTROLS 433 project will be stored there. The TestProject must also become the solution’s startup object. (This is the very reason we added the project to our solution: to have an executable for testing the custom control.) Right-click the test project’s name in the Solution Explorer and select Set As StartUp Object in the context menu. Figure 12.2 The IDE during the design of an inherited control To test the control you just ‘‘designed,’’ you need to place an instance of the custom control on the form of the test project. First, you must build the control. Select the FocusedTextBox item in the Solution Explorer, and from the Build menu, select the Build FocusedTextBox command (or right-click the FocusedTextBox component in the Solution Explorer and select Build from the context menu). The build process will create a DLL file with the control’s executable code in the Bin folder under the project’s folder. Then switch to the test project’s main form and open the ToolBox. You will see a new tab, the FocusedTextBox Components tab, which contains all the custom components of the current project. The new control has already been integrated into the design environment, and you can use it like any of the built-in Windows controls. Every time you edit the code of the custom control, you must rebuild the control’s project for the changes to take effect and update the instances of the custom control on the test form. The icon that appears before the custom control’s name is the default icon for all custom Windows controls. You can associate a different icon with your custom control, as explained in the ‘‘Classifying the Control’s Properties’’ section, later in this chapter. Place an instance of the FocusedTextBox control on the form and check it out. It looks, feels, and behaves just like a regular TextBox. In fact, it is a TextBox control by a different name. It exposes all the members of the regular TextBox control: You can move it around, resize it, change its Multiline and WordWrap properties, set its Text property, and so on. It also exposes all the methods and events of the TextBox control. Adding Functionality to Your Custom Control As you can see, it’s quite trivial to create a new custom control by inheriting any of the built-in Windows controls. Of course, what good is a control that’s identical to an existing one? Let’s add some extra functionality to our custom TextBox control. Switch to the control project and view the Petroutsos c12.tex V2 - 01/28/2008 2:25pm Page 434 434 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS FocusedTextBox object’s code. In the code editor’s pane, expand the Objects list and select the item FocusedTextBox Events. This list contains the events of the TextBox control because it is the base control for our custom control. Expand the Events drop-down list and select the Enter event. The following event handler declaration will appear: Private Sub FocusedTextBox Enter( ) Handles Me.Enter End Sub This event takes place every time our custom control gets the focus. To change the color of the current control, insert the following statement in the event handler: Me.BackColor = Color.Cyan (Or use any other color you like; just make sure it mixes well with the form’s default back- ground color. You can also use the members of the SystemColors enumeration, to help ensure that it mixes well with the background color.) We must also program the Leave event, so that the control’s background color is reset to white when it loses the focus. Enter the following statement in the Leave event’s handler: Private Sub FocusedTextBox Leave( ) Handles Me.Leave Me.BackColor = Color.White End Sub Having a hard time picking the color that signifies that the control has the focus? Why not expose this value as a property, so that you (or other developers using your control) can set it individually in each project? Let’s add the EnterFocusColor property, which is the control’s background color when it has the focus. Because our control is meant for data-entry operations, we can add another neat feature. Some fields on a form are usually mandatory, and some are optional. Let’s add some visual indication for the mandatory fields. First, we need to specify whether a field is mandatory with the Mandatory property. If a field is mandatory, its background color will be set to the value of the MandatoryColor property, but only if the control is empty. Here’s a quick overview of the control’s custom properties: EnterFocusColor When the control receives the focus, its background color is set to this value. If you don’t want the currently active control to change color, set its EnterFocusColor to white. Mandatory This property indicates whether the control corresponds to a required field if Mandatory is True or to an optional field if Mandatory is False. MandatoryColor This is the background color of the control if its Mandatory property is set to True. The MandatoryColor overwrites the control’s default background color. In other words, if the user skips a mandatory field, the corresponding control is painted with the MandatoryColor, and it’s not reset to the control’s background color. Required fields behave like optional fields after they have been assigned a value. If you have read the previous chapter, you should be able to implement these properties easily. Listing 12.1 is the code that implements the four custom properties. The values of the properties are stored in the private variables declared at the beginning of the listing. Then the control’s properties are implemented as Property procedures. [...]... Label1.BackColor = Color.FromARGB( 255 , HScrollBar1.Value, HScrollBar2.Value, HScrollBar3.Value) End Sub The single statement in this subroutine picks up the values of the three basic colors from the ScrollBar controls and creates a new color value with the FromARGB method of the Color object The first argument is the transparency of the color (the A, or alpha channel), and we set it to 255 for a completely opaque... Test Custom Windows Controls Visual Studio 2008 introduced a new, simple method of testing custom controls Instead of using a test project, you can press F5 to ‘‘run’’ the Windows Control project Right-click the name of the Label3D project (the Windows Control project in the solution) in Solution Explorer and from the context menu choose Set As Startup Project Then press F5 to start the project A dialog... the MeasureItem and DrawItem events are fired in this order In the MeasureItem event handler, we set the dimensions of the item with the statements shown in Listing 12. 15 457 458 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS Listing 12. 15: Setting Up an Item’s Rectangle in an Owner-Drawn ListBox Control Private Sub ListBox1 MeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs)... the namedColor variable Then the code extracts the three basic color components with the R, G, and B properties (These properties return the red, green, and blue color components, respectively.) Listing 12 .5 shows the code behind the ComboBox control’s SelectedIndexChanged event, which is fired every time a new color is selected by name Listing 12 .5: Specifying a Color by Name Private Sub ComboBox1 SelectedIndexChanged(... form of the project shows how the RoundButton control behaves on a form You can use the techniques described in this section to make a series of round controls for a totally different feel and look 455 456 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS The Play button’s Click event handler in the test form changes the caption of the button according to the control’s current state It also disables the other... surface The Graphics object exposes all the methods you can call to create graphics on the control’s surface The Graphics object is discussed in detail in Chapter 18, ‘‘Drawing and Painting with Visual Basic 2008, ’’ but for this chapter all you need to know is that the MeasureString method returns the dimensions of a string when rendered in a specific font, and the DrawString method draws the string... in the control’s code: Public Event ColorClick(ByVal sender As Object, ByVal e As ColorEvent) And finally, raise the ColorClick event from within the Label’s Click event handler (see Listing 12.11) 451 452 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS Listing 12.11: Raising a Custom Event Private Sub Label1 Click( ) Handles Label1.Click Dim ev As ColorEvent ev.color = Label1.BackColor RaiseEvent ColorClick(Me,... project with Visual Studio In the project’s folder, you will find a Readme file with a detailed discussion of the application Using the Custom Control in Other Projects By adding a test project to the Label3D custom control project, we designed and tested the control in the same environment A great help, indeed, but the custom control can’t be used in other projects If you start another instance of Visual. .. Sub First, we retrieve the Graphics object of the UserControl; then we create a GraphicsPath object, the roundPath variable, and add an ellipse to it The ellipse is based on the enclosing rectangle 453 454 CHAPTER 12 BUILDING CUSTOM WINDOWS CONTROLS The R object is used temporarily to specify the ellipse The new path is then used to create a Region object, which is assigned to the Region property of... just as you would do with a Windows form The three ScrollBar controls are named RedBar, GreenBar, and BlueBar, respectively The Minimum property for all three controls is 0; the Maximum for all three is 255 This is the valid range of values for a color component The control at the top-left corner is a Label control with its background color set to Black (We could have used a PictureBox control in its place.) . are implemented as Property procedures. Petroutsos c12.tex V2 - 01/28 /2008 2:25pm Page 4 35 ENHANCING EXISTING CONTROLS 4 35 Listing 12.1: Property Procedures of the FocusedTextBox Dim mandatory. supplier? Petroutsos c12.tex V2 - 01/28 /2008 2:25pm Page 429 Chapter 12 Building Custom Windows Controls Just as you can design custom classes, you can use Visual Studio to design custom controls Petroutsos c11.tex V2 - 01/28 /2008 1:36pm Page 4 25 WHO CAN INHERIT WHAT? 4 25 structure of Method4. It has no code, and the End Function statement is