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

(Ebook - Pdf) Kick Ass Delphi Programming

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

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!

-----------

While testing my original version of the handler, I discovered there are two ways to initiate the drag. Using True as the argument of the BeginDrag method starts the drag as soon as the mouse is pressed, while selecting False delays until the mouse is actually moved a few pixels. The second choice felt far more natural. After some bumbles, I also added the line of code that blocks out any attempt to drag an empty string. The typecast used to call the BeginDrag method is typically required when working with the Sender and Source object references provided to event handlers.

Step 2 was next. The handler for OnDragOver events brings with it several parameters. Source specifies the object where the drag started (in this case, the edit box). Sender is the object sending the message—the potential target for the drop. In this case it is the calendar. The X and Y parameters give the relative coordinates of the mouse cursor within the Sender, and State specifies whether the object being dragged is entering, leaving or moving across the Sender. Although default cursors are provided for the drag/drop process, this drag state information makes it easy to specify your own cursors for each part of the process. Finally, there is the Accept parameter, a boolean passed by reference.

The object of the game is to decide, based on the information provided, whether or not it is acceptable to complete the drop. The process is sort of like a pilot of a small plane (the Source) radioing to a controller on the ground, saying “Here are my coordinates over the field in which you’re standing. Is it okay to drop my payload?”

It turned out that by selecting the OvcCalendar, I had made my work exceedingly simple. With the exception of the day titles, everything within the calendar’s client area was fair game for a drop. Since all the rows are the same height, I just had to figure out how tall a row was, and then accept a drop only when the X,Y position was past the first row. The code appears in Listing 12.2.

Listing 12.2 Checking for the acceptability of a drop

procedure TDDDemoForm.CalendarDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);

var

RHeight : Integer;

RNum : Integer; begin

RHeight := Calendar.ClientHeight div 7; RNum := Y div RHeight + 1;

Accept := RNum > 1; end;

Dropping the Payload

I proceeded to Step 3. The strategy was to figure out the row and column locations of the first day of the month and the cursor position. From that, a little arithmetic would give me the number of days difference between the two dates, which I could then add to the first day’s date to obtain the absolute date.

That first day will always appear in the second row (under the day titles), no matter which day of the week it falls on. So much for the row. Since I hadn’t changed the calendar from the standard Sunday-Saturday format, getting the day of the week for the first day gave me a column reference position. From there, I just had to advance the number of days into the calendar. Fortunately, the Orpheus package comes with some powerful date conversion and arithmetic routines that helped greatly. My calculation routine for the date pointed at is shown in Listing 12.3.

Listing 12.3 Calculating the date from the mouse position

function DatePointedTo : TOvcDate; var

Idx : Longint;

DOW : Integer; Day1 : TOvcDate;

begin

{Compute first day as Row = 2, Col = DOW, then calculate an offset to the date pointed to. Then

add

the

two. }

Day1 := DMYToDate(1, Calendar.Month, Calendar.Year);

DOW :=

Ord(DayOfWeek(Day1)) + 1;

Idx :=

(RNum - 2) * 7;

if CNum <

DOW

then

Idx

:= Idx - (DOW - CNum)

else

if CNum > DOW

 

then Idx := Idx + (CNum - DOW);

Result

:=

IncDate(Day1, Idx, 0, 0);

end; {

DatePointedTo }

All that was left was some simple housekeeping—converting the date and edit box text to a string, and adding that string to the string grid. I also found it handy to clear out the edit box once the drop was complete; with the editing capabilities of the edit box somewhat hampered by the dragging support, it became cumbersome to clear it manually.

Note to myself: In this case, it was appropriate to clear the edit box as part of the dragdrop event handler, because I wanted it performed only if the drop was performed. Had I wanted to clear the edit box whether or not the drop succeeded, I would have done so in an OnEndDrag handler for the edit box.

Reminder to myself: Make sure the OvcCalendar’s Initialize property is set to True.

Otherwise, it comes up in an undefined state!

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.

Go!

Keyword

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

Kick Ass Delphi Programming

(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 12.4 shows the code for the entire unit.

Listing 12.4 Code for the drag/drop demo

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

{

Drag/Drop Demonstration

}

{

DRAGMAIN.PAS : Drag/Drop Main Unit

}

{

By Ace Breakpoint, N.T.P.

}

{

Assisted by Don Taylor

}

{

 

}

{ Application that demonstrates dragging and

}

{ dropping within the single application.

}

{

 

}

{ Written for *Kick-Ass Delphi Programming*

}

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

}

{

Last Updated 3/19/96

}

{———————————————————————————————————————————————————} unit DragMain;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls, OvcBase, OvcCal, OvcData, OvcDT, ExtCtrls;

type

TDDDemoForm = class(TForm) Calendar: TOvcCalendar; OvcController1: TOvcController; EditBox: TEdit;

StringGrid: TStringGrid; Label1: TLabel;

Bevel1: TBevel;

QuitBtn: TButton;

Panel1: TPanel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

procedure QuitBtnClick(Sender: TObject);

procedure EditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

procedure CalendarDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);

procedure CalendarDragDrop(Sender, Source: TObject; X, Y: Integer); private

{Private declarations } public

{Public declarations }

end;

var

DDDemoForm: TDDDemoForm;

implementation

{$R *.DFM}

procedure TDDDemoForm.QuitBtnClick(Sender: TObject); begin

Close;

end;

procedure TDDDemoForm.EditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

if (Button = mbLeft)

and (EditBox.Text <> '') and not (ssDouble in Shift)

then TEdit(Sender).BeginDrag(False); end;

procedure TDDDemoForm.CalendarDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);

var

RHeight : Integer; RNum : Integer;

begin

RHeight := Calendar.ClientHeight div 7; RNum := Y div RHeight + 1;

Accept := RNum > 1; end;

procedure TDDDemoForm.CalendarDragDrop(Sender, Source: TObject; X, Y: Integer);

var

 

RHeight

: Integer;

CWidth

: Integer;

RNum

: Integer;

CNum

: Integer;

s

: String;

function DatePointedTo : TOvcDate; var

Idx : Longint;

DOW : Integer; Day1 : TOvcDate;

begin

{ Compute first day as Row = 2, Col = DOW, then calculate an offset to the date pointed to. Then add the two. }

Day1 := DMYToDate(1, Calendar.Month, Calendar.Year); DOW := Ord(DayOfWeek(Day1)) + 1;

Idx := (RNum - 2) * 7; if CNum < DOW

then Idx := Idx - (DOW - CNum) else if CNum > DOW

then Idx := Idx + (CNum - DOW); Result := IncDate(Day1, Idx, 0, 0);

end; { DatePointedTo }

begin

RHeight := Calendar.ClientHeight div 7; RNum := Y div RHeight + 1;

CWidth := Calendar.ClientWidth div 7; CNum := X div CWidth + 1;

{ Put the date and task in the string list }

s := DateTimeToStr(OvcDateToDateTime(DatePointedTo)) + ' - ' + EditBox.Text;

StringGrid.Cells[0, StringGrid.RowCount - 1] := s;

{ Add a blank row to the string list } StringGrid.RowCount := StringGrid.RowCount + 1;

EditBox.Text := '';

end;

end.

End of entry, March 19.

The sinister figure leaned forward, intently reading the purloined Casebook. The dark eyes swept across to the next page.

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.

Go!

Keyword

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

Kick Ass Delphi Programming

(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!

-----------

Packing Paradox and dBASE Tables

Casebook No. 16, March 20: When I was growing up, my mother constantly hounded me to put away bits and pieces that had not gotten incorporated into various projects I was working on. “Clean up your mess!” was a phrase I heard at least once a day. Perhaps the Bag Man had a mother like that, too—maybe that’s why he approached me with a request for an easy way to delete the excess space in Paradox and dBASE tables from a Delphi application.

I guess, like my strange client, the Bag Man, I had just assumed there would be a TTable method for accomplishing this. After all, both dBASE and Paradox offer that functionality. I suppose Delphi’s design team was looking at a bigger picture, one that included large client/server databases that wouldn’t recognize such commands from an application.

Although Delphi’s designers didn’t provide a direct way to pack tables, they did provide an easy way to “get under the hood” and access lots of low-level stuff. Not just Windows’ internals. We’re talking any old application program interface (API) that wants to make itself available—including the Borland Database Engine (BDE).

The BDE provides a lot of low-level services to programs. It is the basis for the methods associated with Delphi’s data-aware components. And the BDE units are available to any Delphi program.

A little searching on the Internet rewarded me with a routine that used the BDE routines to pack both Paradox and dBASE tables. Unfortunately, the routine appeared to have been written anonymously, so I can’t credit the original author here. I modified the code just a bit, to place it in a unit and incorporate some exception handling. I saved the modified version in a file named PAKTABLE.PAS, which can be seen in Listing 12.5.

Listing 12.5 A unit for packing Paradox and dBASE tables

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

{

Data Table Packing Demo

}

{

PAKTABLE.PAS : Packing Routine

}

{

By Ace Breakpoint, N.T.P.

}

{

Assisted by Don Taylor

}

{

 

}

{ A unit containing a specialized procedure for

}

{ "packing" Paradox and dBASE tables to eliminate

}

{ wasted space.

}

{

 

}

{ Written for *Kick-Ass Delphi Programming*

}

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

}

{ Last Updated 3/20/96 } {———————————————————————————————————————————————————}

unit PakTable;

interface

uses

SysUtils, Dialogs, DBTables, DBiTypes, DBiProcs, DBiErrs;

function PackTable(var ATable : TTable) : Boolean;

implementation

type

EDBPackMisc = class(Exception);

var

ActiveStatus : Boolean; ExclusiveStatus : Boolean; Error : DBiResult; ErrorMsg : DBiMsg; pTableDesc : pCRTblDesc; AHandle : hDBiDB;

{PackTable packs the records (and in the case of dBASE tables, actually removes records previously marked for deletion) in Paradox and dBASE tables. The TableType property of the table to be packed must

be either ttParadox or ttDBase; ttDefault will not work. Also, the table must not be in use by anyone else, because it has to be put in Exclusive mode. }

function PackTable(var ATable : TTable) : Boolean; begin

Result := False; try

with ATable do begin

{Save the current status of the table } ActiveStatus := Active;

ExclusiveStatus := Exclusive;

{Disconnect the table from controls and make it exclusive } DisableControls;

Active := False; Exclusive := True;

end; { with }

try

{ Pack the table, depending on the table's type } case ATable.TableType of

ttParadox : begin

{ Create a description table and prepare it for use } GetMem(pTableDesc, SizeOf(CRTblDesc)); FillChar(pTableDesc^, SizeOf(CRTblDesc), 0);

with pTableDesc^ do begin

StrPCopy(szTblName, ATable.TableName); StrPCopy(szTblType, szParadox);

bPack := True; end; { with }

{ Get the table's database handle } with ATable do

begin

Active := True;

AHandle := ATable.DBHandle; Active := False;

end; { with }

try

{ Attempt a restructure/pack and handle any error }

Error := DBiDoRestructure(AHandle, 1, pTableDesc, nil, nil, nil, False);

if Error = DBIERR_NONE then Result := True else begin

DBiGetErrorString(Error, ErrorMsg); raise EDBPackMisc.Create(ErrorMsg); end;

finally

FreeMem(pTableDesc, SizeOf(CRTblDesc)); end; { try }

end;

ttDBase :

with ATable do begin

Active := True;

Error := DBiPackTable(DBHandle, Handle, nil, nil, True); if Error = DBIERR_NONE

then Result := True

else raise EDBPackMisc.Create('Could not pack this dBASE table'); end;

else raise EDBPackMisc.Create('Cannot pack this table type'); end; { case }

except

on E:EDBPackMisc do

MessageDlg(E.Message, mtError, [mbOK], 0); end; { try }

finally

{ Restore the original condition of the table } with ATable do

begin

Active := False;

Exclusive := ExclusiveStatus; Active := ActiveStatus; EnableControls;

end; { with } end; { try }

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.