1. Trang chủ
  2. » Công Nghệ Thông Tin

MASTERING DELPHI 6 phần 4 docx

108 188 0

Đ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

Thông tin cơ bản

Định dạng
Số trang 108
Dung lượng 631,01 KB

Nội dung

317 OnGetItem = VirtualListAction1GetItem OnGetItemCount = VirtualListAction1GetItemCount OnItemSelected = ListActionItemSelected end object ListControlCopySelection1: TListControlCopySelection Caption = ‘Copy’ Destination = ListBox2 ListControl = ListBox1 end object ListControlDeleteSelection1: TListControlDeleteSelection Caption = ‘Delete’ end object ListControlMoveSelection2: TListControlMoveSelection Caption = ‘Move’ Destination = ListBox2 ListControl = ListBox1 end end The program has also two list boxes in its form, used as action targets. The Copy and Move actions are tied to these two list boxes by their ListControl and Destination properties. The Delete action, instead, automatically works with the list box having the input focus. The StaticListAction defines a series of alternative items, in its Items collection. This is not a plain string list, as any item has also an ImageIndex, which allows turning the combo box in graphical selection. You can, of course, add more items to this list programmatically. However, in case of a highly dynamic list, you can also use the VirtualListAction. This com- ponent doesn’t define a list of items but has two events you can use to provide strings and images for the list. The OnGetItemCount event allows you to indicate the number of items to display; the OnGetItem event is then called for each specific item. In the ListActions demo, the VirtualListAction has the following event handlers for its def- inition, producing the list you can see in the active combo box of Figure 8.12: procedure TForm1.VirtualListAction1GetItemCount(Sender: TCustomListAction; var Count: Integer); begin Count := 100; end; procedure TForm1.VirtualListAction1GetItem(Sender: TCustomListAction; const Index: Integer; var Value: String; var ImageIndex: Integer; var Data: Pointer); begin Value := ‘Item’ + IntToStr (Index); end; The ActionManager Architecture Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 318 NOTE I thought that the virtual action items were actually requested only when needed to display them, making this actually a virtual list. Instead, all the items are created right away, as you can prove by enabling the commented code of the VirtualListAction1GetItem method (not in the listing above), which adds to each item the time its string is requested. Both the static and the virtual list have an OnItemSelected event. In the shared event handler, I’ve written the following code, to add the current item to the first list box of the form: procedure TForm1.ListActionItemSelected(Sender: TCustomListAction; Control: TControl); begin ListBox1.Items.Add ((Control as TCustomActionCombo).SelText); end; In this case, the sender is the custom action list, but the ItemIndex property of this list is not updated with the selected item. However, accessing the visual control that displays the list, we can obtain the value of the selected item. FIGURE 8.12: The ListActions application has a toolbar hosting a static list and a virtual one. Chapter8 • Building the User Interface Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 319 What’s Next? In this chapter, I’ve introduced the use of actions, the actions list, and action manager archi- tectures. As you’ve seen, this is an extremely powerful architecture to separate the user inter- face from the actual code of your applications, which uses and refers to the actions and not the menu items or toolbar button related to them. The Delphi 6 extension of this architec- ture allows users of your programs to have a lot of control, and makes your applications resemble high-end programs without much effort on your part. The same architecture is also very handy to let you design the user interface of your program, regardless of whether you give this ability to users. I’ve also covered other user-interface techniques, such as docking toolbars and other con- trols. You can consider this chapter the first step toward building professional applications. We will take other steps in the following chapters; but you already know enough to make your programs similar to some best-selling Windows applications, which may be very impor- tant for your clients. Now that the elements of the main form of our programs are properly set up, we can con- sider adding secondary forms and dialog boxes. This is the topic of the next chapter, along with a general introduction to forms. The following chapter will then cover the overall struc- ture of a Delphi application. What’s Next? Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 9 CHAPTER Working with Forms ● Form styles, border styles, and border icons ● Mouse and keyboard input ● Painting and special effects ● Positioning, scaling, and scrolling forms ● Creating and closing forms ● Modal and modeless dialog boxes and forms ● Creating secondary forms dynamically ● Predefined dialog boxes ● Building a splash screen Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 322 If you’ve read the previous chapters, you should now be able to use Delphi’s visual compo- nents to create the user interface of your applications. So let’s turn our attention to another central element of development in Delphi: forms. We have used forms since the initial chap- ters, but I’ve never described in detail what you can do with a form, which properties you can use, or which methods of the TForm class are particularly interesting. This chapter looks at some of the properties and styles of forms and at sizing and position- ing them. I’ll also introduce applications with multiple forms, the use of dialog boxes (custom and predefined ones), frames, and visual form inheritance. I’ll also devote some time to input on a form, both from the keyboard and the mouse. The TForm Class Forms in Delphi are defined by the TForm class, included in the Forms unit of VCL. Of course, there is now a second definition of forms inside VisualCLX. Although I’ll mainly refer to the VCL class in this chapter, I’ll also try to highlight differences with the cross-platform version provided in CLX. The TForm class is part of the windowed-controls hierarchy, which starts with the TWinControl (or TWidgetControl) class. Actually, TForm inherits from the almost complete TCustomForm, which in turn inherits from TScrollingWinControl (or TScrollingWidget). Having all of the features of their many base classes, forms have a long series of methods, properties, and events. For this reason, I won’t try to list them here, but I’d rather present some interesting techniques related to forms throughout this chapter. I’ll start by presenting a technique for not defining the form of a program at design time, using the TForm class directly, and then explore a few interesting properties of the form class. Throughout the chapter, I’ll point out a few differences between VCL forms and CLX forms. I’ve actually built a CLX version for most of the examples of this chapter, so you can immediately start experimenting with forms and dialog boxes in CLX, as well as VCL. As in past chapters, the CLX version of each example is prefixed by the letter Q. Using Plain Forms Generally, Delphi developers tend to create forms at design time, which implies deriving a new class from the base one, and build the content of the form visually. This is certainly a reasonable standard practice, but it is not compulsory to create a descendant of the TForm class to show a form, particularly if it is a simple one. Consider this case: you have to show a rather long message (based on a string) to a user, and you don’t want to use the simple predefined message box, as it will show up too large and Chapter 9 • Working with Forms Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 323 not provide scroll bars. You can create a form with a memo component in it, and display the string inside it. Nothing prevents you from creating this form in the standard visual way, but you might consider doing this in code, particularly if you need a large degree of flexibility. The DynaForm and QDynaForm examples (both on the companion CD), which are somewhat extreme, have no form defined at design time but include a unit with this function: procedure ShowStringForm (str: string); var form: TForm; begin Application.CreateForm (TForm, form); form.caption := ‘DynaForm’; form.Position := poScreenCenter; with TMemo.Create (form) do begin Parent := form; Align := alClient; Scrollbars := ssVertical; ReadOnly := True; Color := form.Color; BorderStyle := bsNone; WordWrap := True; Text := str; end; form.Show; end; Besides the fact I had to create the form using the Application global object, a feature required by Delphi applications and discussed in the next chapter, this code simply does dynamically what you generally do with the form designer. Writing this code is undoubtedly more tedious, but it allows also a greater deal of flexibility, because any parameter can depend on external settings. The ShowStringForm function above is not executed by an event of another form, as there are no traditional forms in this program. Instead, I’ve modified the project’s source code to the following: program DynaForm; uses Forms, DynaMemo in ‘DynaMemo.pas’; {$R *.RES} var The TForm Class Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 324 str: string; begin str := ‘’; Randomize; while Length (str) < 2000 do str := str + Char (32 + Random (94)); ShowStringForm (str); Application.Run; end. The effect of running the DynaForm program is a strange-looking form filled with ran- dom characters (as you can see in Figure 9.1), not terribly useful in itself but for the idea it underscores. TIP An indirect advantage of this approach, compared to the use of DFM files for design-time forms, is that it would be much more difficult for an external programmer to grab information about the structure of the application. In Chapter 5 we saw that you can extract the DFM from the cur- rent Delphi executable file, but the same can be easily accomplished for any executable file com- piled with Delphi for which you don’t have the source code. If it is really important for you to keep to yourself a specific set of components you are using (maybe those in a specific form), and the default values of their properties, writing the extra code might be worth the effort. The Form Style The FormStyle property allows you to choose between a normal form (fsNormal) and the windows that make up a Multiple Document Interface (MDI) application. In this case, you’ll use the fsMDIForm style for the MDI parent window—that is, the frame window of the MDI application—and the fsMDIChild style for the MDI child window. To know more about the development of an MDI application, look at Chapter 10. FIGURE 9.1: The dynamic form generated by the DynaForm example is completely created at run time, with no design-time support. Chapter 9 • Working with Forms Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 325 A fourth option is the fsStayOnTop style, which determines whether the form has to always remain on top of all other windows, except for any that also happen to be “stay-on- top” windows. To create a top-most form (a form whose window is always on top), you need only set the FormStyle property, as indicated above. This property has two different effects, depending on the kind of form you apply it to: • The main form of an application will remain in front of every other application (unless other applications have the same top-most style, too). At times, this generates a rather ugly visual effect, so this makes sense only for special-purpose alert programs. • A secondary form will remain in front of any other form of the application it belongs to. The windows of other applications are not affected, though. This is often used for floating toolbars and other forms that should stay in front of the main window. The Border Style Another important property of a form is its BorderStyle. This property refers to a visual ele- ment of the form, but it has a much more profound influence on the behavior of the window, as you can see in Figure 9.2. At design time, the form is always shown using the default value of the BorderStyle prop- erty, bsSizeable. This corresponds to a Windows style known as thick frame. When a main window has a thick frame around it, a user can resize it by dragging its border. This is made clear by the special resize cursors (with the shape of a double-pointer arrow) displayed when the user moves the mouse onto this thick window border. FIGURE 9.2: Sample forms with the various border styles, created by the Borders example The TForm Class Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 326 A second important choice for this property is bsDialog. If you select it, the form uses as its border the typical dialog-box frame—a thick frame that doesn’t allow resizing. In addition to this graphical element, note that if you select the bsDialog value, the form becomes a dialog box. This involves several changes. For example, the items on its system menu are different, and the form will ignore some of the elements of the BorderIcons set property. WARNING Setting the BorderStyle property at design time produces no visible effect. In fact, several component properties do not take effect at design time, because they would prevent you from working on the component while developing the program. For example, how could you resize the form with the mouse if it were turned into a dialog box? When you run the applica- tion, though, the form will have the border you requested. There are four more values we can assign to the BorderStyle property. The style bsSingle can be used to create a main window that’s not resizable. Many games and applications based on windows with controls (such as data-entry forms) use this value, simply because resizing these forms makes no sense. Enlarging a form to see an empty area or reducing its size to make some components less visible often doesn’t help a program’s user (although Delphi’s automatic scroll bars partially solve the last problem). The value bsNone is used only in very special situations and inside other forms. You’ll never see an application with a main window that has no border or caption (except maybe as an example in a programming book to show you that it makes no sense). The last two values, bsToolWindow and bsSizeToolWin, are related to the specific Win32 extended style ws_ex_ToolWindow. This style turns the window into a floating toolbox, with a small title font and close button. This style should not be used for the main window of an application. To test the effect and behavior of the different values of the BorderStyle property, I’ve written a simple program called Borders, available also as QBorders in the CLX version. You’ve already seen its output, in Figure 9.2. However, I suggest you run this example and experiment with it for a while to understand all the differences in the forms. WARNING In CLX, the enumeration for the BorderStyle property uses slightly different values, prefixed by the letters fbs (form border style). So we have fbsSingle, fbsDialog, and so on. The main form of this program contains only a radio group and a button. There is also a secondary form, with no components and the Position property set to poDefaultPosOnly. This affects the initial position of the secondary form we’ll create by clicking the button. (I’ll discuss the Position property later in this chapter.) Chapter 9 • Working with Forms Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 327 The code of the program is very simple. When you click the button, a new form is dynami- cally created, depending on the selected item of the radio group: procedure TForm1.BtnNewFormClick(Sender: TObject); var NewForm: TForm2; begin NewForm := TForm2.Create (Application); NewForm.BorderStyle := TFormBorderStyle (BorderRadioGroup.ItemIndex); NewForm.Caption := BorderRadioGroup.Items[BorderRadioGroup.ItemIndex]; NewForm.Show; end; This code actually uses a trick: it casts the number of the selected item into the TFormBorder- Style enumeration. This works because I’ve given the radio buttons the same order as the values of this enumeration: type TFormBorderStyle = (bsNone, bsSingle, bsSizeable, bsDialog, bsTolWindow, bsSizeToolWin); The BtnNewFormClick method then copies the text of the radio button to the caption of the secondary form. This program refers to TForm2, the secondary form defined in a secondary unit of the program, saved as SECOND.PAS. For this reason, to compile the example, you must add the following lines to the implementation section of the unit of the main form: uses Second; TIP Whenever you need to refer to another unit of a program, place the corresponding uses statement in the implementation portion instead of the interface portion if possible. This speeds up the compilation process, results in cleaner code (because the units you include are separate from those included by Delphi), and prevents circular unit compilation errors. To accomplish this, you can also use the File ➢ Use Unit menu command. The Border Icons Another important element of a form is the presence of icons on its border. By default, a win- dow has a small icon connected to the system menu, a Minimize button, a Maximize button, and a Close button on the far right. You can set different options using the BorderIcons prop- erty, a set with four possible values: biSystemMenu, biMinimize, biMaximize, and biHelp. The TForm Class Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com [...]... Scrolling, and Scaling 353 PixelsPerInch sounds like it has something to do with the pixel resolution of the screen, but unfortunately, it doesn’t If you change your screen resolution from 64 0 48 0 to 800 60 0 to 10 24 768 or even 160 0×1280, you will find that Windows reports the same PixelsPerInch value in all cases, unless you change the system font What PixelsPerInch really refers to is the screen pixel resolution... color bitmap for a 300 40 0 image at 2 56 colors requires about 120 KB By increasing the color count or the number of pixels, you can easily have full-screen bitmaps of about 1 MB and reach 4 MB of memory for a 1280×10 24 resolution at 16 million colors If storing the bitmap was the default choice, running half a dozen simple applications would require at least 8 MB of memory, if not 16 MB, just for remembering... visible area of a window Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com Unusual Techniques: Alpha Blending, Color Key, and the Animate API 341 Unusual Techniques: Alpha Blending, Color Key, and the Animate API One of the few new features of Delphi 6 related to forms is support for some new Windows APIs regarding the way forms are displayed (not available under Qt/CLX) For a form, alpha blending... Status.Label3.Caption := IntToStr(ClientWidth); Status.Label4.Caption := IntToStr(HorzScrollBar.Position); end; FIGURE 9.8: The output of the Scroll1 example Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com Position, Size, Scrolling, and Scaling 347 If we wanted to change the output each time the user scrolls the contents of the form, we could not use a Delphi event handler, because there isn’t an OnScroll... is the textual description of the form: object Form1: TForm1 HorzScrollBar.Range = 2000 VertScrollBar.Range = 2000 ClientHeight = 3 36 ClientWidth = 47 2 OnPaint = FormPaint end Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com Position, Size, Scrolling, and Scaling 349 FIGURE 9.9: The lines to draw on the virtual surface of the form If we simply draw the lines using the virtual coordinates of the... Windows API functions in Delphi, unless you write advanced components To remove the caption, we need to change the overlapped style to a pop-up style; otherwise, the caption will simply stick Now how do we add a custom caption? I’ve placed a label aligned to the upper border of the form and a small button on the far end You can see this effect at run time in Figure 9 .4 FIGURE 9 .4: The NoTitle example... TransparentColorValue property Again, you can see an example of this effect in Figure 9.7 Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 342 Chapter 9 • Working with Forms Finally, you can use a native Windows technique, animated display, which is not directly supported by Delphi (beyond the display of hints) For example, instead of calling the Show method of a form, you can write: Form3.Hide; AnimateWindow... reasons to change Delphi defaults in this area For example, you might want to run two copies of the program and avoid having all the forms show up in exactly the same place I’ve collected many other related elements, including form scrolling, in this portion of the chapter The Form Position There are a few properties you can use to set the position of a form The Position property indicates how Delphi determines... its global size This is straightforward, because as you set one of the two client properties, the corresponding form property changes accordingly Copyright ©2001 SYBEX, Inc., Alameda, CA www.sybex.com 344 TIP Chapter 9 • Working with Forms In Windows, it is also possible to create output and receive input from the nonclient area of the form—that is, its border Painting on the border and getting input... the size of the form if it is outside the permitted area Delphi also uses the maximum constraints for maximized windows, producing an awkward effect For this reason, you should generally disable the Maximize button of a window that has a maximum size There are cases in which maximized windows with a limited size make sense— this is the behavior of Delphi s main window In case you need to change constraints . uses and refers to the actions and not the menu items or toolbar button related to them. The Delphi 6 extension of this architec- ture allows users of your programs to have a lot of control, and. now be able to use Delphi s visual compo- nents to create the user interface of your applications. So let’s turn our attention to another central element of development in Delphi: forms. We have. SYBEX, Inc., Alameda, CA www.sybex.com 3 24 str: string; begin str := ‘’; Randomize; while Length (str) < 2000 do str := str + Char (32 + Random ( 94) ); ShowStringForm (str); Application.Run; end. The

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

TỪ KHÓA LIÊN QUAN