
|
HomePage | About Us | HTML | DelpHi | Downloads | Credits | | BookMark This Site |
|
� |
|
- 7 - VCL Components � � As you know by now, components are much of what gives Delphi its power. Using the Form Designer, you can place a component on a form an d modify its design-time properties. In some cases, that's all you have to do. If needed, you can also manipulate the component at runtime by changing its properties and calling its methods. Further, each component is designed to respond to certain events. I discussed properties, methods, and events on Day 5, "The Visual Component Model," so I'm not going to go over that again. Today you will find out more about components. You will learn about often-used components and, as a result, learn about the Visual Component Library (VCL) classes that represent those components. As you go through this chapter, feel free to experiment. If you read something that you want to test, by all means do so. Learning by experience is as valuable as anything you can do, so don't be afraid to experiment. � A Review of Components Let's review some of what you already know about components. Before doing that, though, I want to take a moment to explain the differences between a VCL component and a Windows control. Windows controls include components such as edit controls, list boxes, combo boxes, static controls (labels), and buttons, not to mention all the Win32 controls. Windows controls, by nature, don't have properties, methods, and events. Instead, messages are used to tell the control what to do or to get information from the control. To say that dealing with controls on this level is tedious and cumbersome would be an understatement. A VCL component is a class that encapsulates a Windows control (not all VCL components encapsulate controls, though). A VCL component in effect adds properties, methods, and events to a Windows control to make working with the control easier. You might say that VCL takes a fresh approach to working with Windows controls. It could be said that all VCL components are controls, but not all controls are components. A VCL Edit component, for example, is a control, but a standard Windows edit control is not a VCL component. VCL components wor k with Windows controls to raise the job of dealing with those controls to a higher level. Given that discussion, then, I will use the terms control and component interchangeably when referring to VCL components. (But I will never call a Windows control a component!) � Visual Components Visual components include components such as edit controls, buttons, list boxes, labels, and so on. Most components you will use in a Delphi application are visual components. Visual components, as much as possible, show you at design time what the component will look like when the program runs. New Term: Some components are visual components; others are nonvisual components. A visual component, as its name implies, is one that can be seen by the user at design time. � Nonvisual Components New Term: A nonvisual component is one that cannot be seen by the user at design time. Nonvisual components work behind the scenes to perform specific programming tasks. Examples include system timers, database components, and image lists. Common dialog boxes such as File Open, File Save, Font, and so on are considered nonvisual components as well. (They are nonvisual because they don't show themselves at design time. At runtime, they become visible when they are invoked.) The common dialog components are discussed later in the section "The Common Dialog Boxes." When you place a nonvisual component on a form, Delphi displays an icon representing the component on the form. This icon is used to access the component at design time in order to change the component's properties, but the icon does not show up when the program runs. Nonvisual components have properties, methods, and events just like visual components do. Now let's look at some of the common properties components share. � The Name Property The Name property ser ves a vital role in components. On Day 5, "The Visual Component Model," in the section "VCL Explored," I discussed some of what happens when you place a component on a form. As soon as you place a component on a form, Delphi goes to work in the background while you ponder your next move. One thing Delphi does is create a pointer to the component and assign the Name property as the variable name. For example, let's say you place an Edit component on a form and change the Name property to MyEdit. At that point, Delphi places the following in the class declaration for the form (in the published section): � MyEdit:
TEdit; When the application runs, Delphi creates an instance of the TEdit class and assigns it to MyEdit. You can use this pointer to access the component at runtime. To set the text for the edit control, you would use � MyEdit.Text
:= `Jenna Lynn'; Delphi also uses the Name property when creating event-handler names. Let's say that you want to respond to the OnChange event for an Edit component. Normally, you double-click the Value column in the Object Inspector next to the OnChange event to have Delphi generate an event handler for the event. Delphi creates a default function name based on the Name property of the component and the event being handled. In this case, Delphi would generate a function called MyEditChange. You can change the Name property at any time provided that you change it only via the Object Inspector. When you change a component's Name property at design time, Delphi goes through all the code that it previously generated and changes the name of the pointer and all event-handling functions.
Continuing with this example, if you change the Name property of the edit control from MyEdit to FirstName, Delphi will change the pointer name to FirstName and the OnChange handler name to FirstNameChange. It's all done automatically; you don't have to do anything but change the Name property and trust that Delphi will do the rest of the work.
Delphi assigns a default value to the Name property for all components placed on a form. If you place an Edit component, for example, Delphi assigns Edit1 to the Name property. If you place a second Edit component on the form, Delphi will assign Edit2 to that component's Name property, and so on. You should give your components meaningful names as soon as possible to avoid confusion and extra work later on.
� Important Common Properties All components have certain properties in common. For example, all visual components have Left and Top properties that determine where the component is placed on the form. Properties such as Left, Top, Height, and Width are self-explanatory, so I won't go over them here. A few of the common properties, however, warrant a closer look. � The Align Property On Day 6, "Working with the Form Designer and the Menu Designer," I discussed the Align and Alignment properties, so I won't go over those again in detail. Refer to Day 6 for complete information on Align. It should be noted here, however, that not all components expose the Align property at design time. A single-line edit control, for example, should occupy a standard height, so the features of the Align property do not make sense for that type of component. As you gain experience with Delphi (and depending on the type of applications you write), you will probably rely heavily on the Align property. � The Color Property The Color property sets the background color for the component. (The text color is set through the Font property.) Although the Color property is simple to use, there are a few aspects of component colors that should be addressed. The way the Color property is handled in the Object Inspector is somewhat unique. If you click the Value column, you see the drop-down arrow button indicating that you can choose from a list of color values. That is certainly the case, but there's more to it than that. If you double-click the Value column, the Color dialog box will be displayed. This dialog box enables you to choose a color from one of the predefined colors or to create your own colors by clicking the Define Custom Colors button. Figure 7.1 shows the Color dialog box after the Define Custom Colors button has been clicked. FIGURE 7.1. The Color dialog box. NOTE: This is the same Color dialog box that will be displayed if you implement the ColorDialog component in your application. If you choose a color from the Color dialog box, you see that the value of the Color property changes to a hexadecimal string. This string represents the red, green, and blue (RGB) values that make up the color. If you know the exact RGB value of a color, you can type it in (not likely!). Most of the time you will probably choose a color from the list of color values provided. When you click the drop-down button to display the list of possible values, you will see what essentially amounts to two groups of values. The first group of colors begins with clBlack and ends with clWhite. These are the Delphi predefined colors; this list represents the most commonly used colors. To choose one of the listed colors, simply click the color in the list. If you can't find a color in the list that suits your needs, you can invoke the Color dialog box as discussed. The second group of colors in the list begins with clScrollBar. This group of colors represents the Windows system colors. If you use colors from this list, your application will automatically adjust its colors when the user changes color schemes in Windows. If you want your application to follow the color scheme the user has chosen for his or her system, you should choose colors from this list rather than from the first list. Use of color should be carefully considered. Proper use of color provides an aesthetically pleasing environment for the user. Abuse of colors makes for an obnoxious application that is annoying to use. Color is like a magnet to new programmers. It is common to want to throw lots of colors on a form because it's fun and easy, but don't get caught up in the fun at the expense of your users. � The Cursor Property The Cursor property controls the cursor that is displayed when the user moves the mouse cursor over the component. Windows automatically changes cursors for some components. For example, Windows changes the cursor to an I-beam when the cursor is moved over an Edit, Memo, or RichEdit component. To let Windows manage the cursor, leave the Cursor property set to crDefault. If you have specialized windows (components), you can specify one of the other cursors. When the mouse is moved over that component, Windows will change the cursor to the one you specified. Frequently, you will need to change cursors at runtime. A long process, for example, should be indicated to the user by displaying the hourglass cursor. When you reset the cursor, you need to be sure to set the cursor back to whatever it was originally. The following code snippet illustrates this concept: � var This ensures that the cursor that was originally set for the application is properly restored. Another cursor property, DragCursor, is used to set the cursor that is used when the mouse cursor is over a component that supports drag-and-drop. As with colors, you should be prudent in your use of cursors. Use custom cursors when needed, but don't overdo it. � The Enabled Property Components can be enabled or disabled through the Enabled property. When a component is disabled, it cannot accept focus (clicking on it has no effect), and usually it gives some visual cue to indicate that it is disabled. In the case of buttons, for example, the button text is grayed out as is any bitmap on the button. Enabled is a Boolean property: Set it to True to enable the component or set it to False to disable the component. Enabling and disabling windows (remember that windowed components are windows, too) is a feature of Windows itself.
The Enabled property applies mostly to windowed components, but it can apply to non-windowed components as well. The SpeedButton component is an example of a non-windowed component that can be disabled.
Although components can be disabled at design time, enabling and disabling components is something that is usually done at runtime. Menu items, for example, should be enabled or disabled according to whether they apply at a given time. The same is true of buttons. There are a variety of reasons why you might want to disable other types of controls as well. To disable a component at runtime, just assign False to its Enabled property, and to enable a component assign True to Enabled. The following code snippet enables or disables a menu item based on some condition: � if CanSave
then This process is often referred to as command enabling and is an important part of a professional-looking Windows program.
� The Font Property The Font property is a major property and therefore needs to be included here, but there is not a lot that needs to be said about it. The Font property is an instance of the TFont class and, as suc h, has its own properties. You can set the Font properties by double-clicking on the font name in the Object Inspector (which will expand the Font node and show the Font properties) or by invoking the Font dialog box. (The Font dialog box is discussed in more detail later in this chapter in the section "The Font Dialog Box.") Figure 7.2 shows the Object Inspector with the Font property node expanded to reveal the TFont properties. FIGURE 7.2. The Object Inspector showing the Font property. The Color property sets the color of the font, and the Name property enables you to choose the typeface for the font. The Height and Size properties of TFont deserve special mention as well:
When you change one of these properties, the other will change automatically. The Height is often specified as a negative number. Refer to the online help for TFont for an explanation of why this is the case. The Pitch property is not particularly useful. I'll explain it in just a moment, but first a quick tutorial on fonts. A font can be either proportionally spaced or fixed space:
In theory, the Pitch property can be used to force a proportionally spaced font to fixed space and vice versa. The problem is that Windows might perform font substitutions to carry out the conversion. In other words, you really don't know what you might get. It is far better to pick exactly the font you require than to rely on the Pitch property. � Finally, the Style property of TFont can be used to toggle bold, italic, underline, or strikethrough. These styles are not mutually exclusive, so you can mix styles in any way you choose.
� The Hint Property The Hint property is used to set hint text for a component. The hint text has two parts. The first part is sometimes called the short hint. This is the hint text that is displayed when the user places the cursor over the component and pauses. The pop-up window that displays the hint text is called a tooltip. The second part of the hint text is sometimes called the long hint. The long hint is the optional hint text that shows in the status bar when the user moves the mouse cursor over the component. The short and long hint texts are separated by a pipe (|). For example, to specify both the short hint text and the long hint te xt for a File Open speed button, you would enter the following for the Hint property: � File
Open|Open a file for editing In order for short hints to show, you must have the Application object's ShowHint property set to True (the default) as well as the component's ShowHint property. Displaying the long hint in the status bar requires a little more work, so I'll save that discussion for tomorrow.
� The ParentColor, ParentCtl3D, ParentFont, and ParentShowHint Properties The ParentColor, ParentCtl3D, ParentFont, and ParentShowHint properties work the same way, so I'll discuss them at the same time. When these properties are set to True, the component takes its Color, Ctl3D, Font, or ShowHint settings from its parent. For example, for most components the ParentFont property is set to True by default. This means the component will inherit the font that its parent is currently using. To better understand this, do this exercise:
You can set this property to False, but by the time the component is placed it is already too late and you will have to change the font manually to the font you want for the component. � The Tag Property The Tag property is nothing more than a four-byte variable set aside for your use. You can use the Tag property to store any data that your component might need. The data stored might be a pointer to another class, an index value, or any number of other possibilities. Using the Tag property would probably be considered an advanced programming technique. � Other Common Properties Table 7.1 lists other common properties that are frequently used. These properties don't require as much explanation, so they are listed here for your reference. Not all components have each of the properties listed. � TABLE 7.1. ADDITIONAL COMPONENT PROPERTIES. �
Primary Methods of Components There are more than 20 methods that most components have in common. Windowed components have more than 40 common methods from which to choose. Interestingly, not many of these are widely used. Much of the functionality of components is accomplished via properties. For example, to hide a component, you can call the Hide method or you can set the Visible property to False. In addition, components typically have methods specific to their purpose, and it will likely be those methods that you use most when dealing with a particular component. There are a few methods worthy of note, however, so I'll list them here (see Table 7.2). Note that some of these methods are not available to all controls. These are not the most often used methods common to every component, but rather the most commonly used methods of components in general. Also, this list concentrates on components representing controls (components placed on forms) rather than components as forms. Methods particular to forms were discussed on Day 4, "The Delphi IDE Explored." � TABLE 7.2. COMMON METHODS OF COMPONENTS. �
N ow let's take look at some of the events to which a component is most likely to respond. � Common Events As with properties and methods, there are some events that will be responded to most often. Components cover a wide variety of possible Windows controls, so each component will have individual needs. Events specific to forms are not covered here because I covered that information on Day 4. The most commonly used events are listed in Table 7.3. � TABLE 7.3. COMMONLY HANDLED COMPONENT EVENTS. �
�
�
In just a moment you're going to look at some of the VCL components in more detail. First, however, I want to introduce you to a class that is used by certain VCL components--TStrings. � TStrings The TStrings class is a VCL class that manages lists of strings. Several VCL components use instances of TStrings to manage their data (usually text). For example, on Day 6 you used TStrings when you built the ScratchPad application. "I don't recall using a TStrings class," you say. Well, you did, but you just weren't aware of it. Remember when you saved and loaded files? You used something like this: � Memo.Lines.SaveToFile(SaveDialog.FileName); The Lines property of TMemo is an instance of the TStrings class. The SaveToFile method of TStrings takes the strings and saves them to a file on disk. You can use the same technique to load a list box from a file on disk or save the contents of a list box to disk. In the case of the TListBox class, the property tha t holds the list box items is called Items. For example, try this exercise:
�
When the program runs, the list box will contain the contents of your WIN.INI file. Using this method, it's easy to load a list box from any ASCII text data file. The ComboBox component also has an Items property that works in exactly the same way. You can add, delete, insert, and move items in a list box, combo box, or memo by calling the Add, Append, Delete, Insert, and Move methods of the TStrings class.
A component can be cleared of its contents by calling the Clear method. An individual string can be accessed by using the array subscript operator. For example, to retrieve the first string in a list of strings, you would use � Edit.Text
:= ListBox.Items[0];
� Each string in a TStrings array contains the string itself and four bytes of extra storage. This extra storage can be accessed through the Objects property, and you can use the extra storage any way you like. Let's say, for example, that you create an owner-drawn list box that displays bitmaps. You can store the string in the usual way and store a pointer to the TBitmap object in the Objects array.
�
New Term: An abstract base class is a class that cannot be used directly. A descendent class must be created using the abstract base class, and an instance of the descendent class is used instead. � Standard Windows Control Components Back in the Jurassic age, there was something called Windows 3.0. Windows 3.0 gave you options such as edit controls (single line and multiline), list boxes, combo boxes, buttons, check boxes, radio buttons, and static controls. These controls must have been fairly well designed because they are very prevalent in Windows programs today--even considering all the new Win32 controls. I'm not going to go over every Windows control and its corresponding VCL component. There are a few points, though, that you should know regarding the standard components, which are covered in the next sections.
� Edit Controls Delphi comes with four edit-control components. The Edit, Memo, and MaskEdit components are based on the standard Windows edit control. The RichEdit component is based on the Win32 rich edit control, which is not one of the standard Windows controls. Still, I will discuss RichEdit here because it has many features in common with the other edit controls. � The Edit Component The Edit component encapsulates the basic single-line edit control. This component has no Align or Alignment property. It has no Alignment property because the text in a single-line edit control can only be left-justified. The Edit component has no Align property because it cannot (or more accurately, should not) be expanded to fill the client area of a window.
The MaskEdit component is an Edit component with an input filter, or mask, attached. The MaskEdit does not represent a Windows control per se, but rather is just a VCL extension of a standard edit control. A mask is used to force input to a specific range of numbers or characters. In addition, the mask can contain special characters that are placed in the edit control by default. For example, a date is commonly formatted as follows: � 03/21/98 An edit mask for a date can already have the slashes in place so the user only has to enter the numbers. The edit mask would specify that only numbers can be entered to avoid the possibility of the user entering a nonnumeric character.
The EditMask property controls the mask that is used. When you click the ellipsis button in the Value column for the EditMask property, the Input Mask Editor is displayed. This dialog box enables you to choose from one of the predefined masks or to create your own. You can choose prebuilt masks from several countries. Figure 7.3 shows the Input Mask Editor displaying the United States' set of predefined input masks. FIGURE 7.3. The Input Mask Editor. For more information on building your own masks, see the Delphi online help. � The Memo Component The Memo component encapsulates a multiline edit control. The Lines property is the most significant property in a Memo component. As I mentioned earlier in the discussion on TStrings, the Lines property enables you to save the contents of the Memo component to disk, load the Memo with text from a file, or access the memo's lines individually. The ScrollBars property is unique to the Memo component. This property enables you to specify whether your component has a horizontal scrollbar, a vertical scrollbar, or both. You used the ScrollBars property on Day 6 when you wrote the ScratchPad application. The Memo component is a very versatile component that you will probably find yourself using frequently. � The RichEdit Component The RichEdit component is the biggest and the best of all the edit components; it is based on the Win32-rich edit control. The RichEdit component enables you to change fonts, use indentation, set text to bold, italic, or underlined, and much more. Basically, the RichEdit component is a mini word processor in one neat package. RichEdit has surprisingly few design-time properties over what the Memo component has. Key runtime properties include SelAttributes and Paragraph. The RichEdit component is complex but easy to use, considering its complexi ties. See the Delphi online help for full details on the RichEdit component. � Common Edit Control Properties Table 7.4 lists the properties specific to components based on edit controls. � TABLE 7.4. PROPERTIES FOR EDIT CONTROLS. �
Edit controls have many common methods; they are too numerous to list here. The CutToClipboard, CopyToClipboard, PasteFromClipboard, and Clear methods deal with Clipboard operations and text manipulation. The GetSelTextBuff and GetTextBuff methods retrieve the selected text in the component and the entire text in the component, respectively. See the Delphi online help topics TEdit, TMaskEdit, TMemo, and TRichEdit for a complete list of methods associated with each edit component. The edit component events that you are most likely to be interested in are dependent on the type of edit control you are using. In general, though, the OnEnter, OnExit, OnChange, OnKeyDown (or OnKeyPress), and OnKeyUp events will be the most widely used. � The ListBox and ComboBox Components The ListBox and ComboBox components are also widely used. The ListBox component represents a standard Windows list box, which simply presents a list of choices that the user can choose from. If the list box contains more items than can be shown at one time, scrollbars provide access to the rest of the items in the list box. New Term: Some list boxes are owner-drawn list boxes. In an owner-drawn list box, the programmer takes the responsibility for drawing the items in the list box. You can do owner-drawn list boxes if needed. Owner-drawn list boxes are fairly common, although you might not realize it. On Day 4 I talked about customizing the Delphi toolbar. As part of that discussion, you looked at the Delphi Toolbar Editor dialog box. The Toolbar Editor dialog box contains two list boxes (see Figure 7 .4). FIGURE 7.4. The Toolbar Editor's Commands list box is owner-drawn. The list box on the left is a regular list box; it lists the possible button groups you can choose from. The list box on the right is an owner-drawn list box. It shows the actual button as it will appear on the toolbar, as well as a textual description of what function the button performs. Combo boxes are specialized list boxes. Actually, a combo box is a combination of a list box and an edit control. The user can choose from the list or type in a value in the edit portion. When the user chooses an item from the list, that item is placed in the edit control. There are three different types of combo box. The combo box type is determined by the Style property. Table 7.5 lists the types of combo boxes and a description of each. � TABLE 7.5. TYPES OF COMBO BOXES. �
The book's code contains a program called ComboTst that illustrates the different types of combo boxes. Figure 7.5 shows the test program running. Run the program and try out the combo boxes to get a feel for how each works. FIGURE 7.5. The ComboTst program. Table 7.6 lists the properties common to list boxes and combo boxes. � TABLE 7.6. PROPERTIES FOR EDIT CONTROLS. �
As with the edit components you looked at earlier, there are very few ListBox and ComboBox methods. The Clear method clears the control of all data. The ItemAtPos methods return the list box item at the specified x and y coordinates. The SelectAll method selects the text in the edit control portion of a combo box. Easily the most-used events when dealing with combo boxes and list boxes are the OnChange and OnClick events. Use these events to determine when a selection has been made in the list box.
The OnChange event can be used to detect changes to the edit portion of a combo box just as it is used with edit controls. The OnDropDown event is used to detect when the drop-down button on a combo box has been clicked. The OnMeasureItem and OnDrawItem events are used with owner-drawn list boxes and owner-drawn combo boxes. � VCL Button Types VCL contains several types of buttons that you can use in your applications. Although not all of them are based on the standard Windows button control, I will still address all the button types here. Before you look at the specific button components, though, let's cover some of the basics.
� Button Properties The button components have onl y four properties of note, as follows:
The ModalResult Property��The ModalResult property is used to provide built-in form closing for forms displayed with ShowModal. By default, ModalResult is set to mrNone (which is 0). Use this value for buttons that are used as regular buttons on the form and that don't close the form. If you use any non-zero value for ModalResult, pressing the button will close the form and return the ModalResult value. For example, if you place a button on a form and set the ModalResult property to mrOk, pressing the button will close the form, and the return value from ShowModal will be mrOk (1). Given that, then, you can do something like the following: � var ���
Exit; end; Table 7.7 lists the ModalResult constants that VCL defines. � TABLE 7.7. VCL ModalResult CONSTANTS. �
The book's code contains a program called ButtnTst that demonstrates the use of ModalResult. The program enables you to execute a form containing several buttons. When you click a button, the ModalResult will be reported on the main form. The Default Property��The Default property is another key property of buttons. Windows has a standard mechanism for dealing with dialog boxes. One of the features of this mechanism is as follows: If a control other than a button has keyboard focus and the user presses the Enter key on the keyboard, the dialog box will behave as if the user had clicked the default button. The default button is the button that has the BS_DEFPUSHBUTTON style set (usually the OK button). This feature has been the bane of programmers and the curse of data-entry personnel for years. The Default property is used to set a button as the default button for a form. The default value for this property is False. To make a button the default button, set its Default property to True. If you don't specifically set any button's Default property to True, the form will not close when the user presses the Enter key.
The Cancel Property The Cancel property works with the Esc key in much the same way as the Default property works with the Enter key. When the user presses the Esc key to close a form, the return value from ShowModal will be the ModalResult value of the button whose Cancel property is set to True. If no button has its Cancel property set to True, mrCancel will be returned if the user uses the Esc key to close the form (mrCancel is equal to 2; see Table 7.7).
The Enabled Property��Earlier I discussed the Enabled property when I discussed components in general. This property is used often with buttons to enable or disable the button depending on the current state of the program or of a particular form. When a button is disabled (its Enabled property is set to False), its text is grayed out and the button does not function. In the case of buttons with bitmaps on them (BitBtn and SpeedButton), the bitmap will also be grayed out automatically. Button components have only one method of interest: the Click method, which simulates a mouse click. When you call Click for a button, the OnClick event of the button is executed just as if the user had clicked the button. As for events, typically only the OnClick event is used. Now let's take a look at the different button components Delphi provides. � The Button Component The standard Button component is sort of like actor Danny DeVito: He ain't pretty, but he sure gets a lot of work. There really isn't anything to add concerning the standard Button component. It has a default Height property value of 25 pixels and a default Width property value of 75. Typically you will place a button on a form and respond to its OnClick event, and that's about it. � The BitBtn Component The BitBtn component is a perfect example of how a component can be extended to provide additional functionality. In this case, the standard Button component is extended to enable a bitmap to be displayed on the face of the button. The BitBtn component has several properties in addition to what the Button component provides. All these properties work together to manage the bitmap on the button and the layout between the bitmap and the button's text. They are explained in the following sections. The Glyph Property��The Glyph property represents the bitmap on the button. The value of the Glyph property is a picture, or glyph. New Term: A glyph is a picture that is usually in the form of a Windows bitmap file (BMP). The glyph itself consists of one or more bitmaps that represent the four possible states a button can be in: up, down, disabled, and stay down. If you are creating your own buttons, you can probably get by with supplying just one glyph, which the BitBtn component will then modify to represent the other three possible states. The bitmap will move down and to the right when the button is clicked and will be grayed out when disabled. The glyph in the stay-down state will be the same as in the up state, although the button face will change to give a pressed look. If you provide more than one glyph, the glyphs must all be the same height and width and must be contained in a bitmap strip. The bitmaps that ship with Delphi provide two glyphs. Figure 7.6 shows the bitmap for the print button that comes with Delphi (print.bmp) in both its actual size and zoomed in to show detail. Note that the two glyphs each occupy the same width in the bitmap. FIGURE 7.6. The PRINT.BMP bitmap. � �
To set the glyph for a BitBtn, double-click the Value column in the Object Inspector next to the Glyph property. The Picture Editor will be displayed, and you can choose the bitmap that will be used for the glyph.
The Kind Property��The Kind property is a nice feature of the BitBtn component that enables you to choose from several predefined kinds of buttons. The default value for the Kind property is bkCustom, which means that you will supply the glyph and set any other properties for the button. Choosing any of the other predefined kinds will result in these five events happening:
For example, if you set the value of Kind to bkOK, the button will become an OK button. The glyph is set to a green check mark, the Cancel property is set to False, the Default property is set to True, the ModalResult property is set to mrOk, the Caption property is set to OK, and the results show up on the form. You can always override any of the properties modified by changing the Kind property, but it is not usually necessary to do so. Figure 7.7 shows the Button Test program from the code that comes with this book, with the BitBtn Test form displayed. The form contains each of the predefined button types available plus one custom button. The Layout Property��The Layout property determines where the button is placed relative to the text. The default is blGlyphLeft. You can also choose to place the glyph on the face of the button to the right of the text, above the text, or below the text. FIGURE 7.7.< /B> The predefined BitBtn types. The Margin Property��The Margin property specifies the margin between the glyph and the edge of the button (which edge this property affects is determined by the value of the Layout property). The default is -1, which centers the glyph and the text in the button. Enter any positive value to set an absolute margin (in pixels). The NumGlyphs Property��The NumGlyphs property specifies the number of glyphs you have in your bitmap strip for a particular button. You can supply from one to four glyphs, as I've mentioned. The glyphs must appear in the bitmap strip in this order: up, disabled, down, stay down. The Spacing Property��The Spacing property controls the distance in pixels between the glyph and the button's text. The default value is four pixels. � The SpeedButton Component The SpeedButton component was designed to be used with the Panel component to build toolbars. It is different from the Button and BitBtn components in that it is not a windowed component. This means that a speed button cannot receive input focus and cannot be tabbed to. On the other hand, the SpeedButton component has several features in common with the BitBtn component. The way in which the Glyph property is handled by the SpeedButton component is exactly the same as with the BitBtn component, so I'm not going to go over that ground again. There are a couple of major differences, though, so let's look at those. By default, speed buttons are square and are 25�25 pixels. Your speed buttons can be any size you like and can contain text, although speed buttons don't usually contain text. There are some properties specific to speed buttons that you should be aware of, which I've broken down in the following sections.
GroupIndex��Speed buttons can be grouped to make them behave like radio buttons (radio buttons will be discussed later in this chapter in the section "Radio Buttons and Check Boxes"). When one button in the group is pressed, it stays down, and the button that was previously pressed pops up again. To group speed buttons, simply assign the same value to the GroupIndex property for all buttons in a group. (The default value of 0 indicates that the button is not part of any group.) To better understand this, try the following exercise:
1. Create a blank form and place five speed buttons on the form. (I won't bother adding glyphs to the buttons in this simple exercise, but you certainly can if you want.) �
� 2. Select all the buttons and change the value of the GroupIndex property to 1. The GroupIndex for all buttons will be changed to 1. �
� 3. Optional: Change the Down property of one of the buttons to True. �
� 4. Click the Run button to compile and run the program. � When you run the program, click several of the buttons. You will notice that only one button can be in the down state at one time. As you can see when you assign a nonzero value to GroupIndex, the speed buttons change their behavior. A speed button with a GroupIndex of 0 pops back up when you click it, whereas a speed button that is part of a group stays down when clicked. AllowAllUp��By default, one button in the group must be down at all times. You can change that behavior by setting the AllowAllUp property to True. Doing this for one button automatically changes the AllowAllUp property for all other buttons in the group to True as well. Now you can have any one button in the group selected or no buttons.
Down��The Down property, when read, returns True if the button is currently down and False if it is not. When written to, the Down property can be used to toggle a button as pressed or not pressed. Writing to the Down property has no effect unless the speed button is part of a group. � Radio Buttons and Check Boxes Although radio buttons and check boxes are specialized buttons, they are, in the end, still buttons. I'm not going to spend a lot of time discussing these two components because implementing them is straightforward. Both the RadioButton and CheckBox components have a property called Checked that can be used to set the check state and can be read to retrieve the current check state. The radio button is usually used in a group of buttons. A radio button typically signifies a group of options, only one of which can be selected at one time (like a group of speed buttons, which you just learned about). Although you can use a radio button by itself, it is not recommended because it is confusing to your users. When tempted to use a radio button by itself, use a check box instead--that's what a check box is for, after all. Any radio buttons placed on a form will automatically be considered part of the same group. If you have more than one group of radio buttons, and those groups need to operate independent of one another, you need to use a RadioGroup compon ent. This component enables you to quickly set up a group of radio buttons with a 3D frame around the buttons and a caption as well. To better understand this concept, try the following exercise:
1. Create a blank form or use the form you created in the previous exercise. Place a RadioGroup component on the form (you will find it on the Standard tab). �
� 2. Locate the Items property and double-click the Value column. �
� 3. The String list editor is displayed. Type the following lines in the String list editor: �
�
When you click one of the radio buttons, the previously selected button pops up as expected. Using the RadioGroup component, you can put more than one group of radio buttons on a form. Like the list box and combo box components discussed earlier, the RadioGroup component has an ItemIndex property that you can read at runtime to determine which item in the group is selected. You can also set the ItemIndex to force a particular radio button to be selected. You might have noticed that none of the radio buttons were selected when the application ran. Change the ItemIndex to 0 in the Object Inspector and run the program again. This time the first radio button is selected. Oh, by the way--if you live in the U.S., the answer to the quiz is Redtailed Hawk (American Kestrel would also have been an acceptable answer, but it was not presented in the list).
The CheckBox component is used to enable users to turn an option on or off or to indicate to a user that an option is currently on or off. A check box can have up to three states, depending on its style: on, off, or grayed. If the check box's AllowGrayed property is False, it can only be checked or unchecked. When the AllowGrayed property is True, the check box can be any one of the three states. The grayed, or indeterminate, state is handled programmatically. In other words, it's up to you to decide what the grayed state means for your application. If the AllowGrayed property is False (the default), you can use the Checked property to determine whether the check box is checked or unchecked. If the AllowGrayed property is True, you must use the State property to determine (or set) the check box state. State will return cbChecked, cbUnchecked, or cbGrayed.
� The Label Component The Label component is used to display text on a form. Sometimes the label text is determined at design time and never changed. In other cases, the label is dynamic and is changed at runtime as the program dictates. Use the label's Caption property to set the label text at runtime. The Label component has no specialized methods or events beyond what is ava ilable with other components. Table 7.8 lists the properties specific to the Label component. � TABLE 7.8. PROPERTIES FOR THE Label COMPONENT. �
� The ScrollBar Component The ScrollBar component represents a stand-alone scrollbar. It's standalone in the sense that it is not connected to an edit control, list box, form, or anything else. I have not found that the scrollbar is a control I use very frequently. Certain types of applications use scrollbars heavily, of course, but for day-in, day-out applications its use is fairly uncommon. The scrollbar's performance is set by setting the Min, Max, LargeChange, and SmallChange properties. The scrollbar's position can be set or obtained via the Position property. The Kind property enables you to specify a horizontal or vertical scrollbar. � The Panel Component The Panel component is sort of a workhorse in Delphi. There is almost no limit to what you can use panels for. Panels can be used to hold toolbar buttons, to display text labels such as a title for a form, to display graphics, and to hold regular buttons as well. One of the advantages of a panel is that components placed on the panel become children of the panel. As such, they go with the panel wherever the panel goes. This can be a great aid at runtime and at design time. Much of the power of the Panel component lies in its Align property. For example, let's say you want a title to be displayed on the top of a form. Let's further assume that you want it centered no matter how the user sizes the window. By setting the Align property to alTop and the Alignment property to taCenter, your title will always be centered. It's as simple as that. A panel can have many appearances. The panel's appearance can be altered by changing the BevelInner, BevelOuter, BorderStyle, and Bo rderWidth properties, as displayed in Figure 7.8. FIGURE 7.8. The Panel Styles Example showing different styles. The Panel component is so versatile that it will take you a while to discover all its possible uses. � And That's Not All... Unfortunately, there isn't sufficient space here to go over all the components Delphi provides. You saw the Image component on Day 4 when you created the Picture Viewer program. You also got a brief glimpse at the Bevel component on Day 4 when you built an About dialog box, and the Shape component on Day 6 as part of an exercise in aligning components. These represent just a sampling of the components that are waiting for you. You need to test drive each one of them to determine their usefulness for you. There is one other group of components that I need to discuss before you move on: the Dialog group. � The Common Dialog Boxes Windows provides a set of common dialog boxes that any Windows program can use, including the following:
The common dialog boxes are found on the Dialogs tab of the Component palette. These components are considered nonvisual because they don't have a visual design-time interface. The following sections discuss each of these dialog boxes with one exception--I'll leave the discussion of the Print and Printer Setup dialog boxes for Day 13 when I discuss printing. � The Execute Method One feature that all the common dialog boxes have in common is the Execute method, which is used to create and display the dialog box. The dialog box is displayed modally except for the Find and Replace dialog boxes, which are displayed modelessly. Execut e returns True if the user clicked the OK button, double-clicked a file name (in the case of the file dialogs), or pressed Enter on the keyboard. Execute returns False if the user clicked the Cancel button, pressed the Esc key, or closed the dialog box with the system close box. A common dialog box is often implemented like this: � if
OpenDialog.Execute then begin This code displays the File Open dialog box and gets a filename from the user. If the user clicked the OK button, the code inside the if block is executed and the file is loaded in to a Memo component. If OK was not pressed, the code inside the if block is ignored and no action takes place.
�
�
� The File Open and File Save Dialog Boxes The File Open and File Save dialog boxes have several properties in common. File Open is used when you want to allow the user to open a file in your application (see Figure 7.9). It is encapsulated in the OpenDialog component. The File Save dialog box is used when getting a filename from the user in order to save a file. It is also used as the Save As dialog box. The File Save dialog box is encapsulated by the SaveDialog component. FIGURE 7.9. A typical File Open dialog box. The file dialog boxes are fairly easy to use in their most basic form. They do have a few features, however, that need to be explained in order for you t o get the full benefit of using them. The following sections examine the properties that are specific to the file dialog boxes.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||