(Ebook - Pdf) Kick Ass Delphi Programming
.pdfI suppose this is a personal preference, but I would like shared event handlers to have a more generic name than what is automatically generated by Delphi. I decided to call the two handlers
GridDragOver and GridDragDrop.
Before proceeding any further, I want to document the 8-step method I used to create generic-sounding routine names for the handlers:
1.Double-click on the name of the event to be handled, as it appears in the Object Inspector.
2.Delphi automatically names the routine, combining the names of the component and the event to produce a unique identifier. More importantly, it automatically generates the call parameter list for the specific event. (Being lazy, I would much rather have Delphi do this for me than create it from scratch.)
3.Type anything (a semicolon does nicely) between the begin and end of the empty routine created by Delphi. This will prevent Delphi from automatically deleting the routine if you try to save it.
4.Edit the name of the routine, then double-click to highlight it, and press Ctrl-C to copy the new name to the clipboard.
5.Jump to the beginning of the file, and find the original handler declaration within the form’s declaration. Highlight the original name there, and tap Ctrl-V to replace it with the new name.
6.At some point in the process, Delphi will complain that the name it originally assigned (still present in the Object Inspector) can’t be found. Give Delphi the okay to remove it.
7.Move the cursor to the event slot in the Object Inspector, where this all began. Use the
Ctrl-V combination to paste in the new name.
8. Save the file.
The routines I wrote appear in Listing 14.1.
Listing 14.1 Common handlers for OnDragOver and OnDragDrop events
{ Common event handler for all the grids' OnDragOver event. } procedure TShareEventDemoForm.GridDragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean); begin
{ We can accept anything, but only from the EditBox. } Accept := Source is TEdit;
end;
{ Common event handler for all the grids' OnDragDrop event. } procedure TShareEventDemoForm.GridDragDrop(Sender, Source : TObject;
X, Y : Integer); begin
{ Drop the load on the currently selected grid. } DropEditString(CurrentGrid);
end;
{Common event handler support routine that drops the string
in the EditBox onto the specified grid. Also clears the EditBox. }
procedure TShareEventDemoForm.DropEditString(AGrid : TStringGrid); begin
if AGrid <> nil then with AGrid do begin
Cells[0, RowCount - 1] := EditBox.Text; RowCount := RowCount + 1;
EditBox.Text := '';
end; { with } end;
{ Return a pointer to the grid on the currenly selected tab sheet. } function TShareEventDemoForm.CurrentGrid : TStringGrid;
begin
Result := nil;
if PageControl.ActivePage = MorningSheet then Result := MorningGrid else
if PageControl.ActivePage = AfternoonSheet then Result := AfternoonGrid else
if PageControl.ActivePage = EveningSheet then Result := EveningGrid;
end;
The OnDragOver routine is very straightforward. As long as the source object for the drag is the edit box, it can be accepted by any of the grids. I chose to split the OnDragDrop handling into two routines: a main handler and a support method. The handler merely calls the support routine, using a function which returns a pointer to the grid on the currently selected tabsheet. Delphi’s ability to mask the use of pointers really comes into play here, making it very straightforward to pull some shenanigans with pointers, while keeping the program exceedingly readable. Given the pointer, the DropEditString routine adds the string from the edit box to the appropriate string grid, updating the grid’s row counter and clearing out the edit box.
The handlers worked as expected for the grid on the first tabsheet (MorningGrid). I went back to the Object Inspector and selected the same handlers for the other two grids. Again, everything worked perfectly.
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.
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls, ExtCtrls, ComCtrls;
type
TShareEventDemoForm = class(TForm) EditBox: TEdit;
Label1: TLabel;
QuitBtn: TButton;
Panel1: TPanel; PageControl: TPageControl; MorningSheet: TTabSheet; AfternoonSheet: TTabSheet; EveningSheet: TTabSheet; MorningGrid: TStringGrid; AfternoonGrid: TStringGrid; EveningGrid: TStringGrid;
procedure FormCreate(Sender: TObject); procedure QuitBtnClick(Sender: TObject);
procedure EditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure GridMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure GridDragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean); procedure GridDragDrop(Sender, Source : TObject;
X, Y : Integer);
procedure PageControlDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure PageControlDragDrop(Sender, Source: TObject; X, Y: Integer);
private
CopyDrag : Boolean;
function ManualTabsSet : Boolean; function CurrentGrid : TStringGrid;
function TabGrid(X : Integer) : TStringGrid; procedure SetTabSizes;
procedure DropEditString(AGrid : TStringGrid); procedure DropGridString(TargetGrid : TStringGrid);
public
{ Public declarations } end;
var
ShareEventDemoForm: TShareEventDemoForm;
implementation
{$R *.DFM}
{ Return the length in pixels of a string for display, given a handle to the window in which it will appear, along with a handle to the window’s font. }
function StringWidth
(WinHnd : HWND; FntHnd : HWND; Text : String) : Integer; var
DCHnd : HWND;
StrSize : TSize;
TextArr : array[0..127] of char; begin
Result := -1;
DCHnd := GetDC(WinHnd);
if GetMapMode(DCHnd) = MM_TEXT then begin
SelectObject(DCHnd, FntHnd); StrPCopy(TextArr, Text);
if GetTextExtentPoint32(DCHnd, @TextArr, Length(Text), StrSize) then Result := StrSize.Cx
end; ReleaseDC(WinHnd, DCHnd); end;
{Return the height in pixels of a font for display, given a handle to the window in which it will appear, along with a handle to the window’s font. The height must include the ascent, descent and inner leading. }
function FontHeight(WinHnd : HWND; FntHnd : HWND) : Integer; var
DCHnd : HWND;
TextMex : TTextMetric; begin
Result := -1;
DCHnd := GetDC(WinHnd);
if GetMapMode(DCHnd) = MM_TEXT then begin
SelectObject(DCHnd, FntHnd); GetTextMetrics(DCHnd, TextMex); Result := TextMex.tmHeight; end;
ReleaseDC(WinHnd, DCHnd); end;
procedure TShareEventDemoForm.FormCreate(Sender: TObject); begin
PageControl.ActivePage := MorningSheet; SetTabSizes;
CopyDrag := False; end;
procedure TShareEventDemoForm.QuitBtnClick(Sender: TObject); begin
Close;
end;
procedure TShareEventDemoForm.EditBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
{ Before initiating a drag, make sure the left button
is pressed, the EditBox has text in it, and that we’re not in a double-click situation. }
if (Button = mbLeft)
and (EditBox.Text <> '') and not (ssDouble in Shift)
then TEdit(Sender).BeginDrag(False); end;
{ Common event handler for all the grids' OnMouseDown event. } procedure TShareEventDemoForm.GridMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var
TheGrid : TStringGrid; begin
{We’re initiating a drag from whichever string grid is currently selected. Set the CopyDrag flag if the control key is down. Before starting the drag, make sure the left mouse button is pressed, there is text in the selected row of the grid, and we’re not in
a double-click situation. }
TheGrid := CurrentGrid; CopyDrag := ssCtrl in Shift; if (Button = mbLeft)
and (TheGrid.Cells[0, TheGrid.Row] <> '') and not (ssDouble in Shift)
then TStringGrid(Sender).BeginDrag(False); end;
{ Common event handler for all the grids' OnDragOver event. } procedure TShareEventDemoForm.GridDragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean); begin
{ We can accept anything, but only from the EditBox. } Accept := Source is TEdit;
end;
{ Common event handler for all the grids' OnDragDrop event. } procedure TShareEventDemoForm.GridDragDrop(Sender, Source : TObject;
X, Y : Integer); begin
{ Drop the load on the currently selected grid. } DropEditString(CurrentGrid);
end;
procedure TShareEventDemoForm.PageControlDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
{ A drop on a tab is acceptable if it comes fron the EditBox, or if it comes from a grid -- as long as the tab isn't the
one for the grid originating the drag. In either case, tabs must have been manually set. }
Accept := ManualTabsSet and
(
(Source is TEdit) or
((Source is TStringGrid) and (CurrentGrid <> TabGrid(X))) );
end;
procedure TShareEventDemoForm.PageControlDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
{Get the string from the proper source and drop it on the grid associated with the tab at position X. }
if (Source is TEdit) then DropEditString(TabGrid(X));
if (Source is TStringGrid) then DropGridString(TabGrid(X));
end;
{Return True only if both tab height and width have been set manually. } function TShareEventDemoForm.ManualTabsSet : Boolean;
begin
Result := (PageControl.TabHeight > 0) and (PageControl.TabWidth > 0); end;
{Return a pointer to the grid on the currenly selected tab sheet.} function TShareEventDemoForm.CurrentGrid : TStringGrid;
begin
Result := nil;
if PageControl.ActivePage = MorningSheet then Result := MorningGrid else
if PageControl.ActivePage = AfternoonSheet then Result := AfternoonGrid else
if PageControl.ActivePage = EveningSheet then Result := EveningGrid;
end;
{Return a pointer to the grid on the tab sheet associated with the tab located at position X. }
function TShareEventDemoForm.TabGrid(X : Integer) : TStringGrid; var
Idx : Integer; begin
Result := nil; with PageControl do begin
Idx := X div TabWidth; case Idx of
0 : Result := MorningGrid;
1 : Result := AfternoonGrid;
2 : Result := EveningGrid; end; { case }
end; { with } end;
{Adjust tab height and width as required to give a pleasing appearance, and to ensure tabs each have the same height and width. }
procedure TShareEventDemoForm.SetTabSizes; var
i : Integer;
Len : Integer; MaxWidth : Integer; s : String;
begin
with PageControl do begin
if TabWidth > 0 then begin
MaxWidth := -1;
for i := 0 to PageCount - 1 do begin
s := Pages[i].Caption;
Len := StringWidth(Handle, Font.Handle, s); if Len > MaxWidth then MaxWidth := Len; 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.