home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 January
/
Pcwk0198.iso
/
Dcomplib
/
BTNARRAY.LZH
/
BUTARRAY.PAS
next >
Wrap
Pascal/Delphi Source File
|
1995-07-13
|
19KB
|
532 lines
unit ButArray;
(*
Description
Base Class to create an array of buttons using (TButton) like DB Navigator
The Variables are: Button Width, Height, No of Buttons and
Spacing between buttons
The button height and width and Spacing is fixed in the object editor
and can not be changed using the mouse.
The Button Count by default is 1, to increase the number of buttons
expand the width of the control using a mouse or change the value in the
object editor
To Add Button Caption and Hints to each button either use the string property
or use a resource string table.
For the second option you need a resource workshop like in Borland C++ 4
When using a string table just pass the first resource ID it is assumed
that subsequent button text will be the next number ID a long.
To capture event
Each button has an index number starting from 0 to N
the LHB (Left hand Button) is 0
This index number is passed when the event is captured by the user
inheritance
To creating a new object from this class is easier than using
DBNavigator all the Events have virtual procedural calls, this may be
overriden and new functionality added
An example of database navigator buttons using this class see ClinNav
Author Mike Lindre CompuServe USERID 100567,2225
Last Edit 12 July 1995
*)
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs,StdCtrls;
{Set the constanst to be used}
const DF_BUT_WIDTH = 67; {Height of the buttons}
DF_BUT_HEIGHT = 22; {Width of the buttons}
DF_BUT_SPACE = -1; {Space between each button}
DF_NO_OF_BUT = 1; {No of buttons on creation of component}
DF_NOT_USED = 0; {Are the resources used or not}
type
{Create new events with a button index (0...N) so that each button
in the group may be used effectively}
EButClick = procedure (Sender:TObject;ButtonIndex:integer) of object;
EButEnter = procedure (Sender: TObject;ButtonIndex:integer)of object;
EButExit = procedure (Sender: TObject;ButtonIndex:integer)of object;
EButKeyDown = procedure (Sender: TObject;ButtonIndex:integer;var Key: Word;
Shift: TShiftState)of object;
EButKeyPress = procedure (Sender: TObject;ButtonIndex:integer;
var Key: Char)of object;
EButKeyUp = procedure (Sender: TObject;ButtonIndex:integer; var Key: Word;
Shift: TShiftState) of object;
EButMouseDown = procedure (Sender: TObject ;ButtonIndex:integer ;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer) of object;
EButMouseMove = procedure (Sender: TObject ;ButtonIndex:integer ;
Shift: TShiftState; X,Y: Integer) of object;
EButMouseUp = procedure (Sender: TObject ;ButtonIndex:integer;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer) of object;
TButtonArray = class(TWinControl)
private
{ Private declarations }
FNoOFButtons:integer; {No of buttons}
FHints:TStrings; {Hints to be used}
FNames:TStrings; {Names for the buttons}
FButtonWidth:integer; {Width of the buttons}
FButtonHeight:integer;{Height of the buttons}
FButtonSpace:integer; {Space between each button default = -1}
FNameResource:integer;{Resource number if names are stored in res file}
FHintResource:integer;{Resource number if hints are stored in res file}
ButtonList:TList; {List of button objects}
CurrentControlWidth:integer;
{properties for the new events}
FOnButClick:EButClick;
FOnButEnter:EButEnter;
FOnButExit:EButExit;
FOnButKeyDown:EButKeyDown;
FOnButKeyPress:EButKeyPress;
FOnButKeyUp:EButKeyUp;
FOnButMouseDown:EButMouseDown;
FOnButMouseMove:EButMouseMove;
FOnButMouseUp:EButMouseUp;
{General functions}
procedure SetUpButtons; {Create button(s) and place them in the list}
procedure UpdateSize; {Change the size of the buttons in the control}
procedure SetUpHints; {Assign buttons with hint help}
procedure SetUpNames; {Assign button with Captions}
procedure ClearList; {Remove anything from the button list}
{property function used when setting properties}
procedure SetHints(Value:TStrings);
procedure SetNames(Value:TStrings);
procedure SetNoOFButtons(Value:integer);
procedure SetButtonWidth(Value:integer);
procedure SetButtonHeight(Value:integer);
procedure SetButtonSpace(Value :integer);
procedure SetNameResource(Value:integer);
procedure SetHintResource(Value:integer);
{Function definitons that replicate the events for a standard button
These will be assigned to each of the buttons in a list, and will
capture all the events made by the buttons.
Once the event is captured it will be reassigned to the new event
handler for this component with the approprate button index set}
procedure Click(Sender:TObject);
procedure Enter(Sender: TObject);
procedure Exit(Sender: TObject);
procedure KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
procedure KeyPress(Sender: TObject; var Key: Char);
procedure KeyUp(Sender: TObject; var Key: Word;Shift: TShiftState);
procedure MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
procedure MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
{ When a wm size message is sent handle it properly}
procedure WMSize(var Message:TWMSize); message WM_SIZE;
protected
{Set the approprate buttons to enable etc}
procedure EnableButtons(const A:array of Boolean);
{These are virtual functions using the dynamic calling convention
These are used as place holders for new components
These functions may be overriden in new components as long as the
new versions calls the inhertied ones so it keep this basic functionality.
Using dynamic to keep memory usage low and, it appears that if a function
is called a lot like a message then this dispatch method is then used;
Only when speed is very important that one should use the virtual keyword
When the standard events are called from each button, it is redirected
to one of the below functions, from where it is processed.
(It checks to see if any of the new events have been assigned)}
procedure ButClick(ButtonIndex:integer); dynamic;
procedure ButEnter (ButtonIndex:integer); dynamic;
procedure ButExit(ButtonIndex:integer); dynamic;
procedure ButKeyDown(ButtonIndex:integer;var Key: Word;Shift: TShiftState);dynamic;
procedure ButKeyPress(ButtonIndex:integer;var Key: Char);dynamic;
procedure ButKeyUp (ButtonIndex:integer; var Key: Word;Shift: TShiftState);dynamic;
procedure ButMouseDown(ButtonIndex:integer;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);dynamic;
procedure ButMouseMove(ButtonIndex:integer;Shift: TShiftState; X,Y: Integer);dynamic;
procedure ButMouseUp (ButtonIndex:integer;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);dynamic;
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{define the resource numbers for names and string}
property NameResource:integer read FNameResource write SetNameResource;
property HintResource:integer read FHintResource write SetHintResource;
published
{ Published declarations }
property Enabled;
property Visible;
property ShowHint;
property ParentShowHint;
property Font;
property TabOrder;
property TabStop;
property Hints:TStrings read FHints write SetHints;
property Names:TStrings read FNames write SetNames;
property NoOfButtons:integer read FNoOFButtons write SetNoOFButtons default DF_NO_OF_BUT;
property ButtonWidth:integer read FButtonWidth write SetButtonWidth default DF_BUT_WIDTH;
property ButtonHeight:integer read FButtonHeight write SetButtonHeight default DF_BUT_HEIGHT;
property ButtonSpace :integer read FButtonSpace write SetButtonSpace default DF_BUT_SPACE;
{Add properties for the new events that may be used by the component user}
property OnClick:EButClick read FOnButClick write FOnButClick;
property OnEnter:EButEnter read FOnButEnter write FOnButEnter;
property OnExit: EButExit read FOnButExit write FOnButExit;
property OnKeyDown:EButKeyDown read FOnButKeyDown write FOnButKeyDown;
property OnKeyPress:EButKeyPress read FOnButKeyPress write FOnButKeyPress;
property OnKeyUp:EButKeyUp read FOnButKeyUp write FOnButKeyUp;
property OnMouseDown:EButMouseDown read FOnButMouseDown write FOnButMouseDown;
property OnMouseMove:EButMouseMove read FOnButMouseMove write FOnButMouseMove;
property OnMouseUp: EButMouseUp read FOnButMouseUp write FOnButMouseUp;
end;
implementation
constructor TButtonArray.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{Set the defaults for the button height and width and number of}
FButtonWidth := DF_BUT_WIDTH;
FButtonHeight := DF_BUT_HEIGHT;
FButtonSpace := DF_BUT_SPACE;
FNoOFButtons := DF_NO_OF_BUT;
FNameResource := DF_NOT_USED;
FHintREsource := DF_NOT_USED;
CurrentControlWidth := DF_BUT_WIDTH;
Visible := True;
{Create the lists for the names and helpful hints}
FHints := TStringList.Create;
FNames := TStringList.Create;
{Create the buttons}
SetUpButtons;
end;
destructor TButtonArray.Destroy;
begin
ClearList;
inherited Destroy;
end;
procedure TButtonArray.SetNameResource(Value:integer);
begin
if Value <= 0 then Value := 0;
FNameResource := Value;
SetUpNames;
end;
procedure TButtonArray.SetHintResource(Value:integer);
begin
if Value <= 0 then Value := 0;
FHintResource := Value;
SetUpHints;
end;
procedure TButtonArray.ClearList;
{Each time SetupButtons is Called this function
destroys the list ready to be recreated}
var Bnt:TButton;
begin
while ButtonList <> nil do begin
Bnt:= TButton(ButtonList.Last);
ButtonList.Remove(Bnt);
if ButtonList.Count = 0 then
begin
ButtonList.Free;
ButtonList := nil;
end;
Bnt.Destroy;
end;
end;
procedure TButtonArray.SetUpButtons;
var Counter:integer;
Space:integer;
Bnt:TButton;
begin
{Distroy the current list}
ClearList;
{Make a new list}
ButtonList := TList.Create;
ButtonList.Capacity := FNoOFButtons;
Space := 0;
{Add the buttons as required}
for Counter := 0 to FNoOFButtons-1 do begin
Bnt:= TButton.Create(Self);
{Set the size of each button}
Bnt.SetBounds (Counter * (FButtonWidth+Space), 0, FButtonWidth, FButtonHeight);
Bnt.Parent:=Self;
Bnt.Enabled:= Enabled;
{The button tag proptery is used to identify the button as an index}
Bnt.Tag:=Counter;
{Assign the intermediate funtions to catch and process events for
each of the buttons}
Bnt.OnClick := Click;
Bnt.OnEnter := Enter;
Bnt.OnExit := Exit;
Bnt.OnKeyDown := KeyDown;
Bnt.OnKeyPress := KeyPress;
Bnt.OnKeyUp := KeyUp;
Bnt.OnMouseDown := MouseDown;
Bnt.OnMouseMove := MouseMove;
Bnt.OnMouseUp := MouseUp;
{Add the button to the list}
ButtonList.Add(Bnt);
{set the space between each button}
Space := FButtonSpace;
end;
{Set the size for the complete control}
CurrentControlWidth := (FNoOFButtons * FButtonWidth) + (FNoOFButtons -1)*FButtonSpace;
inherited SetBounds(Left,Top,CurrentControlWidth,FButtonHeight);
{set the button captions and hints}
SetUpNames;
SetUpHints;
end;
procedure TButtonArray.UpdateSize;
var Counter:integer;
Space:integer;
begin
Space := 0;
{Add the buttons as required}
for Counter := 0 to FNoOFButtons-1 do begin
{Set the size of each button}
TButton(ButtonList.Items[Counter]).SetBounds (Counter * (FButtonWidth+Space), 0, FButtonWidth, FButtonHeight);
{set the space between each button}
Space := FButtonSpace;
end;
{Set the size for the complete control}
CurrentControlWidth := (FNoOFButtons * FButtonWidth) + (FNoOFButtons -1)*FButtonSpace;
inherited SetBounds(Left,Top,CurrentControlWidth,FButtonHeight);
end;
{The following functions are the intermedate ones that capture the
events from each button and redirect it to the new events}
procedure TButtonArray.Click(Sender:TObject);
begin
ButClick(TButton(Sender).Tag);
end;
procedure TButtonArray.ButClick(ButtonIndex:integer);
begin
{If a user has assigned an event use it}
if not (csDesigning in ComponentState) and Assigned(FOnButClick) then
FOnButClick(Self,ButtonIndex);
end;
procedure TButtonArray.Enter(Sender: TObject);
begin
ButEnter(TButton(Sender).Tag);
end;
procedure TButtonArray.ButEnter(ButtonIndex:integer);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButEnter) then
FOnButEnter(Self,ButtonIndex);
end;
procedure TButtonArray.Exit(Sender: TObject);
begin
ButExit(TButton(Sender).Tag);
end;
procedure TButtonArray.ButExit(ButtonIndex:integer);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButExit) then
FOnButExit(Self,ButtonIndex);
end;
procedure TButtonArray.KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
begin
ButKeyDown(TButton(Sender).Tag,Key,Shift);
end;
procedure TButtonArray.ButKeyDown(ButtonIndex:integer;var Key: Word;Shift: TShiftState);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButKeyDown) then
FOnButKeyDown(Self,ButtonIndex,Key,Shift);
end;
procedure TButtonArray.KeyPress(Sender: TObject; var Key: Char);
begin
ButKeyPress(TButton(Sender).Tag,Key);
end;
procedure TButtonArray.ButKeyPress(ButtonIndex:integer;var Key: Char);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButKeyPress) then
FOnButKeyPress(Self,ButtonIndex,Key);
end;
procedure TButtonArray.KeyUp(Sender: TObject; var Key: Word;Shift: TShiftState);
begin
ButKeyUp(TButton(Sender).Tag,Key,Shift);
end;
procedure TButtonArray.ButKeyUp(ButtonIndex:integer; var Key: Word;Shift: TShiftState);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButKeyUp) then
FOnButKeyUp(Self,ButtonIndex,Key,Shift);
end;
procedure TButtonArray.MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
ButMouseDown(TButton(Sender).Tag,Button,Shift,X,Y);
end;
procedure TButtonArray.ButMouseDown(ButtonIndex:integer;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButMouseDown) then
FOnButMouseDown(Self,ButtonIndex,Button,Shift,X,Y);
end;
procedure TButtonArray.MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
begin
ButMouseMove(TButton(Sender).Tag,Shift,X,Y);
end;
procedure TButtonArray.ButMouseMove(ButtonIndex:integer;Shift: TShiftState; X,Y: Integer);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButMouseMove) then
FOnButMouseMove(Self,ButtonIndex,Shift,X,Y);
end;
procedure TButtonArray.MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
ButMouseUp(TButton(Sender).Tag,Button,Shift,X, Y);
end;
procedure TButtonArray.ButMouseUp(ButtonIndex:integer;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if not (csDesigning in ComponentState) and Assigned(FOnButClick) then
FOnButMouseUp(Self,ButtonIndex,Button,Shift,X, Y);
end;
{set the enabled property on each button}
{Always starting from the first button so some dummies might be needed}
procedure TButtonArray.EnableButtons(const A:array of Boolean);
var Counter:integer;
begin
for Counter := 0 to sizeof(A) - 1 do
TButton(ButtonList.Items[Counter]).Enabled := A[Counter];
end;
{Set the captions for each button, check to see if the names are stored
in a resource file or a text file CAN be both}
procedure TButtonArray.SetUpNames;
var Counter:integer;
begin
if FNameResource <> 0 then begin
for Counter := 0 to FNoOFButtons - 1 do
TButton(ButtonList.Items[Counter]).Caption := loadstr(FNameResource + Counter);
end;
Counter := 0;
while (Counter < FNames.Count) and (Counter < FNoOFButtons) do begin
if FNames[Counter] <> '' then
TButton(ButtonList.Items[Counter]).Caption := FNames[Counter];
inc(Counter);
end;
end;
{set the hints for each buttonm, check to see if the names are stored
in a resource file or a text file CAN be both}
procedure TButtonArray.SetUpHints;
var Counter:integer;
begin
if FHintResource <> 0 then begin
for Counter := 0 to FNoOFButtons - 1 do
TButton(ButtonList.Items[Counter]).Hint := loadstr(FHintResource + Counter);
end;
Counter := 0;
while (Counter < FHints.Count) and (Counter < FNoOFButtons) do begin
if FHints[Counter] <> '' then
TButton(ButtonList.Items[Counter]).Hint := FHints[Counter];
inc(Counter);
end;
end;
{Assign properties functions}
procedure TButtonArray.SetNames(Value:TStrings);
begin
FNames.Assign(Value);
SetUpNames;
end;
procedure TButtonArray.SetHints(Value:TStrings);
begin
FHints.Assign(Value);
SetUpHints;
end;
procedure TButtonArray.SetNoOFButtons(Value:integer);
begin
{check the value has changed}
if FNoOFButtons <> Value then begin
FNoOFButtons := Value;
SetUpButtons;
end;
end;
procedure TButtonArray.SetButtonWidth(Value:integer);
begin
{check the value has changed}
if FButtonWidth <> Value then begin
FButtonWidth := Value;
UpdateSize;
end;
end;
procedure TButtonArray.SetButtonHeight(Value:integer);
begin
{check the value has changed}
if FButtonHeight <> Value then begin
FButtonHeight := Value;
UpdateSize;
end;
end;
procedure TButtonArray.SetButtonSpace(Value:integer);
begin
{Check that the value has changed}
if FButtonSpace <> Value then begin
FButtonSpace := Value;
UpdateSize;
end;
end;
procedure TButtonArray.WMSize(var Message:TWMSize);
var NewButtonCount:integer;
begin
{Check the size has changed}
inherited; {Do default processing}
{When the controls size changes keep the button count appropriate}
NewButtonCount := round((Width-(FNoOfButtons-1)*FButtonSpace)/FButtonWidth);
if NewButtonCount <> FNoOFButtons then begin
FNoOFButtons := NewButtonCount;
if FNoOFButtons <= 0 then FNoOFButtons := 1;
SetUpButtons;
end;
{Make sure that the control stays the same size as the buttons}
if (Width <> CurrentControlWidth) or (Height <> FButtonHeight) then
inherited SetBounds(Left,Top,CurrentControlWidth,FButtonHeight);
{This message returns zero to tell the application
that this message has been processed}
Message.Result := 0;
end;
end.