home   Java Script   MS Access   Perl   HTML   Delphi   C ++   Visual Basic   Java   CGIPerl   MS Excel   Front Page 98   Windows 98   Ms Word   Builder   PHP   Assembler     Link to us   Links    

Teach Yourself Borland Delphi 4 in 21 Days

Previous chapterNext chapterContents

- 5 -

The Visual Component Model

Today I am going to talk about the visual component model and Borland's Visual Component Library (VCL). Before getting into that, though, I'll talk a little about class frameworks. In this chapter you will find

Frameworks Fundamentals

"In the beginning there was C. . . ." Well, not quite. As far as Windows programming is concerned, though, that statement is accurate. In the beginning, the vast majority of Windows programs were written in C. In fact, the Windows Application Programming Interface (API) is just a huge collection of C functions--hundreds of them. There are still undoubtedly thousands of programmers out there writing Windows programs in C.

Somewhere along the line, the folks at Borland decided, "There has got to be an easier way." (Actually, the framework revolution might have started on several different fronts, but Borland was certainly a leader.) It was apparent that Windows programming was very well suited to object-oriented programming. By creating classes that encapsulate common Windows programming tasks, a programmer could be much more productive. After a class was created to encapsulate a window's various duties, for instance, that class could be used over and over again. The framework revolution began.

But I haven't yet told you what a framework is.

New Term: A framework is a collection of classes that simplifies programming in Windows by encapsulating often-used programming techniques. Frameworks are also called class libraries. Encapsulation means taking a complex programming task and making it easier by providing a simplified interface.

Popular frameworks have classes that encapsulate windows, edit controls, list boxes, graphics operations, bitmaps, scrollbars, dialog boxes, and so on.

So Why Should I Care About Frameworks?

That's a good question. The bottom line is that frameworks make Windows programming much easier than it would be in straight C, in assembler, or in the original Pascal language (the Pascal that came prior to Object Pascal). Let me give you an example. Listing 5.1 contains a portion of a Windows program written in C++. This section of code loads a bitmap file from disk and displays the bitmap in the center of the screen. None of this will make sense to you right now, but be patient.


HFILE hFile;
DWORD nClrUsed, nSize;
HBITMAP hBitmap;
void *bits;
do {
  if ((hFile = _lopen(data.FileName, OF_READ)) == HFILE_ERROR) break;
  if (_hread(hFile, &bfh, sizeof(bfh)) != sizeof(bfh)) break;
  if (bfh.bfType != `BM') break;
  if (_hread(hFile, &bih, sizeof(bih)) != sizeof(bih)) break;
  nClrUsed =
    (bih.biClrUsed) ? bih.biClrUsed : 1 << bih.biBitCount;
  nSize =
    sizeof(BITMAPINFOHEADER) + nClrUsed * sizeof(RGBQUAD);
  lpbi = (LPBITMAPINFO) GlobalAllocPtr(GHND, nSize);
  if (!lpbi) break;
  MoveMemory(lpbi, &bih, sizeof(bih));
  nSize = nClrUsed * sizeof(RGBQUAD);
  if (_hread(hFile, &lpbi->bmiColors, nSize) != nSize) break;
  if (_llseek(hFile, bfh.bfOffBits, 0) == HFILE_ERROR) break;
  nSize = bfh.bfSize-bfh.bfOffBits;
  if ((bits = GlobalAllocPtr(GHND, nSize)) == NULL) break;
  if (_hread(hFile, bits, nSize) != nSize) break;
  hDC = GetDC(hWnd);
  hBitmap = CreateDIBitmap(hDC, &(lpbi->bmiHeader), CBM_INIT,
                          bits, lpbi, DIB_RGB_COLORS);
  if (hBitmap) {
    DWORD nsize = sizeof(LOGPALETTE)
      + (nClrUsed-1) * sizeof(PALETTEENTRY);
    lppal = (LPLOGPALETTE)  GlobalAllocPtr(GHND, nSize);
    if (lppal) {
      lppal->palVersion = 0x0300;
      lppal->palNumEntries = (WORD) nClrUsed;
      MoveMemory(lppal->palPalEntry, lpbi->bmiColors,
      nClrUsed * sizeof(PALETTEENTRY));
      hPal = CreatePalette(lppal);
      (void) GlobalFreePtr(lppal);
}  while(FALSE);
if (hFile != HFILE_ERROR) _lclose(hFile);
HPALETTE oldPal = SelectPalette(hDC, hPal, FALSE);
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP oldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap);
BitBlt(hDC, 0, 0, (WORD)bih.biWidth, (WORD)bih.biHeight,
  hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, oldBitmap);
SelectPalette(hDC, oldPal, FALSE);
ReleaseDC(hWnd, hDC);
if (bits) (void) GlobalFreePtr(bits);
if (lpbi) (void) GlobalFreePtr(lpbi);

That looks just a little intimidating, doesn't it? Now look at the equivalent using Borland's VCL:


So which would you rather use? You don't even have to know what these code snippets do to make that decision. It's easy to see that the VCL version is shorter (just a bit!) and more readable.

These examples sum up what frameworks are all about. Frameworks hide details from you that you don't need to know. Everything that is contained in Listing 5.1 is performed behind the scenes in the VCL code (albeit in Pascal rather than in C++). You don't need to know every detail about what goes on behind the scenes when VCL does its job, and you probably don't want to know. All you want is to take the objects that make up a framework and put them to use in your programs.

A good framework takes full advantage of OOP, and some do that better than others. Borland's Object Windows Library (which came in both C++ and Pascal versions) and Visual Component Library are excellent examples of object-oriented programming. They provide the proper abstraction needed for you to rise above the clutter and get down to the serious business of programming.

So What's the Catch?

A little skeptical, are you? Good. You're bright enough to figure out that if you have all that ease of use, you must be giving up something. Truth is, you are right. You might think that a program written with a framework would be larger and slower than its counterpart written in a low-level language. That's partially correct. Applications written with frameworks don't necessarily have to be slower than those other programs, though. There is some additional overhead inherent in an object-oriented language, certainly, but for the most part, it is not noticeable in a typical Windows program.

The primary trade-off is that Windows programs written in Delphi tend to be larger than programs written in languages such as C. For example, let's say you had a simple Windows program written in C that was 75KB. The equivalent program written with Delphi might be 250KB. That might seem like a significant difference, but this example demonstrates the worst-case scenario. The difference in final program size between a C application and a Delphi application written with a framework is most noticeable in very small programs. As your programs increase in size and sophistication, the size difference is much less noticeable.

One reason for the size difference is simply the difference between a procedural language and an object-oriented language. Object-oriented languages (C++ and Object Pascal, for example) carry additional overhead for features such as exception handling, runtime type information (RTTI), and other OOP goodies. In my opinion, the difference in code size is an acceptable trade-off for the features that Object Pascal provides.

Now, before you label me as a code-bloat proponent, let me say that I am as conscientious as the next person when it comes to code bloat. I believe that we should all write the tightest code we can given the tools we use. I am also a realist, and I understand that time-to-market is a driving force in the software industry today. I am willing to trade some code size for the power that Object Pascal and VCL give me. Let me put it another way. I'm not interested in spending a month to write a Windows program that compiles to a 100KB executable when I can accomplish the same thing in Delphi in two days and end up with a 400KB executable. The size of the resulting executables is insignificant when compared to the development time saved.


If you end up getting serious about this crazy game called Windows programming, you will eventually end up peeking into the source code of your favorite framework. Sooner or later you'll want to know how the pros do things. The VCL source code is a great place to go for that kind of information.

Some weekend when the leaves are raked, the house trim is painted, the laundry is done, the kids are at Grandma's, and you think you have a good handle on Delphi, spend some time browsing the VCL source code. (Delphi Professional and Client/Server ship with the VCL source code.) It can be intimidating at first, but after a while you'll see what the designers were doing. Don't strain yourself. Attempt to understand the things that bump up against the limits of your knowledge regarding Object Pascal. Leave the complicated stuff for later.
But notice how the VCL designers use private, protected, and public access in classes. Notice how things that should be kept hidden from the user aren't in public view. Studying the VCL source can teach you a great deal about Object Pascal and object-oriented design.

The Visual Component Library

You have probably noticed that this book contains "Delphi 4" in its title. Obviously Delphi has been around a while. When Delphi 1 was introduced in 1995, it was an instant hit. Delphi offered rapid application development (RAD) using something called components. Components are objects that can be dropped on a form and manipulated via properties, methods, and events. It's visual programming, if you will.

The concept of form-based programming was first popularized by Microsoft's Visual Basic. Unlike Visual Basic, though, Delphi used a derivative of Pascal as its programming language. This new language, called Object Pascal, introduced OOP to the Pascal language. Delphi and Object Pascal represented the marriage of object-oriented programming and form-based programming. In addition, Delphi could produce standalone executables. Real programs. Programs that did not require a runtime DLL to run; programs that were compiled, not interpreted; programs that ran tens of times faster than Visual Basic programs. The programming world was impressed.

Delphi didn't just throw Object Pascal at you and let you flounder. It also introduced the Visual Component Library. As I have said, VCL is an application framework for Windows programming in Object Pascal. The most noticeable feature of VCL is that it was designed around the concept of properties, methods, and events--the visual component model. Let's look at the visual component model in more detail.


As I talked about on Day 1, "Getting Started with Delphi," VCL components are objects that perform a specific programming task. VCL components are wrapped up in Object Pascal classes. From now on in this book, you will be encountering components on a daily basis. I won't spend a lot of time explaining every detail of components right now because you will see by example how they work throughout the rest of the book. I'll explain components in more detail on Day 7, "VCL Components."

Properties, Methods, and Events

On Day 1, I gave you a brief introduction to the properties, methods, and events model. These three ingredients make up the public interface of components in VCL (the part of the component the user will see). Let's take a look at these elements one at a time.


Properties are elements of a component that control how the component operates. Many components have common properties. All visual components, for example, have a Top and a Left property. These two properties control where the component will be positioned on a form both at design time and at runtime. All components have an Owner property, which VCL uses to keep track of the child components a particular parent form or component owns.

Properties and the Object Inspector  A picture is always worth a thousand words, so let's start up Delphi again and see properties in action. When you start Delphi, you are greeted with a blank form and the Object Inspector.

NOTE: If you have the Delphi options configured to save the desktop when you close Delphi, you might see the last project you were working on when you start Delphi. If that's the case, choose File|New Application from the main menu to get a blank form.

The Object Inspector will look something like Figure 5.1. (When Delphi starts, it sizes the Object Inspector based on your current screen resolution, so your Object Inspector might be taller or shorter than the one shown in Figure 5.1.) If necessary, click on the Properties tab of the Object Inspector window so that the form's properties are displayed. The component's properties are arranged in alphabetical order.

FIGURE 5.1.The Object Inspector.

If more properties exist than can be displayed at one time, the Object Inspector displays a scrollbar so that you can view additional properties. The Object Inspector window can be moved and sized. I like my Object Inspector as tall as my screen permits so that I can see the maximum number of properties at one time. Scroll through the properties until you locate the Left property and then click on it. Change the value for the Left property (any number between 0 and 600 will do) and press Enter on the keyboard. Notice how the form moves as you change the value.

This illustrates an important aspect of properties: they are more than simple fields of a class. Each property has an underlying data field associated with it, but the property itself is not a class data field. Changing a property often leads to code executed behind the scenes.

New Term: Properties are often tied to access methods that execute when the property is modified.

Changing a Property's Value  Properties can be changed at design time (when you are designing your form) and at runtime (when the program is running through code you write). In either case, if the property has an access method, that access method will be called and executed when the property is modified. You already saw an example of changing a property at design time when you changed the Left property and watched the form move on the screen.

That is one of the strengths of VCL and how it is used in Delphi: You can instantly see on the screen the result of your design change. Not all properties show a visible change on the form at design time, however, so this doesn't happen in every case. Still, when possible, the results of the new property value are immediately displayed on the form.

To change a property at runtime, you simply make an assignment to the property. When you make an assignment, VCL works behind the scenes to call the access method for that property. To change the Left property at runtime, you use code like this:

Left := 200;

In the case of the Left property (as well as the Top property), VCL moves and repaints the form. (For you Windows API programmers, you can figure out that this eventually translates into calls to the Windows API functions SetWindowPos and InvalidateRect.)

New Term: Property Access Specifiers  Properties have two access specifiers, which are used when properties are read or modified. There is a read specifier and a write specifier.

Suffice it to say that access specifiers associate read and write methods with the property. When the property is read or written to, the methods associated with the property are automatically called. When you make an assignment as in the previous example, you are accessing the write specifier. In effect, VCL checks to see whether an access method exists for the write specifier. If it does, the access method is called. If no access method exists, VCL assigns the new value to the data field associated with the property.

When you reference a property (use the property as the right side of an equation), you are accessing the read specifier:

X := Left;

In this case, VCL calls the read specifier to read the value of the Left property. In many cases the read specifier does very little more than return a property's current value.

Property Attributes  The properties of the property (sorry, I couldn't resist) are determined by the writer of the component. A property can be read-only. A read-only property can be read--its value can be retrieved--but not 
written to. In other words, you can fetch the property's value, but you can't change it. In rare cases, a property can be made write-only (a property that can be written to but not read isn't very useful in most cases). This is obviously the opposite 
of a read-only property. 

Finally, some properties can be specified runtime-only. A runtime-only property can be accessed only at runtime, not design time. Because a runtime-only property doesn't apply at design time, it is not displayed in the Object Inspector. A runtime-only property can be declared as read-only, too, which means that it can be accessed only at runtime and can only be read (not written to).

Property Types  Some properties use an instance of a VCL class as the underlying data field. To illustrate, let's put a memo component on our blank form:

1. Go to the Delphi Component palette, choose the Standard tab, and click the Memo button. (The tooltip will tell when you are over the Memo button.)

2. Now move to the form and click on it where you want the memo's top-left corner to appear. As soon as you place the memo component on the form, the Object Inspector switches to show you the properties of the component just placed on the form, in this case a TMemo.

3. Locate the Lines property and click on it. Notice that the property value contains the text (TStrings) and that there is a little button with an ellipsis (. . .) to the right of the property value.

The ellipsis button tells you that this property can be edited by using a property editor. For an array of strings, for instance, a dialog box will be displayed in which you can type the strings. In the case of the Font property, clicking the ellipsis button will invoke the Choose Font dialog box. The exact type of the property editor is property-specific, although certain properties can share a common editor. You can bring up the property editor by clicking the ellipsis button or by double-clicking the property value.

The Lines property for a memo component is an instance of the TStrings class. When you double-click the Value column, the string editor is displayed and you can then type the strings you want displayed in the memo component when the application runs. If you don't want any strings displayed in the memo component, you need to clear the property editor of any strings.

The Font property is another example of a property that is an instance of a VCL class. A font includes things like the typeface, the color, the font size, and so on. Locate the Font property in the Object Inspector. (It doesn't matter whether you have selected the memo component or the form.)

Notice that there is a plus sign before the word Font. This tells you that there are individual properties within this property that can be set. If you double-click on the property name, you will see that the Object Inspector expands the property to reveal its individual elements. You can now individually edit the Font property's elements. In the case of the Font property, these same settings can be edited by invoking the property editor. You can use either method with the same results.

Some properties are sets (I talked about sets on Day 3, "Classes and Object-Oriented Programming"). The Style property within the Font object is a good example of a set. Notice that Style has a plus sign in front of it. If you double-click on the Style property, you will see that the Style node expands to reveal the set's contents. In this case, the set consists of the various styles available for fonts: bold, italic, underline, and strikeout. By double-clicking a style, you can turn that style on or off. A set can be empty or can contain one or more of the allowed values.

New Term: Some properties can be enumerations, a list of possible choices.

An enumeration is a list of possible choices for a property. When you click on an enumeration property, a drop-down arrow button appears to the right of the value. To see the choices in the enumeration, click the drop-down button to display the list of choices. Alternatively, you can double-click the Value column for the property. As you double-click on the property's value, the Object Inspector will cycle through (or enumerate) the choices. The Cursor property gives a good example of an enumerated property. Locate the Cursor property and click the arrow button to expose the list of possible cursors to choose from.

Enumerations and sets differ in that with an enumeration property, only one of the presented choices can be selected (only one cursor can be in effect at any time). The set can contain none or any number of the choices (a font style can contain bold, underline, italic, or none of these).

As long as you have Delphi running and a blank form displayed, you might as well spend some time examining the various components and their properties. Go ahead, I'll wait.



I discussed methods on Day 3, "Classes and Object-Oriented Programming," so I don't need to cover them again here in any great detail. Methods in VCL components are functions and procedures that can be called to make the 
component perform certain actions. For example, all visual components have a method called Show, which displays the component, and a method called Hide, which hides the component. For example:
{ do some stuff, then later... } 

Methods in VCL can be declared as public, protected, or private. Public methods can be accessed by the component's users. In this example, both the Show and Hide methods are public. Protected methods cannot be accessed by the component users but can be accessed by classes (components) derived from a component. Of course, private methods can be accessed only within a class itself.

Some methods take parameters and return values, others don't. It depends entirely on how the method was written by the component writer. For example, the GetTextBuf method retrieves the text of a TEdit component. This method can be used to get the text from an edit control as follows:

  Buff     : array [0..255] of Char;
  NumChars : Integer;
  NumChars := EditControl.GetTextBuf(Buff, SizeOf(Buff));

As you can see, this particular method takes two parameters and returns an integer. When this method is called, the edit control contents are placed in the variable Buff and the return value is the number of characters retrieved from the edit control.

For now, that's all you need to know in order to use methods. I'll discuss them in more detail on Day 20, "Creating Components."

House Rules: Methods


New Term: Windows is said to be an event-driven environment. Event-driven means that a program is driven by events that occur within the Windows environment. Events include mouse movements, mouse clicks, and key presses.

Programmers moving from DOS or mainframe programming environments might have some difficulty with the concept of something being event-driven. A Windows program continually polls Windows for events. Events in Windows include a menu being activated, a button being clicked, a window being moved, a window needing repainting, a window being activated, and so forth.

Windows notifies a program of an event by sending a Windows message. There are over 200 possible messages that Windows can send to an application. That's a lot of messages. Fortunately, you don't have to know about each and every one of them to program in Delphi; there are only a couple dozen that are used frequently.

VCL Events  In VCL, an event is anything that occurs in the component that the user might need to know about. Each component is designed to respond to certain events. Usually this means a Windows event, but it can mean other things as well. For example, a button component is designed to respond to a mouse click, as you would expect. But a nonvisual control, such as a database component, can respond to non-Windows events, such as the user reaching the end of the table.

New Term: Handling Events  When you respond to a component event, you are said to handle the event.

Events are handled through methods called event handlers. You used event handlers extensively as you worked through the first three days of the book.

A typical Windows program spends most of its time idle, waiting for some event to occur. VCL makes it incredibly easy to handle events. The events that a component has been designed to handle are listed under the Events tab in the Object Inspector window. Event names are descriptive of the event to which they respond. For instance, the event to handle a mouse click is called OnClick.

NOTE: You don't have to handle every event that a component defines. In fact, you rarely do. If you don't respond to a particular event, the event message is either discarded or handled in a default manner as described by either VCL or the component itself. You can handle any events you have an interest in and ignore the rest.

These concepts will make more sense if you put them into practice. To begin, let's start a new application. Choose File|New Application from the main menu. If you are prompted to save the current project, click No. Now you will again have a blank form. First, set up the main form:

1. Change the Name property to PMEForm (PME for properties, methods, and events).

2. Change the Caption property to PME Test Program.

Next, you need to add a memo component to the form:

1. Choose the Standard tab on the Component palette and click the Memo button.

2. Click on the form to place a memo component on the form.

3. Change the Name property to Memo. Be sure the memo component is selected so that you don't accidentally change the form's name instead of the memo component.

4. Double-click on the Lines property in the Value column. The String list editor will be displayed.

5. Delete the word Memo and type A test program using properties, methods, and events. Click OK to close the String list editor.

6. Resize the memo component so that it occupies most of the form. Leave room for a button at the bottom.

Your form will now look like the form shown in Figure 5.2.

Now you can place a button on the form:

2. Click on the form below the memo component to place the button on the form.

3. Change the Name property for the button to Button.

4. Change the Caption property to Show/Hide.

FIGURE 5.2.The form with a memo component added.

5. Center the button horizontally on the form.

TIP: You can center components visually, but for a more exact method use the Alignment palette. Choose View|Alignment Palette from the main menu and then click the Center horizontally in window button on the Alignment palette to center a component horizontally on the form.

You will use this button to alternately show and hide the memo component. Now you need to write some code so that the button does something when it is clicked. Be sure that the button component is selected, and then click on the Events tab in the Object Inspector.

A list of the events that a button component is designed to handle is presented. The top event should be the OnClick event. Double-click on the Value column of the OnClick event. What happens next is one of the great things about visual programming. The Code Editor comes to the top and displays the OnClick procedure ready for you to type code. Figure 5.3 shows the Code Editor with the OnClick handler displayed.

FIGURE 5.3.The Delphi Code Editor with the OnClick handler displayed.

NOTE: Your Code Editor might not look exactly like Figure 5.3. I removed the Module Explorer from the Code Editor window to show more of the code. One of the great things about the Delphi IDE is that it is fully customizable. If you don't like the default layout, you can always change it.

Adding Event Handler Code  Notice that the event handler is already set up for you, all you have to do is type the code. If you take a good look at the event handler, you will see that it is a procedure, that it is called ButtonClick, that it is a member of the TPMEForm class, and that it takes a pointer to a TObject called Sender as a parameter. (I'll talk about the Sender parameter in just a bit.) All that is left to do now is type code that shows and hides the button each time the button is clicked. We'll borrow a little code from our earlier discussion of methods. Edit the ButtonClick method until it looks like this:

procedure TPMEForm.ButtonClick(Sender: TObject);
  IsVisible : Boolean = False;
  IsVisible := not IsVisible;
  if IsVisible then
This code first declares a typed constant named IsVisible.

New Term: A typed constant, when used in this way, is a variable that retains its value between calls to the method.

The first line of code in this method flips the Boolean variable between True and False by applying a logical NOT to the variable's present value. It works like so:

1. Initially the static variable is set to False. The first time the event handler is called, the variable is assigned NOT False, which is, of course, True.

2. The next time the event handler is called, the variable is assigned NOT True, and so on.

3. Each time the method is called, IsVisible contains the opposite value it had on the previous call. After that, the if/else pair calls either Show or Hide depending on the value of IsVisible.

That's all there is to it. But does it work? Let's find out. Click the Run button on the toolbar. After being compiled, the program runs and is displayed. It's the moment of truth. Click the button, and the memo component is hidden. Click the button again, and the memo component is again displayed. It works!

After playing with that for a minute, close the program (use the Close Program button in the upper-right corner of the title bar) and you are back to the Code Editor.

Before you go on, save the project. Choose File|Save All from the main menu. The first thing you are prompted for is the name of the unit (source file). Type PMEMain and click OK. Next, you are prompted for a filename for the project. Type PMETest and press Enter or click OK.

Using the Visible Property  All that work with a Boolean variable is a bit cumbersome. Think back to the discussion about properties. Wouldn't it be nice if the memo component had a property that could tell us whether the component was currently visible? Is there such a beast? Of course there is. It's called, predictably, Visible. Let's make use of it. Again, edit the event handler until it looks like this:

procedure TPMEForm.ButtonClick(Sender: TObject);


  if Memo.Visible then

Again click the Run button. The program is displayed and, lo and behold, the button does what it's supposed to. How about that? You managed to use properties, methods, and events in the same example.

Are you getting the fever yet? Hold on, because there's much more to come. Oh, and wipe that silly grin off your face. . .your boss thinks you're working!

The Sender Parameter  As you can see, the ButtonClick method takes a pointer to a TObject called Sender (whether you know it or not, all class variables in Delphi are pointers). Every event handler will have at least a Sender parameter. Depending on the event being handled, the event handler might have one or more additional parameters. For instance, the OnMouseDown event handler looks like this:

procedure TPMEForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

Here you are getting information on the button that was pressed, which keyboard keys were pressed at the time the mouse was clicked, and the x, y coordinate of the cursor when the mouse button was clicked. The event handler contains all the information you need to deal with the particular event the event handler is designed to handle.

So what exactly is Sender? Sender is a pointer to the component that is sending the message to the message handler. In this example, the Sender parameter is extra baggage because you know that the Show/Hide button is the sender. Sender exists to enable you to have more than one component use the same event handler.

To illustrate, let's create a new button and make one of our buttons the Show button and the other the Hide button:

1. If the Code Editor is on top, press F12 to switch back to the Form Editor.
2. Click on the Show/Hide button to select it. Change both the Name and Caption properties to Show.

3. Add a new button to the form to the right of the Show button. Arrange the buttons if you want to give an even look to the form.

4. Change the Name property for the new button to Hide. The Caption property will also change to Hide (you'll have to press Enter before the Caption property will change).

5. Click the Show button and then click on the Events tab in the Object Inspector. Notice that the OnClick event now says ShowClick. Edit it to say ButtonClick again. (The initial event-handler name is a default name. You can change it to any name you like.)

6. Click the Hide button and find the OnClick event in the Object Inspector (it will be selected already). Next to the value is a drop-down arrow button. Click the arrow button and choose ButtonClick from the list that drops down (there will be only one name in the list at this point).

7. Double-click on the value ButtonClick. You are presented with the Code Editor with the cursor in the ButtonClick method. Modify the code so that it reads like this:

procedure TPMEForm.ButtonClick(Sender: TObject)
  if Sender = Hide
    then Memo.Hide
8. Bake at 425 degrees for one hour or until golden brown. (Just checking.)

Your form will look similar to Figure 5.4. Compile and run the program. Click each button to be sure that it functions as advertised. 

FIGURE 5.4.The form with all components added.

What you have done here is create a single event-handling method that handles the OnClick event of both buttons. You use the Sender parameter to determine which button sent the OnClick event and then either hide or show the memo component as needed. You could have created a separate OnClick handler for each button, but with this method the code is more compact. Besides, it's a good illustration of how Sender can be used.

Note that I am comparing the Sender variable to a component's Name property. Because both are pointers, a comparison is being made to see whether both variables contain the same address.

Step 6 in the previous exercise illustrates an important point: After you create an OnClick event handler for a particular component, you can attach that same handler to the OnClick event of any component on the form. This enables you to use the same event handler for multiple components. I'll discuss events in more detail as you progress through the book.


VCL Explored

The Visual Component Library is a well-designed framework. As with most good frameworks, VCL makes maximum use of inheritance. The bulk of the VCL framework is composed of classes that represent components. Other VCL classes are not related to components. These classes perform housekeeping chores, act as helper classes, and provide some utility services.

The VCL class hierarchy dealing with components is complex. Fortunately, you don't have to know every detail of VCL to begin programming in Delphi. At the top of the VCL chain, you will find TObject. Figure 5.5 shows some of the main base classes and the classes derived from them.

FIGURE 5.5.The VCL class hierarchy.

TObject is the granddaddy of all VCL component classes. (Remember that all classes in Object Pascal are derived from TObject.) Below TObject you see TPersistent. This class deals with a component's capability to save itself to files and to memory as well as other messy details you don't need to know ab