
(Ebook - Pdf) Kick Ass Delphi Programming
.pdf
TMyGrid = class(TDrawGrid) protected
procedure SizeChanged(OldColCount, OldRowCount: Longint); override;
end;
{ In unit's implementation... }
procedure TMyGrid.SizeChanged(OldColCount, OldRowCount: Longint); begin
{ Take whatever actions necessary } end;
Overriding SizeChanged provides all the notification we need, but if we want control over the number of columns—for example, if we’re developing a grid that should have no more than three columns—SizeChanged is not a satisfactory place to shoehorn in our veto. By the time SizeChanged is called (note the past tense in the name), the change has already been made. The best we can do then, if ColCount was set to 4, is change it to 3, requiring the whole private process of change to be repeated.
What we want is front end control, and we can get this by redeclaring the ColCount property with our own access methods (see the TMyGrid declaration in Listing 7.10). Our redeclaration of the property will hide our ancestor’s ColCount, so that when a programmer writes
ColCount := AValue;
our own nonvirtual SetColCount access method will be called. As you can see from the SetColCount method in Listing 7.10, we first check to see whether the suggested value for the number of columns is less than or equal to 3. If it is, we make the change.
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!
-----------
Listing 7.10 SETCOLCT.SRC
{A descendant of TDrawGrid that redeclares the ColCount property with new access methods. This lets the descendant component control the number of columns. }
{In unit's interface... }
type
TMyGrid = class(TDrawGrid) private
function GetColCount: LongInt; procedure SetColCount(Value: LongInt);
published
property ColCount: LongInt read GetColCount write SetColCount default 0;
end;
{ In unit's implementation... }
function TMyGrid.GetColCount: LongInt; begin
Result := inherited ColCount; end;
procedure SetColCount(Value: LongInt); begin
if Value <= 3 then inherited ColCount := Value; end;
But how we make the change is perhaps the most interesting part of redeclaring a property. We can’t directly change the FColCount field—and we wouldn’t want to if we
could—because the other adjustments needed in the grid would not get made. We can’t call our ancestor’s SetColCount method—that’s private. And if we write
ColCount := Value;
within our own SetColCount method, we will create endless recursion and crash the stack.
The answer is to use the INHERITED keyword with the property name:
inherited ColCount := Value;
The ability to use INHERITED with an ancestor’s property name is not as well documented as its use with an inherited public or protected method. It’s a pleasant surprise, but it is entirely consistent with Object Pascal’s other pleasant surprises.
Taking Snapshots of the Screen with Delphi
In Delphi, if we want to capture the image of a form’s client area, we can call GetFormImage. But sometimes we want a snapshot of the entire form—title bar, frame, and all. Or we want a snapshot of the entire screen. If we were desperate, we might pop up a message box that says, “Press Print Screen button NOW!” and then figure out a way to get the screen’s mug off the clipboard.
But we’re not that desperate. Combining Delphi canvases with a few GDI functions makes capturing the screen in code a snap. CaptureScreenRect, in Listing 7.11, demonstrates this. It gets the screen’s device context with GetDC(0), and then it copies a rectangular area from that DC to a bitmap’s canvas. To do the copying, it uses BitBlt. The key to using BitBlt—or any GDI function—with Delphi is remembering that a canvas’ Handle is the DC that Windows needs.
Listing 7.11 SCRNCAP.PAS
{ Screen capture functions for Delphi } unit ScrnCap;
interface
uses WinTypes, WinProcs, Forms, Classes, Graphics;
function CaptureScreenRect( ARect: TRect ): TBitmap; function CaptureScreen: TBitmap;
function CaptureClientImage( Control: TControl ): TBitmap; function CaptureControlImage( Control: TControl ): TBitmap;
implementation
{ Use this to capture a rectangle on the screen... } function CaptureScreenRect( ARect: TRect ): TBitmap; var
ScreenDC: HDC; begin
Result := TBitmap.Create; with Result, ARect do
begin
Width := Right - Left; Height := Bottom - Top;
ScreenDC := GetDC( 0 ); try
BitBlt( Canvas.Handle, 0, 0, Width, Height, ScreenDC, Left, Top, SRCCOPY );
finally
ReleaseDC( 0, ScreenDC ); end;
end;
end;
{Use this to capture the entire screen... } function CaptureScreen: TBitmap;
begin
with Screen do
Result := CaptureScreenRect( Rect( 0, 0, Width, Height ));
end;
{Use this to capture just the client area of a form
or control... }
function CaptureClientImage( Control: TControl ): TBitmap; begin
with Control, Control.ClientOrigin do
Result := CaptureScreenRect( Bounds( X, Y, ClientWidth, ClientHeight ));
end;
{ Use this to capture an entire form or control... } function CaptureControlImage( Control: TControl ): TBitmap; begin
with Control do
if Parent = nil then
Result := CaptureScreenRect( Bounds( Left, Top, Width, Height ))
else
with Parent.ClientToScreen( Point( Left, Top )) do Result := CaptureScreenRect( Bounds( X, Y, Width,
Height ));
end;
end.
The remaining screen capture functions in Listing 7.11 cobble up rectangles and farm out the real work to CaptureScreenRect. CaptureScreen throws together a rectangle for the whole screen. CaptureClientImage and CaptureControlImage throw together rectangles for the client area and for the entire area of a control, respectively.
These four functions can be used to capture any arbitrary screen area, as well as the screen images of forms, buttons, memos, combo boxes, and so on. We just tell the little buggers to

say cheese—and free the bitmaps when we’re done.
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!
-----------
Delphi RadioGroup Buttons You Can Disable
When I am designing forms, nothing is quite so comforting as controls that know how to snap into place, spring out to size, and arrange their contents into columns: Hey, I feel as though I’m not fighting the battle alone. And the benefit of these size-wise controls is not just emotional; how many lines of code has a panel’s Align property saved me? Tens? Hundreds? That’s why, when I need to disable individual radio buttons, I am reluctant to heave the springy little RadioGroup control over the side. TRadioGroup automatically arranges its child buttons into columns, spaces them evenly, and lets them be named with one string list.
What it does not do is allow access to individual buttons—and for good reason, I’m sure. But since I trust myself to disable responsibly, I derived an enhanced component from TRadioGroup, as shown in Listing 7.12. TRadioBtnGroup has a new property, ItemEnabled, that lets us get and set the enabled status of individual buttons.
Listing 7.12 RBTNGRPS.PAS
{ A radio group with buttons that can be disabled } unit RBtnGrps;
interface
uses StdCtrls, ExtCtrls;
type
TRadioBtnGroup = class( TRadioGroup ) private
function GetItemEnabled( Index: Integer ): Boolean; procedure SetItemEnabled( Index: Integer; Value: Boolean ); function GetButtons( Index: Integer ): TRadioButton;
protected
function CheckAnyBut( NotThisIndex: Integer ): Boolean; property Buttons[ Index: Integer ]: TRadioButton
read GetButtons; public
property ItemEnabled[ Index: Integer ]: Boolean read GetItemEnabled write SetItemEnabled;
end;
implementation
function TRadioBtnGroup.CheckAnyBut; var
Index: Integer; begin
Result := True;
for Index := NotThisIndex + 1 to Items.Count - 1 do if Buttons[ Index ].Enabled then
begin
Buttons[ Index ].Checked := True; Exit;
end;
for Index := 0 to NotThisIndex - 1 do if Buttons[ Index ].Enabled then begin
Buttons[ Index ].Checked := True; Exit;
end;
Result := False; end;
function TRadioBtnGroup.GetItemEnabled; begin
Result := Buttons[ Index ].Enabled; end;
procedure TRadioBtnGroup.SetItemEnabled; begin
if ( not Value ) and ( Index = ItemIndex ) and Buttons[ Index ].Checked and
( not CheckAnyBut( Index )) then ItemIndex := -1;
Buttons[ Index ].Enabled := Value; end;
function TRadioBtnGroup.GetButtons; begin
Result := Components[ Index ] as TRadioButton; end;
end.
Internally, TRadioBtnGroup uses the GetButtons method to gain access to its radio buttons. GetButtons relies on the fact that, since a radio group owns its child buttons, it holds them in its Components array. All GetButtons does is index into the Components array and safely typecast the result.
The new control tries its best to be an intelligent helper. If a checked button is disabled, the

control tries to check another button; if all the buttons are disabled, it unchecks all the buttons. Depending on your needs, you might want to change this latter behavior.
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!
-----------
CHAPTER 8
Animated Screen Savers in Delphi
RAY KONOPKA
•Hooking the Application’s OnIdle Event
•Windows 95 Callback Functions
•A Combo Box for Color Selection
•Special Project File Modifications
Anything you can do with the Windows API, you can do in Delphi. How about a screen saver? Fear not the Windows Callback, and kiss MakeProcInstance goodbye!
Unlike many other visual development tools, Delphi provides complete access to the Windows
API. Yes, the VCL does encapsulate much of this API, but not all of it. This chapter investigates how Delphi applications can take advantage of the Windows API. To demonstrate the process, we’re going to create a screen saver.
Figure 8.1 shows a picture of the screen saver in action. The basic scheme is that a laser beam (okay, a line) draws out the Def Leppard logo and then erases it. I selected the logo of my favorite band, but you could use any logo you want. All you need to do is determine the coordinates of the line segments that define the path of the laser.
FIGURE 8.1 The Def Leppard screen saver.
Secrets of the Main Form
The heart of the screen saver lies in the LaserFrm form file. Listing 8.1 shows the source code for the unit embodying the form file. This form file defines the TFrmLaser form class, which
represents the main window on which the laser beam will draw the logo.
Listing 8.1 LASERFRM.PAS
unit LaserFrm;
interface
uses
Messages, WinTypes, WinProcs, Classes, Graphics, Controls, Forms, DLPoints, SvrUtils;
type |
|
|
TFrmLaser = |
class(TForm) |
|
procedure |
FormCreate(Sender: TObject); |
|
procedure |
FormClose( Sender: TObject; |
|
|
var |
Action: TCloseAction); |
procedure |
FormKeyDown( Sender: TObject; var Key: Word; |
|
|
Shift: TShiftState); |
|
procedure |
FormMouseDown( |
Sender: TObject; Button: TMouseButton; |
|
|
Shift: TShiftState; X, Y: Integer); |
procedure |
FormMouseMove( |
Sender: TObject; Shift: TShiftState; |
|
|
X, Y: Integer); |
private
FMousePt : TPoint; FDone : Boolean; FOriginPoint : Longint;
FOrigins : array[ TLaserOrigin ] of Longint; FCurrPoint : Integer;
FFirstPass : Boolean; FGettingPassword : Boolean; FOrigX : Integer;
FOrigY : Integer;
procedure IdleProc( Sender : TObject; var Done : Boolean ); procedure Animate;
procedure CursorOff; procedure CursorOn; procedure PopulateOrigins; procedure GetPassword;
procedure SetTopMost( TopMost : Boolean ); end;
var
FrmLaser: TFrmLaser;
implementation
{$R *.DFM}
uses
GetPWFrm, MMSystem;
const
Offset = 25; { Distance from Screen Edge of Laser Source }