Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

(Ebook - Pdf) Kick Ass Delphi Programming

.pdf
Скачиваний:
284
Добавлен:
17.08.2013
Размер:
5.02 Mб
Скачать

width, so I could easily manipulate these values.

The next step was to determine the point representing the lower-right corner of the form. The lParam of the default WM_GETMINMAXINFO handler is a pointer to an array of five point structures. Thankfully, the wizards at Borland thoughtfully provided a TWMGetMinMaxInfo message type that hides most of the complexity.

Listing 13.1 contains the complete source for my resizing experiment. The listing includes the handler that resulted after several head-scratching attempts (I was surprised by the “interesting” effects that could be attained by forgetting such frivolities as calling the inherited handler). As can be seen in the listing, simply dereferencing the MinMaxInfo portion of the message gives quick and easy access to the points defined by ptMinTrackSize and ptMaxTrackSize. I added some code in the form’s OnCreate handler to compute values for MinWidth and MinHeight, based on the sizes of the form’s components at startup.

Listing 13.1 Source code for the Form Resize Demo

{———————————————————————————————————————————————————}

{

Form Resize Demo

}

{

RS.PAS : Main Form

}

{

By Ace Breakpoint, N.T.P.

}

{

Assisted by Don Taylor

}

{

 

}

{ This application demonstrates how a combination

}

{of panels with alignments set, along with gaining }

{control of Windows' resizing messaging, can create}

{ flexible forms that follow and limit resizing

}

{ commands.

 

}

{

 

}

{ Written for *Kick-Ass Delphi Programming*

}

{ Copyright (c) 1996 The Coriolis Group, Inc.

}

{

Last Updated 3/25/96

}

{———————————————————————————————————————————————————}

unit Rs;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Buttons;

type

TRSMainForm = class(TForm) ControlPanel: TPanel; RSMemoPanel: TPanel; RSMemo: TMemo;

BtnPanel: TPanel;

SBPanel: TPanel; QuitSB: TSpeedButton; QuitBtn: TButton; SBComboPanel: TPanel; ComboBox1: TComboBox;

SpeedButton1: TSpeedButton; Button1: TButton;

procedure QuitBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormResize(Sender: TObject);

private

{ Private declarations }

procedure WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); message WM_GET MINMAXINFO;

public

{ Public declarations } end;

var

RSMainForm: TRSMainForm; MinWidth : Integer; MinHeight : Integer;

implementation

{$R *.DFM}

procedure TRSMainForm.QuitBtnClick(Sender: TObject); begin

Close;

end;

procedure TRSMainForm.FormCreate(Sender: TObject); begin

MinWidth := RSMemoPanel.Width + BtnPanel.Width + 10; MinHeight := RSMainForm.Height

- (RSMainForm.ClientHeight - (RSMemo.Top + RSMemo.Height)) + 10; end;

procedure TRSMainForm.WMGetMinMaxInfo(var Msg: TWMGetMinMaxInfo); begin

inherited;

with Msg.MinMaxInfo^ do begin

with ptMinTrackSize do begin

X := MinWidth;

Y := MinHeight; end; { with }

with ptMaxTrackSize do begin

X := Screen.Width;

Y := Screen.Height; end; { with }

end; { with } end;

procedure TRSMainForm.FormResize(Sender: TObject); begin

RSMemo.Height := RSMemoPanel.Height - (2 * RSMemo.Top); RSMemoPanel.Width := RSMainForm.ClientWidth - BtnPanel.Width; RSMemo.Width := RSMemoPanel.Width - (2 * RSMemo.Left);

end;

end.

Products | Contact Us | About Us | Privacy | Ad Info | Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.

All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.

To access the contents, click the chapter and section titles.

Kick Ass Delphi Programming

Go!

Keyword

(Publisher: The Coriolis Group)

Author(s): Don Taylor, Jim Mischel, John Penman, Terence Goggin

ISBN: 1576100448

Publication Date: 09/01/96

Search this book:

Go!

-----------

Now it was time to play with the arrangement of components on the form, so their positioning would be consistent even if the form containing them was resized.

When I first started working with panels, they gave me headaches. But as I got to know them better, I fell in love with three cool characteristics they share. First, they can, with the Alignment property, be forced into absolute correspondence with their parents. If you set a panel’s Alignment to alTop, it will take over the entire top of the form it’s placed on. Second, other components (memos, buttons, etc.) placed on a panel will stay in a fixed position relative to that panel, as long as it is not resized. Finally, a panel placed on another panel has the same characteristics as a panel placed on a form: If the Alignment is set to alBottom, it will spread out and glue itself across the bottom of the parent panel.

All of this creates a neat little set of behaviors that make consistent form resizing possible. I had several goals for the form shown in Figure 13.1:

Panel3 would have a fixed height and occupy the entire top of the form, so its length would always track the width of the form;

SB1 would remain in a fixed position relative to the left side of Panel3 (and thus the upper-left corner of the window);

Panel4 would be aligned with the right side of Panel3, so Panel4 would not change in size, but would track the right side of Panel3 as the length of Panel3 changed;

Panel5 (which contains Memo1) would be aligned with the left side of the form, and its height would track with form resizing;

Panel1 (which contains Panel2) would be aligned with the right side of the form, and its height would also track with form resizing;

Panel2 (which contains Button1 and Button2) would be aligned with the bottom of Panel1, so it would remain the same size and follow the

bottom of the Panel1 (and thus the form) during a resize; and

Button1 and Button2 would be placed in a fixed position on Panel2, so they would each remain fixed with respect to both the bottom and right side of the form.

Whew! I got to work setting the properties of the various panels. It’s a little confusing working with panels, until you learn the rules of etiquette. Panel alignments set to alTop or alBottom will always take precedence over those set alLeft or alRight. Anyway, I set Panel3 to alTop, Panel1 and Panel4 to alRight, Panel5 to alLeft, and Panel2 to alBottom. I set the BevelOuter properties on Panel4 and Panel2 to bvNone, so they would “disappear,” and I set the color of Panel3 and Panel4 to clGray, to set them off aesthetically from the rest of the form. I also added a combobox and another speedbutton to Panel4, so I could verify that tracking was working properly. I then renamed the panels and blanked out all their captions.

I decided I wanted the overall panel containing the buttons (formerly Panel1) to remain a constant width, while enabling the panel holding the memo to take up the rest of the available width. I would then automatically resize Memo1 to take up all of its parent panel, less some margins on each side. I was able to accomplish this with a little arithmetic in the form’s OnResize event handler.

After several tries, I got everything just the way I wanted it. Figure 13.2 shows the demo form as it appears at the start of the program; Figure 13.3 is a shot of how the form looks when it has been resized to the specified limits.

End of entry, March 25.

FIGURE 13.2 The Resize Demo form at program startup.

FIGURE 13.3 The Resize Demo form after resizing to the limits.

Making a Splash

The mysterious figure closed the Casebook and reached for the telephone. The instrument readily accepted the seven digits keyed in, then produced a series of soft buzzes that indicated the line was ringing at the other end. There was a click. Then the Avenger began to speak to an intimately familiar voice on the other end of the line.

“Hello, Baby Cakes... Yes, it’s me. Just thought you’d like to know how things went last night. I broke into Ace Breakpoint’s apartment as planned, and stole his Casebook right out from under his nose. The whole thing was almost flawless....Uh-huh.... I want you to know how much I appreciate how

invaluable your part was in all of this. I couldn’t have done it without you....

What? Yes, it’s been a long time coming—and believe me, revenge is sweet. Right. Listen, Baby Cakes—drop everything and meet me tonight at nine o’clock at the Gates Motel, just off Highway 101. Right—up on the hill, just outside of Norton City. Uh-huh... Tonight I’ll show you the book that will change both our lives, and make me the world’s preeminent Windows programmer.... That’s right, Baby, me—the Delphi Avenger. 9:00 P.M. Don’t be late. Bye.”

The Avenger hung up the phone and picked up the Casebook, and chuckling loudly, began once again to peruse its pages.

Casebook No. 16, March 26: Today the Bag Man called me again. This time he wants me to create a “splash screen” component he can use in a variety of programs. He basically wants to drop a component on the main form of an application, set a few properties, and have it pop up a screen before the main form shows up.

I got to thinking about what I would like to see in a generic splash screen. Not a great deal. I would probably make it modal, so I could prevent the program from executing until the screen had properly displayed its contents to the user. I would want to kill the screen with a click of a button, a timeout, or both. And of course, I would want the ability to include a graphic on the screen. I sat down at the computer and created the initial design shown in Figure 13.4.

FIGURE 13.4 A first cut at the splash screen, shown at design time.

Now, how was I going to turn this into a component? After a couple of false starts, I decided the best approach would be to create a new component with a TForm object as its core, but with another object “wrapped” around the TForm to manage it. This wrapper object could manage only the properties associated with the splash screen object, giving the splash screen a simple user interface. The wrapper could also manage the creation and destruction of the form, all from one simple command issued by the owner of the wrapper object. I decided to call the wrapper a TSplashDialog.

Products | Contact Us | About Us | Privacy | Ad Info | Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.

All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.

To access the contents, click the chapter and section titles.

Kick Ass Delphi Programming

Go!

Keyword

(Publisher: The Coriolis Group)

Author(s): Don Taylor, Jim Mischel, John Penman, Terence Goggin

ISBN: 1576100448

Publication Date: 09/01/96

Search this book:

Go!

-----------

As part of my initial specification, I decided to write a simple-minded test application—a form containing only a button—that would eventually contain a TSplashDialog. The code for the test application is shown in Listing 13.2.

Listing 13.2 The test application for TSplashDialog

{———————————————————————————————————————————————————}

{

Splash Screen Component

}

{

SPLSHMN.PAS : Demo Program Main Form

}

{

By Ace Breakpoint, N.T.P.

}

{

Assisted by Don Taylor

}

{

 

}

{ A simple program that demonstrates the use of

}

{ the TSplashDialog component. Try combinations

}

{ of time delays, sizes, graphics and such to see

}

{ the flexibility provided.

}

{

 

}

{ Written for *Kick-Ass Delphi Programming*

}

{ Copyright (c) 1996 The Coriolis Group, Inc.

}

{

Last Updated 3/26/96

}

{———————————————————————————————————————————————————}

unit SplshMn;

{.$define Test }

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, SplshDlg;

type

TForm1 = class(TForm) QuitBtn: TButton;

SplashDialog1: TSplashDialog;

procedure QuitBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject);

private

{$ifdef Test }

SplashDialog1 : TSplashDialog; {$endif}

public

{ Public declarations } end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.QuitBtnClick(Sender: TObject); begin

Close;

end;

procedure TForm1.FormCreate(Sender: TObject); begin

{$ifdef Test}

SplashDialog1 := TSplashDialog.Create(Application); {$endif}

SplashDialog1.Execute;

end;

end.

This brings up something noteworthy: Never test a component under construction by placing it in Delphi’s library. Bad—very bad—stuff can happen if things aren’t right. Plus, it’s a slow, tedious process to recompile the library for each and every run. Instead, include the component’s unit in a test program, and then create an instance of the component as the object it is. That is what is done here. Through the use of a conditional compiler directive and a constant I called Test, this simple program has been given two modes. As shown (with the period preceding the ‘$’ in the directive), the $define becomes only a comment, and the program can be used to test the installed version of the component. Deleting the period enables the conditional code, which in this program declares a TSplashDialog with the same name (SplashDialog1) that the IDE will give the component when it is dropped on the form. Use of the conditional test in the OnCreate handler also creates an instance of SplashDialog1.

As can be seen, I decided to put the dialog into action with a method called Execute, in the proud tradition of the specialized system dialogs like TOpenDialog.

I had set the stage for a TSplashDialog. Now, what properties should it have? It must enable the programmer to specify its size, although I would assume it would always be displayed at the center of the user’s screen. The screen needs to be told whether it has a button, and if so, the caption on that button. It needs to know if the dialog is to have a timeout, and if so, what the time delay will be. It needs a TPicture object to plug into the TImage component. And to give it some flexibility with that graphic, the programmer should be able to specify the alignment, whether or not the TImage is to be autosized to the graphic’s dimensions, and whether or not the graphic is to be stretched to fit the TImage dimensions.

Products | Contact Us | About Us | Privacy | Ad Info | Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.

All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.

To access the contents, click the chapter and section titles.

Kick Ass Delphi Programming

Go!

Keyword

(Publisher: The Coriolis Group)

Author(s): Don Taylor, Jim Mischel, John Penman, Terence Goggin

ISBN: 1576100448

Publication Date: 09/01/96

Search this book:

Go!

-----------

A couple of hours later, I had a more-or-less finished component. The source code appears in Listing 2.3.

Listing 13.3 Source code for the TSplashDialog component

{———————————————————————————————————————————————————}

{

Splash Screen Component

}

{

SPLSHDLG.PAS : Component unit

}

{

By Ace Breakpoint, N.T.P.

}

{

Assisted by Don Taylor

}

{

 

}

{ This unit describes a specialized component that

}

{ pops up a "splash screen" whenever your program

}

{ wants to display one (usually at program startup) }

{

 

}

{ Written for *Kick-Ass Delphi Programming*

}

{ Copyright (c) 1996 The Coriolis Group, Inc.

}

{

Last Updated 3/26/96

}

{———————————————————————————————————————————————————}

unit SplshDlg;

{.$define Test }

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;

type

ESplashConflict = class(Exception);

TImageAlign = (iaNone, iaTop, iaBottom, iaLeft, iaRight, iaClient, iaAllAboveButton);

{TSplashForm is the actual form displayed to the user. It contains a TImage, a TButton and a TTimer, so the programmer can vary how