MASTERING DELPHI 6 phần 3 ppsx

108 236 0
MASTERING DELPHI 6 phần 3 ppsx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

209 When you set a font, either by entering values for the attributes of the property in the Object Inspector or by using the standard font selection dialog box, you can choose one of the fonts installed in the system. The fact that Delphi allows you to use all the fonts installed on your system has both advantages and drawbacks. The main advantage is that if you have a number of nice fonts installed, your program can use any of them. The drawback is that if you distribute your application, these fonts might not be available on your users’ computers. If your program uses a font that your user doesn’t have, Windows will select some other font to use in its place. A program’s carefully formatted output can be ruined by the font sub- stitution. For this reason, you should probably rely only on standard Windows fonts (such as MS Sans Serif, System, Arial, Times New Roman, and so on). Colors There are various ways to set the value of a color. The type of this property is TColor. For properties of this type, you can choose a value from a series of predefined name constants or enter a value directly. The constants for colors include clBlue, clSilver, clWhite, clGreen, clRed, and many others. TIP Delphi 6 adds four new standard colors: clMoneyGreen, clSkyBlue, clCream, and clMedGray. As a better alternative, you can use one of the colors used by the system to denote the sta- tus of given elements. These sets of colors are different in VCL and CLX. VCL includes pre- defined Windows colors such as the background of a window (clWindow), the color of the text of a highlighted menu (clHightlightText), the active caption (clActiveCaption), and the ubiqui- tous button face color (clBtnFace). CLX includes a different and incompatible set of system colors, including clBackground, which is the standard color of a form; clBase, used by edit boxes and other visual controls; clActiveForeground, the foreground color for active controls; and clDisabledBase, the back- ground color for disabled text controls. All the color constants mentioned here are listed in VCL and CLX Help files under the “TColor type” topic. Another option is to specify a TColor as a number (a 4-byte hexadecimal value) instead of using a predefined value. If you use this approach, you should know that the low three bytes of this number represent RGB color intensities for blue, green, and red, respectively. For example, the value $00FF0000 corresponds to a pure blue color, the value $0000FF00 to green, the value $000000FF to red, the value $00000000 to black, and the value $00FFFFFF to white. By specifying intermediate values, you can obtain any of 16 million possible colors. Instead of specifying these hexadecimal values directly, you should use the Windows RGB function, which has three parameters, all ranging from 0 to 255. The first indicates the amount of red, the second the amount of green, and the last the amount of blue. Using the RGB function makes programs generally more readable than using a single hexadecimal TControl and Derived Classes Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 210 constant. Actually, RGB is almost a Windows API function. It is defined by the Windows- related units and not by Delphi units, but a similar function does not exist in the Windows API. In C, there is a macro that has the same name and effect, so this is a welcome addition to the Pascal interface to Windows. RGB is not available on CLX, so I’ve written my own ver- sion as: function RGB (red, green, blue: Byte): Cardinal; begin Result := blue + green * 256 + red * 256 * 256; end; The highest-order byte of the TColor type is used to indicate which palette should be searched for the closest matching color, but palettes are too advanced a topic to discuss here. (Sophisticated imaging programs also use this byte to carry transparency information for each display element on the screen.) Regarding palettes and color matching, note that Win- dows sometimes replaces an arbitrary color with the closest available solid color, at least in video modes that use a palette. This is always the case with fonts, lines, and so on. At other times, Windows uses a dithering technique to mimic the requested color by drawing a tight pattern of pixels with the available colors. In 16-color (VGA) adapters and at higher resolu- tions, you often end up seeing strange patterns of pixels of different colors and not the color you had in mind. The TWinControl Class (VCL) In Windows, most elements of the user interface are windows. From a user standpoint, a window is a portion of the screen surrounded by a border, having a caption and usually a sys- tem menu. But technically speaking, a window is an entry in an internal system table, often corresponding to an element visible on the screen that has some associated code. Most of these windows have the role of controls; others are temporarily created by the system (for example, to show a pull-down menu). Still other windows are created by the application but remain hidden from the user and are used only as a way to receive a message (for example, nonblocking sockets use windows to communicate with the system). The common denominator of all windows is that they are known by the Windows system and refer to a function for their behavior; each time something happens in the system, a noti- fication message is sent to the proper window, which responds by executing some code. Each window of the system, in fact, has an associated function (generally called its window procedure), which handles the various messages the window is interested in. In Delphi, any TWinControl class can override the WndProc method or define a new value for the WindowProc property. Interesting Windows messages, however, can be better tracked by providing specific message handlers. Even better, VCL converts these lower-level mes- sages into events. In short, Delphi allows us to work at a high level, making application development easier, but still allows us to go low-level when this is required. Chapter 6 • Controls: VCL Versus VisualCLX Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 211 Notice also that creating a WinControl doesn’t automatically create its corresponding Window handle. Delphi, in fact, uses a lazy initialization technique, so that the low control is only created when this is required, generally as soon as a method accesses the Handle prop- erty. The get method for this property the first time calls HandleNeeded, which eventually calls CreateHandle… and so on reaching CreateWnd, CreateParams, and CreateWindowHandle (the sequence is rather complex, and I don’t think it is necessary to know it in detail). At the opposite end, you can keep an existing (perhaps invisible) control in memory but destroy its window handle, to save system resources. The TWidgetControl Class (CLX) In CLX, every TWidgetControl has an internal Qt object, referenced using the Handle prop- erty. This property has the same name as the corresponding Windows property, but it is totally different behind the scenes. The Qt object is generally owned by the TWidgetControl, which automatically frees the object when it is destroyed. The class also uses delayed construction, as you can see in the InitWidget method, similar to CreateWindow. However it is also possible to create a widget around an existing Qt object: in this case, the widget won’t own the Qt object and won’t destroy it. The behavior is indicated by the OwnHandle property. Actually each VisualCLX component has two associated C++ objects, the Qt Handle and the Qt Hook, which is the object receiving the system events. With the current Qt design, this has to be a C++ object, which acts as an intermediary to the event handlers of the Object Pas- cal control. The HookEvents method associates the hook object to the CLX control. Differently from Windows, Qt defines two different types of events: • Events are the translation of input or system events (such as key press, mouse move, and paint). • Signals are internal component events (corresponding to VCL internal or abstract operations, such as OnClick and OnChange) NOTE In CLX there is a seldom-used EventHandler method, which corresponds more or less to the WndProc method of VCL. Opening the Component Tool Box So you want to write a Delphi application. You open a new Delphi project and find yourself faced with a large number of components. The problem is that for every operation, there are multiple alternatives. For example, you can show a list of values using a list box, a combo box, Opening the Component Tool Box Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 212 a radio group, a string grid, a list view, or even a tree view if there is a hierarchical order. Which should you use? That’s difficult to say. There are many considerations, depending on what you want your application to do. For this reason, I’ve provided a highly condensed summary of alternative options for a few common tasks. NOTE For some of the controls described in the following sections, Delphi also includes a data-aware version, usually indicated by the DB prefix. As you’ll see in Chapter 13, “Delphi’s Database Architecture,” the DB version of a control typically serves a role similar to that of its “stan- dard” equivalent; but the properties and the ways you use it are often quite different. For example, in an Edit control you use the Text property, while in a DBEdit component you access the Value of the related field object. The Text Input Components Although a form or component can handle keyboard input directly, using the OnKeyPress event, this isn’t a common operation. Windows provides ready-to-use controls you can use to get string input and even build a simple text editor. Delphi has several slightly different com- ponents in this area. The Edit Component The Edit component allows the user to enter a single line of text. You can also display a single line of text with a Label or a StaticText control, but these components are generally used only for fixed text or program-generated output, not for input. In CLX, there is also a native LCD digit control you can use to display numbers. The Edit component uses the Text property, whereas many other controls use the Caption property to refer to the text they display. The only condition you can impose on user input is the number of characters to accept. If you want to accept only specific characters, you can handle the OnKeyPress event of the edit box. For example, we can write a method that tests whether the character is a number or the Backspace key (which has a numerical value of 8). If it’s not, we change the value of the key to the null character (#0), so that it won’t be processed by the edit control and will produce a warning beep: procedure TForm1.Edit1KeyPress( Sender: TObject; var Key: Char); begin // check if the key is a number or backspace if not (Key in [‘0’ ’9’, #8]) then begin Key := #0; Beep; end; end; Chapter 6 • Controls: VCL Versus VisualCLX Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 213 NOTE A minor difference of CLX is that the Edit control has no Undo mechanism built in. Another is that the PasswordChar property is replaced by the EchoMode property. You don’t determine the character to display, but whether to echo the entered text or display an asterisk instead. The New LabeledEdit Control Delphi 6 adds a very nice control, called LabeledEdit, which is an Edit control with a label attached to it. The Label appears as a property of the compound control, which inherits from TCustomEdit. I have to say this component is very handy, because it allows you to reduce the number of components on your forms, move them around more easily, and have a more standard layout for labels, particularly when they are placed above the edit box. The EditLabel property is connected with the subcomponent, which has the usual properties and events. Two more properties, LabelPosition and LabelSpacing, allow you to configure the relative positions of the two controls. NOTE This component has been added to the ExtCtrls unit to demonstrate the use of subcompo- nents in the Object Inspector, which is a new feature of Delphi 6. I’ll discuss the development of these components in Chapter 11, “Creating Components.” Notice also that this compo- nent, along with all of the other new Delphi 6 components, is not (yet) available on CLX and on the first release of Kylix. However, we can expect all non–Windows-specific additions to VCL, including subcomponents in general and the LabeledEdit control in particular, to be avail- able in the next release of Kylix. The MaskEdit Component To customize the input of an edit box further, you can use the MaskEdit component, which has an EditMask property. This is a string indicating for each character whether it should be uppercase, lowercase, or a number, and other similar conditions. You can see the editor of the EditMask property in Figure 6.3. FIGURE 6.3: The MaskEdit component’s EditMask property editor Opening the Component Tool Box Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 214 TIP You can display any property’s editor by selecting the property in the Object Inspector and clicking the ellipsis (…) button. The Input Mask editor allows you to enter a mask, but it also asks you to indicate a charac- ter to be used as a placeholder for the input and to decide whether to save the literals present in the mask, together with the final string. For example, you can choose to display the paren- theses around the area code of a phone number only as an input hint or to save them with the string holding the resulting number. These two entries in the Input Mask editor correspond to the last two fields of the mask (separated by semicolons). TIP Clicking the Masks button of the Mask Editor lets you choose predefined input masks for dif- ferent countries. The Memo and RichEdit Components Both of the controls discussed so far allow a single line of input. The Memo component, by contrast, can host several lines of text but (on the Win95/98 platforms) still retains the 16-bit Windows text limit (32 KB) and allows only a single font for the entire text. You can work on the text of the memo line by line (using the Lines string list) or access the entire text at once (using the Text property). If you want to host a large amount of text or change fonts and paragraph alignments, in VCL you should use the RichEdit control, a Win32 common control based on the RTF document format. You can find an example of a complete editor based on the RichEdit component among the sample programs that ship with Delphi. (The example is named RichEdit, too.) The RichEdit component has a DefAttributes property indicating the default styles and a SelAttributes property indicating the style of the current selection. These two properties are not of the TFont type, but they are compatible with fonts, so we can use the Assign method to copy the value, as in the following code fragment: procedure TForm1.Button1Click(Sender: TObject); begin if RichEdit1.SelLength > 0 then begin FontDialog1.Font.Assign (RichEdit1.DefAttributes); if FontDialog1.Execute then RichEdit1.SelAttributes.Assign (FontDialog1.Font); end; end; Chapter 6 • Controls: VCL Versus VisualCLX Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 215 The TextViewer CLX Control Among all of the common controls, CLX and Qt lack a RichEdit control. However, they provide a full-blown HTML viewer, which is very powerful for displaying formatted text but not for typing it. This HTML viewer is embedded in two different controls, the single-page TextViewer control or the TextBrowser control with active links. As a simple demo, I’ve added a memo and a text viewer to a CLX form and connected them so that everything you type on the memo is immediately displayed in the viewer. I’ve called the example HtmlEdit not because this is a real HTML editor, but because this is the simplest way I know of to build an HTML preview inside a program. The form of the pro- gram is visible at run time in Figure 6.4, while typing some text inside a cell of the table. TIP I originally built this example with Kylix on Linux. To port it to Windows and Delphi 6, all I had to do was to copy the files and recompile. Selecting Options There are two standard Windows controls that allow the user to choose different options, as well as controls for grouping sets of options. FIGURE 6.4: The HtmlEdit example at run time: when you add new HTML text to the memo, you get an immediate preview. Opening the Component Tool Box Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 216 The CheckBox and RadioButton Components The first standard option-selecting control is the check box, which corresponds to an option that can be selected regardless of the status of other check boxes. Setting the AllowGrayed property of the check box allows you to display three different states (selected, not selected, and grayed), which alternate as a user clicks the check box. The second type of control is the radio button, which corresponds to an exclusive selection. Two radio buttons on the same form or inside the same radio group container cannot be selected at the same time, and one of them should always be selected (as programmer, you are responsible for selecting one of the radio buttons at design time). The GroupBox Components To host several groups of radio buttons, you can use a GroupBox control to hold them together, both functionally and visually. To build a group box with radio buttons, simply place the GroupBox component on a form and then add the radio buttons to the group box. You can handle the radio buttons individually, but it’s easier to navigate through the array of controls owned by the group box, as discussed in the previous chapter. Here is a small code excerpt used to get the text of the selected radio button of a group: var I: Integer; Text: string; begin for I := 0 to GroupBox1.ControlCount - 1 do if (GroupBox1.Controls[I] as TRadioButton).Checked then Text := (GroupBox1.Controls[I] as TRadioButton).Caption; The RadioGroup Component Delphi has a similar component that can be used specifically for radio buttons: the RadioGroup component. A RadioGroup is a group box with some radio button clones painted inside it. The term clone in this context refers to the fact that the RadioGroup component is a single control, a single window, with elements similar to radio buttons painted on its surface. Using the radio group is generally easier than using the group box, since the various items are part of a list, as in a list box. This is how you can get the text of the selected item: Text := RadioGroup1.Items [RadioGroup1.ItemIndex]; Technically, a RadioGroup uses fewer resources and less memory, and it should be faster to create and paint. Also, the RadioGroup component can automatically align its radio buttons in one or more columns (as indicated by the Columns property), and you can easily add new choices at run time, by adding strings to the Items string list. By contrast, adding new radio buttons to a group box would be quite complex. Chapter 6 • Controls: VCL Versus VisualCLX Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 217 Lists When you have many selections, radio buttons are not appropriate. The usual number of radio buttons is no more than five or six, to avoid cluttering the user interface; when you have more choices, you can use a list box or one of the other controls that display lists of items and allow the selection of one of them. The ListBox Component The selection of an item in a list box uses the Items and ItemIndex properties as in the code shown above for the RadioGroup control. If you need access to the text of selected list box items often, you can write a small wrapper function like this: function SelText (List: TListBox): string; var nItem: Integer; begin nItem := List.ItemIndex; if nItem >= 0 then Result := List.Items [nItem] else Result := ‘’; end; Another important feature is that by using the ListBox component, you can choose between allowing only a single selection, as in a group of radio buttons, and allowing multiple selec- tions, as in a group of check boxes. You make this choice by specifying the value of the MultiSelect property. There are two kinds of multiple selections in Windows and in Delphi list boxes: multiple selection and extended selection. In the first case, a user selects multiple items simply by clicking them, while in the second case the user can use the Shift and Ctrl keys to select multiple consecutive or nonconsecutive items, respectively. This second choice is determined by the ExtendedSelect property. For a multiple-selection list box, a program can retrieve information about the number of selected items by using the SelCount property, and it can determine which items are selected by examining the Selected array. This array of Boolean values has the same number of entries as the list box. For example, to concatenate all the selected items into a string, you can scan the Selected array as follows: var SelItems: string; nItem: Integer; begin SelItems := ‘’; for nItem := 0 to ListBox1.Items.Count - 1 do if ListBox1.Selected [nItem] then SelItems := SelItems + ListBox1.Items[nItem] + ‘ ‘; Opening the Component Tool Box Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 218 In CLX the ListBox can be configured to use a fixed number of columns and rows, using the Columns, Row, ColumnLayout and RowLayout properties. Of these, the VCL ListBox has only the Columns property. The ComboBox Component List boxes take up a lot of screen space, and they offer a fixed selection—that is, a user can choose only among the items in the list box and cannot enter any choice that the program- mer did not specifically foresee. You can solve both problems by using a ComboBox control, which combines an edit box and a drop-down list. The behavior of a ComboBox component changes a lot depending on the value of its Style property: • The csDropDown style defines a typical combo box, which allows direct editing and displays a list box on request. • The csDropDownList style defines a combo box that does not allow editing (but uses the keystrokes to select an item). • The csSimple style defines a combo box that always displays the list box below it. Note also that accessing the text of the selected value of a ComboBox is easier than doing the same operation for a list box, since you can simply use the Text property. A useful and common trick for combo boxes is to add a new element to the list when a user enters some text and presses the Enter key. The following method first tests whether the user has pressed that key, by looking for the character with the numeric (ASCII) value of 13. It then tests to make sure the text of the combo box is not empty and is not already in the list—if its position in the list is less than zero. Here is the code: procedure TForm1.ComboBox1KeyPress( Sender: TObject; var Key: Char); begin // if the user presses the Enter key if Key = Chr (13) then with ComboBox3 do if (Text <> ‘’) and (Items.IndexOf (Text) < 0) then Items.Add (Text); end; NOTE In CLX, the combo box can automatically add the text typed into the edit to the drop-down list, when the user presses the Enter key. Also, some events fire at different times than in VCL. Chapter 6 • Controls: VCL Versus VisualCLX Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com [...]... Component Delphi applications often use the name/value structure natively offered by string lists, which I discussed in the last chapter Delphi 6 introduces a version of the StringGrid component specifically geared towards this type of string lists The ValueListEditor has two columns where you can display and let the user edit the contents of a string list with name/value pairs, as you can see in Figure 6. 6... a specific menu item), which displays the font selection dialog box You can see the dynamic menu in Figure 6. 9 FIGURE 6. 9: The Size pull-down menu of the DynaMenu example is created at run time, along with all of its menu items Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 232 Chapter 6 • Controls: VCL Versus VisualCLX WARNING Because the program uses the Caption of the new items dynamically,... (shown in Figure 6. 11), then import existing bitmap or icon files You can actually prepare a single large bitmap and let the image editor divide it according to the Height and Width properties of the ImageList component, which refer to the size of the individual bitmaps in the list Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 234 Chapter 6 • Controls: VCL Versus VisualCLX FIGURE 6. 11: The Image... or the hexadecimal value, there is also a Delphi function to convert a properly formatted string into a color, StringToColor In the ODList example, this method is called in the OnCreate event handler of the form (after previously setting the height of the items): AddColors ([clRed, clBlue, clYellow, clGreen, clFuchsia, clLime, clPurple, clGray, RGB (2 13, 23, 1 23) , RGB (0, 0, 0), clAqua, clNavy, clOlive,... ellipsis (three dots) after the text As you enter new elements in the Menu Designer, Delphi creates a new component for each menu item and lists it in the Object Inspector (although nothing is added to the form) To name each component, Delphi uses the caption you enter and appends a number (so that Open becomes Open1) Because Delphi removes spaces and other special characters in the caption when it creates... check boxes can be grayed) Delphi 5 introduced the ItemEnabled array property, which you can use to enable or disable each item of the list We’ll use the CheckListBox in the DragList example, later in this chapter FIGURE 6. 5: The user interface of the CheckListBox control, basically a list of check boxes Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 220 TIP Chapter 6 • Controls: VCL Versus VisualCLX... Alameda, CA www.sybex.com Working with Menus 233 When you want to create a menu or a menu item dynamically, you can use the corresponding components, as I’ve done in the DynaMenu and QDynaMenu examples As an alternative, you can also use some global functions available in the Menus unit: NewMenu, NewPopupMenu, NewSubMenu, NewItem, and NewLine Using Menu Images In Delphi it is very easy to improve a program’s... in Delphi using specific properties of the form and the other components hosting them Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com Opening the Component Tool Box 2 23 The TrackBar and ProgressBar Components Direct use of the ScrollBar component is quite rare, especially with the TrackBar component introduced with Windows 95, which is used to let a user select a value in a range Among Win32... in Delphi, we have to define a new message-response method for the form class: public procedure WMSysCommand (var Msg: TMessage); message wm_SysCommand; The code of this procedure is not very complex We just need to check whether the command is our own and call the default handler: procedure TForm1.WMSysCommand (var Msg: TWMSysCommand); begin if Msg.CmdType = idSysAbout then ShowMessage ( Mastering Delphi: ... menu, instead of adding and handling each menu item as we have just done, we can follow a different approach Just add a MainMenu component to Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 2 36 Chapter 6 • Controls: VCL Versus VisualCLX the form, create its structure (any structure will do), and write the proper event handlers Then reset the value of the Menu property of the form, removing the . feature of Delphi 6. I’ll discuss the development of these components in Chapter 11, “Creating Components.” Notice also that this compo- nent, along with all of the other new Delphi 6 components,. and other similar conditions. You can see the editor of the EditMask property in Figure 6. 3. FIGURE 6. 3: The MaskEdit component’s EditMask property editor Opening the Component Tool Box Copyright. as: function RGB (red, green, blue: Byte): Cardinal; begin Result := blue + green * 2 56 + red * 2 56 * 2 56; end; The highest-order byte of the TColor type is used to indicate which palette should

Ngày đăng: 12/08/2014, 21:20

Tài liệu cùng người dùng

Tài liệu liên quan