lazarus-ccr/components/orpheus/ovcsc.pas
2007-01-16 02:17:08 +00:00

1718 lines
52 KiB
ObjectPascal

{*********************************************************}
{* OVCSC.PAS 4.06 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* The contents of this file are subject to the Mozilla Public License *}
{* Version 1.1 (the "License"); you may not use this file except in *}
{* compliance with the License. You may obtain a copy of the License at *}
{* http://www.mozilla.org/MPL/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Orpheus *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
(*Changes)
01/15/02 - Set AutoRepeat modified to prevent deadlocks at runtime.
*)
{$I OVC.INC}
{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit ovcsc;
{-Spin control}
interface
uses
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, MyMisc, {$ENDIF}
Buttons, Classes, Controls, Forms, Graphics, StdCtrls,
SysUtils, OvcBase, OvcData, OvcEF, OvcMisc, OvcExcpt;
type
TOvcSpinnerStyle = (stNormalVertical, stNormalHorizontal, stFourWay, stStar,
stDiagonalVertical, stDiagonalHorizontal, stDiagonalFourWay,
stPlainStar);
TOvcDirection = (dUp, dDown, dRight, dLeft);
TOvcSpinState = (ssNone, ssNormal, ssUpBtn, ssDownBtn, ssLeftBtn,
ssRightBtn, ssCenterBtn);
TOvcSpinnerLineType = (ltSingle,
ltTopBevel, ltBottomBevel, ltTopSlice, ltBottomSlice,
ltTopSliceSquare, ltBottomSliceSquare,
ltDiagTopBevel,ltDiagBottomBevel,
ltStarLine0, ltStarLine1, ltStarLine2, ltStarLine3, ltStarLine4, ltStarLine5
);
TSpinClickEvent =
procedure(Sender : TObject; State : TOvcSpinState; Delta : Double; Wrap : Boolean)
of object;
type
TOvcSpinner = class(TOvcCustomControl)
protected {private}
{property variables}
FAcceleration : Integer; {value used to determine acceleration}
FAutoRepeat : Boolean; {repeat if button held}
FDelayTime : LongInt;
FDelta : Double; {amount to change by}
FRepeatCount : LongInt;
FFocusedControl : TWinControl; {the control to give the focus to}
FShowArrows : Boolean;
FStyle : TOvcSpinnerStyle;
FWrapMode : Boolean; {wrap at field bounderies}
{events}
FOnClick : TSpinClickEvent;
{private instance variables}
scNextMsgTime : LongInt;
{regions for the five spin button sections}
scUpRgn : hRgn;
scDownRgn : hRgn;
scLeftRgn : hRgn;
scRightRgn : hRgn;
scCenterRgn : hRgn;
scCurrentState : TOvcSpinState;
scLButton : Byte;
scMouseOverBtn : Boolean;
scPrevState : TOvcSpinState;
scSizing : Boolean;
scTopLeft, scTopRight, scBottomLeft, scBottomRight, scCenter : TPoint;
scTopLeftCenter, scBottomLeftCenter, scTopRightCenter, scBottomRightCenter : TPoint;
scTopMiddle, scBottomMiddle, scLeftMiddle, scRightMiddle : TPoint;
scTopLeft4, scBottomLeft4, scTopRight4, scBottomRight4 : TPoint;
{property methods}
procedure SetAcceleration(const Value : Integer);
procedure SetAutoRepeat(Value: Boolean);
procedure SetShowArrows(const Value : Boolean);
procedure SetStyle(Value : TOvcSpinnerStyle);
{internal methods}
function scCheckMousePos : TOvcSpinState;
procedure scDeleteRegions;
procedure scDoAutoRepeat;
procedure scDrawArrow(const R: TRect; const Pressed: Boolean; const Direction: TOvcDirection);
procedure scDrawLine(P1, P2 : TPoint; const Up : Boolean; LineType : TOvcSpinnerLineType);
procedure scDrawNormalButton(const Redraw : Boolean);
procedure scDrawFourWayButton(const Redraw : Boolean);
procedure scDrawStarButton(const Redraw : Boolean);
procedure scDrawDiagonalVertical(const Redraw : Boolean);
procedure scDrawDiagonalHorizontal(const Redraw : Boolean);
procedure scDrawDiagonalFourWay(const Redraw : Boolean);
procedure scDrawPlainStar(const Redraw : Boolean);
procedure scDrawButton(const Redraw : Boolean);
procedure scInvalidateButton(const State : TOvcSpinState);
procedure scPolyline(const Points: array of TPoint);
{private message response methods}
procedure OMRecreateWnd(var Msg : TMessage);
message om_RecreateWnd;
{windows message handling methods}
procedure WMGetDlgCode(var Msg : TWMGetDlgCode);
message WM_GETDLGCODE;
procedure WMLButtonDown(var Msg : TWMLButtonDown);
message WM_LBUTTONDOWN;
procedure WMLButtonUp(var Msg : TWMLButtonUp);
message WM_LBUTTONUP;
protected
procedure CreateParams(var Params : TCreateParams);
override;
procedure Loaded;
override;
procedure Notification(AComponent : TComponent; Operation : TOperation);
override;
procedure Paint;
override;
{dynamic event wrappers}
procedure DoOnClick(State : TOvcSpinState);
dynamic;
procedure scDoMouseDown(const XPos, YPos: Integer);
virtual;
procedure scDoMouseUp;
virtual;
procedure scUpdateNormalSizes;
procedure scUpdateFourWaySizes;
procedure scUpdateStarSizes;
procedure scUpdateDiagonalVerticalSizes;
procedure scUpdateDiagonalHorizontalSizes;
procedure scUpdateDiagonalFourWaySizes;
procedure scUpdatePlainStarSizes;
procedure scUpdateSizes;
virtual;
public
constructor Create(AOwner : TComponent);
override;
destructor Destroy;
override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
override;
property RepeatCount : LongInt
read FRepeatCount;
published
{properties}
property Acceleration : Integer
read FAcceleration write SetAcceleration
default 5;
property AutoRepeat : Boolean
read FAutoRepeat write SetAutoRepeat;
property Delta : Double
read FDelta write FDelta;
property DelayTime : LongInt
read FDelayTime write FDelayTime
default 500;
property FocusedControl : TWinControl
read FFocusedControl write FFocusedControl;
property ShowArrows : Boolean
read FShowArrows write SetShowArrows
default True;
property Style : TOvcSpinnerStyle
read FStyle write SetStyle
default stNormalVertical;
property WrapMode : Boolean
read FWrapMode write FWrapMode
default True;
{inherited properties}
{$IFDEF VERSION4}
property Anchors;
property Constraints;
{$ENDIF}
property Enabled;
property ParentShowHint;
property ShowHint;
property Visible;
{events}
property OnClick : TSpinClickEvent
read FOnClick write FOnClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
end;
implementation
uses
OvcEdCal, OvcEdTim;
const
scDefMinSize = 13;
{$IFDEF NoAsm}
function GetArrowWidth(Width, Height : Integer) : Integer;
begin
Result := Height;
if Width < Height then
Result := Width;
Result := (Result SHR 1) OR 1;
end;
{$ELSE}
function GetArrowWidth(Width, Height : Integer) : Integer; register;
asm
cmp eax, edx
jle @@1
mov eax, edx
@@1:
shr eax, 1
or eax, 1
end;
{$ENDIF}
{*** TOvcSpinner ***}
constructor TOvcSpinner.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csFramed, csOpaque];
ControlStyle := ControlStyle + [csReplicatable];
{initialize property variables}
FAcceleration := 5;
FAutoRepeat := True;
FDelayTime := 500;
FDelta := 1;
FRepeatCount := 0;
FShowArrows := True;
FStyle := stNormalVertical;
FWrapMode := True;
Width := 16;
Height := 25;
TabStop := False;
scCurrentState := ssNormal;
scPrevState := ssNone;
scMouseOverBtn := False;
end;
procedure TOvcSpinner.CreateParams(var Params : TCreateParams);
begin
inherited CreateParams(Params);
ControlStyle := ControlStyle + [csOpaque] - [csFramed];
if not (csDesigning in ComponentState) then
ControlStyle := ControlStyle - [csDoubleClicks];
end;
destructor TOvcSpinner.Destroy;
begin
scDeleteRegions;
inherited Destroy;
end;
procedure TOvcSpinner.DoOnClick(State : TOvcSpinState);
var
D : Double;
begin
if Assigned(FOnClick) or
(Assigned(FFocusedControl) and
((FFocusedControl is TOvcBaseEntryField) or
(FFocusedControl is TCustomEdit))) then begin
if scMouseOverBtn then begin
if LongInt(GetTickCount) > scNextMsgTime then begin
{auto link with Orpheus entry fields}
if Assigned(FFocusedControl) and (FFocusedControl is TOvcBaseEntryField) then begin
case State of
ssUpBtn : TOvcBaseEntryField(FFocusedControl).IncreaseValue(FWrapMode, Delta);
ssDownBtn : TOvcBaseEntryField(FFocusedControl).DecreaseValue(FWrapMode, Delta);
ssLeftBtn : TOvcBaseEntryField(FFocusedControl).MoveCaret(-1);
ssRightBtn : TOvcBaseEntryField(FFocusedControl).MoveCaret(+1);
end;
end;
{auto link with TCustomEdit controls}
if Assigned(FFocusedControl) and (FFocusedControl is TCustomEdit) then begin
try
if (FFocusedControl is TOvcCustomDateEdit) then
D := TOvcCustomDateEdit(FFocusedControl).Date
else if (FFocusedControl is TOvcCustomTimeEdit) then
D := TOvcCustomTimeEdit(FFocusedControl).AsMinutes
else
D := StrToFloat(TCustomEdit(FFocusedControl).Text);
case State of
ssUpBtn : D := D + Delta;
ssDownBtn : D := D - Delta;
end;
if (FFocusedControl is TOvcCustomDateEdit) then
TOvcCustomDateEdit(FFocusedControl).Date := D
else if (FFocusedControl is TOvcCustomTimeEdit) then
TOvcCustomTimeEdit(FFocusedControl).AsMinutes := trunc(D)
else
TCustomEdit(FFocusedControl).Text := FloatToStr(D);
except
end;
end;
{call OnClick event handler, if assigned}
if Assigned(FOnClick) then
FOnClick(Self, State, Delta, FWrapMode);
{setup for next time}
scNextMsgTime := LongInt(GetTickCount) + DelayTime - Acceleration*10*FRepeatCount;
Inc(FRepeatCount);
end;
end;
end;
end;
procedure TOvcSpinner.Loaded;
begin
inherited Loaded;
scUpdateSizes;
end;
procedure TOvcSpinner.Notification(AComponent : TComponent; Operation : TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FFocusedControl) and (Operation = opRemove) then
FocusedControl := nil;
end;
procedure TOvcSpinner.OMRecreateWnd(var Msg : TMessage);
begin
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
end;
function TOvcSpinner.scCheckMousePos : TOvcSpinState;
var
P : TPoint;
begin
GetCursorPos(P);
P := ScreenToClient(P);
{see which button the mouse is over}
Result := ssNone;
if PtInRect(ClientRect, P) then begin
{$IFDEF MSWINDOWS}
if not (csClicked in ControlState) then
{$ELSE} //csClicked not getting set with GTK
if not (csLButtonDown in ControlState) then
{$ENDIF}
Result := ssNormal
{mouse is over one of the buttons, which one?}
else if (scUpRgn <> 0) and PtInRegion(scUpRgn, P.X, P.Y) then
if (Style = stNormalHorizontal) then
Result := ssRightBtn
else
Result := ssUpBtn
else if (scDownRgn <> 0) and PtInRegion(scDownRgn, P.X, P.Y) then
if (Style = stNormalHorizontal) then
Result := ssLeftBtn
else
Result := ssDownBtn
else if (scLeftRgn <> 0) and PtInRegion(scLeftRgn, P.X, P.Y) then
Result := ssLeftBtn
else if (scRightRgn <> 0) and PtInRegion(scRightRgn, P.X, P.Y) then
Result := ssRightBtn
else if (scCenterRgn <> 0) and PtInRegion(scCenterRgn, P.X, P.Y) then
Result := ssCenterBtn
else
Result := ssNormal;
end;
end;
procedure TOvcSpinner.scDeleteRegions;
begin
if scUpRgn <> 0 then begin
DeleteObject(scUpRgn);
scUpRgn := 0;
end;
if scDownRgn <> 0 then begin
DeleteObject(scDownRgn);
scDownRgn := 0;
end;
if scLeftRgn <> 0 then begin
DeleteObject(scLeftRgn);
scLeftRgn := 0;
end;
if scRightRgn <> 0 then begin
DeleteObject(scRightRgn);
scRightRgn := 0;
end;
if scCenterRgn <> 0 then begin
DeleteObject(scCenterRgn);
scCenterRgn := 0;
end;
end;
procedure TOvcSpinner.scDoAutoRepeat;
var
NewState : TOvcSpinState;
begin
DoOnClick(scCurrentState);
{don't auto-repeat for center button}
if (scCurrentState = ssCenterBtn) or (not AutoRepeat) then begin
repeat
{allow other messages}
Application.ProcessMessages;
{until the mouse button is released}
{$IFDEF MSWINDOWS}
until ({$IFNDEF LCL} GetAsyncKeyState(scLButton) {$ELSE} GetKeyState(scLButton) {$ENDIF} and $8000) = 0;
{$ELSE} //GTK GetKeyState returns 0
until not (csLButtonDown in ControlState);
{$ENDIF}
scDoMouseUp;
Exit;
end;
{repeat until left button released}
repeat
if AutoRepeat then
DoOnClick(scCurrentState);
{allow other messages}
Application.ProcessMessages;
{get new button/mouse state}
NewState := scCheckMousePos;
{has anything changed}
if NewState <> scCurrentState then begin
{the mouse is not over a button or its over a new one}
scPrevState := scCurrentState;
scCurrentState := NewState;
{don't depress the center button if the mouse moves over it}
if NewState = ssCenterBtn then
scCurrentState := ssNormal;
scMouseOverBtn := not (scCurrentState in [ssNone, ssNormal]);
scInvalidateButton(scPrevState);
scInvalidateButton(scCurrentState);
end;
{until the mouse button is released}
{$IFDEF MSWINDOWS}
until ({$IFNDEF LCL} GetAsyncKeyState(scLButton) {$ELSE} GetKeyState(scLButton) {$ENDIF} and $8000) = 0;
{$ELSE} //GTK GetKeyState returns 0
until not (csLButtonDown in ControlState);
{$ENDIF}
scDoMouseUp;
end;
procedure TOvcSpinner.scDoMouseDown(const XPos, YPos: Integer);
begin
scPrevState := scCurrentState;
{find which button was clicked}
scCurrentState := scCheckMousePos;
scMouseOverBtn := True;
scInvalidateButton(scPrevState);
scInvalidateButton(scCurrentState);
{initialize and start repeating}
FRepeatCount := 0;
scLButton := GetLeftButton;
scNextMsgTime := GetTickCount-1;
scDoAutoRepeat;
end;
procedure TOvcSpinner.scDoMouseUp;
begin
{save last state and redraw}
scPrevState := scCurrentState;
scCurrentState := ssNormal;
scMouseOverBtn := False;
scInvalidateButton(scPrevState);
scInvalidateButton(scCurrentState);
scDrawButton(False);
end;
procedure TOvcSpinner.scDrawArrow(const R: TRect; const Pressed: Boolean;
const Direction: TOvcDirection);
var
ArrowWidth, ArrowHeight : Integer;
X, Y : Integer;
LeftPoint, RightPoint, PointPoint : TPoint;
PLeftPoint, PRightPoint, PPointPoint : TPoint;
begin
if not FShowArrows then
Exit;
with Canvas do begin
ArrowWidth := GetArrowWidth(R.Right-R.Left, R.Bottom-R.Top);
ArrowHeight := (ArrowWidth + 1) div 2;
if Direction in [dUp, dDown] then begin
X := (R.Right-R.Left-ArrowWidth) div 2;
Y := (R.Bottom-R.Top-ArrowHeight) div 2;
end else begin
X := (R.Right-R.Left-ArrowHeight) div 2;
Y := (R.Bottom-R.Top-ArrowWidth) div 2;
end;
case Direction of
dUp :
begin
LeftPoint := Point(R.Left + X, Y + ArrowHeight + R.Top - 1);
RightPoint := Point(R.Left + X + ArrowWidth - 1, Y + ArrowHeight + R.Top -1 );
PointPoint := Point(R.Left + X + (ArrowWidth div 2), Y + R.Top);
end;
dDown :
begin
LeftPoint := Point(R.Left + X, Y + R.Top);
RightPoint := Point(R.Left + X + ArrowWidth - 1 , Y + R.Top);
PointPoint := Point(R.Left + X + (ArrowWidth div 2), Y + ArrowHeight + R.Top - 1);
end;
dRight :
begin
LeftPoint := Point(R.Left + X, Y + R.Top);
RightPoint := Point(R.Left + X, Y + ArrowWidth + R.Top - 1);
PointPoint := Point(R.Left + X + ArrowHeight - 1, Y + (ArrowWidth div 2) + R.Top);
end;
dLeft :
begin
LeftPoint := Point(R.Left + X + ArrowHeight - 1, Y + R.Top);
RightPoint := Point(R.Left + X + ArrowHeight - 1, Y + ArrowWidth - 1 + R.Top);
PointPoint := Point(R.Left + X, Y + (ArrowWidth div 2) + R.Top);
end;
end;
PLeftPoint.X := LeftPoint.X + 1;
PLeftPoint.Y := LeftPoint.Y + 1;
PRightPoint.X := RightPoint.X + 1;
PRightPoint.Y := RightPoint.Y + 1;
PPointPoint.X := PointPoint.X + 1;
PPointPoint.Y := PointPoint.Y + 1;
if Pressed then begin
Pen.Color := clBtnFace;
Brush.Color := clBtnFace;
Polygon([LeftPoint, RightPoint, PointPoint]);
Pen.Color := clBtnText;
Brush.Color := clBtnText;
Polygon([PLeftPoint, PRightPoint, PPointPoint]);
end else begin
Pen.Color := clBtnFace;
Brush.Color := clBtnFace;
Polygon([PLeftPoint, PRightPoint, PPointPoint]);
Pen.Color := clBtnText;
Brush.Color := clBtnText;
Polygon([LeftPoint, RightPoint, PointPoint]);
end;
end;
end;
procedure TOvcSpinner.scDrawButton(const Redraw : Boolean);
begin
case FStyle of
stDiagonalFourWay : scDrawDiagonalFourWay(Redraw);
stDiagonalHorizontal : scDrawDiagonalHorizontal(Redraw);
stDiagonalVertical : scDrawDiagonalVertical(Redraw);
stFourWay : scDrawFourWayButton(Redraw);
stNormalHorizontal : scDrawNormalButton(Redraw);
stNormalVertical : scDrawNormalButton(Redraw);
stPlainStar : scDrawPlainStar(Redraw);
stStar : scDrawStarButton(Redraw);
end;
end;
procedure TOvcSpinner.scDrawDiagonalFourWay(const Redraw : Boolean);
procedure DrawBasicShape;
begin
with Canvas do begin
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
Pen.Color := clBtnFace;
FillRect(Rect(scTopLeft.X, scTopLeft.Y, scBottomRight.X, scBottomRight.Y));
scDrawLine(scBottomLeft4, scTopRight4, True, ltSingle);
scDrawLine(scBottomLeft, scTopLeft, True, ltTopBevel);
scDrawLine(scTopLeft, scTopRight, True, ltTopBevel);
scDrawLine(scBottomLeft, scBottomRight, True, ltBottomBevel);
scDrawLine(scBottomRight, scTopRight, True, ltBottomBevel);
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssUpBtn : begin
scDrawArrow(Rect(Width Div 4, 0, Width Div 2, Height div 2), not(Up), dUp);
scDrawLine(scTopLeft4, scTopRight4, Up, ltTopBevel);
scDrawLine(scTopLeft4, scBottomLeft4, Up, ltDiagTopBevel);
scDrawLine(scBottomLeft4, scTopRight4, Up, ltBottomSlice);
end;
ssDownBtn : begin
scDrawArrow(Rect(Width Div 2, (Height+1) div 2, Width * 3 Div 4, Height), not(Up), dDown);
scDrawLine(scBottomRight4, scBottomLeft4, Up, ltBottomBevel);
scDrawLine(scTopRight4, scBottomRight4, Up, ltDiagBottomBevel);
scDrawLine(scBottomLeft4, scTopRight4, Up, ltTopSlice);
end;
ssLeftBtn : begin
scDrawArrow(Rect(0, 0, Width Div 4, Height), not(Up), dLeft);
scDrawLine(scTopLeft, scTopLeft4, Up, ltTopBevel);
scDrawLine(scTopLeft, scBottomLeft, Up, ltTopBevel);
scDrawLine(scTopLeft4, scBottomLeft4, Up, ltBottomBevel);
scDrawLine(scBottomLeft, scBottomLeft4, Up, ltBottomBevel);
end;
ssRightBtn : begin
scDrawArrow(Rect(Width * 3 Div 4, 0, Width, Height), not(Up), dRight);
scDrawLine(scTopRight4, scTopRight, Up, ltTopBevel);
scDrawLine(scTopRight4, scBottomRight4, Up, ltTopBevel);
scDrawLine(scTopRight, scBottomRight, Up, ltBottomBevel);
scDrawLine(scBottomRight4, scBottomRight, Up, ltBottomBevel);
end;
end;
end;
end;
begin
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssUpBtn, True);
DrawFace(ssDownBtn, True);
DrawFace(ssLeftBtn, True);
DrawFace(ssRightBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scDrawDiagonalHorizontal(const Redraw : Boolean);
procedure DrawBasicShape;
begin
with Canvas do begin
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
Pen.Color := clBtnFace;
FillRect(Rect(scTopLeft.X, scTopLeft.Y, scBottomRight.X, scBottomRight.Y));
scDrawLine(scBottomLeft, scTopRight, True, ltSingle);
scDrawLine(scBottomLeft, scTopLeft, True, ltTopBevel);
scDrawLine(scTopLeft, scTopRight, True, ltTopBevel);
scDrawLine(scBottomLeft, scBottomRight, True, ltBottomBevel);
scDrawLine(scBottomRight, scTopRight, True, ltBottomBevel);
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssLeftBtn : begin
scDrawArrow(Rect(0, 0, Width div 2, (Height div 2)), not(Up), dLeft);
scDrawLine(scTopLeft, scTopRight, Up, ltTopBevel);
scDrawLine(scTopLeft, scBottomLeft, Up, ltTopBevel);
scDrawLine(scBottomLeft, scTopRight, Up, ltBottomSlice);
end;
ssRightBtn : begin
scDrawArrow(Rect((Width+1) div 2, (Height+1) div 2, Width, Height), not(Up), dRight);
scDrawLine(scBottomLeft, scBottomRight, Up, ltBottomBevel);
scDrawLine(scTopRight, scBottomRight, Up, ltBottomBevel);
scDrawLine(scBottomLeft, scTopRight, Up, ltTopSlice);
end;
end;
end;
end;
begin
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssLeftBtn, True);
DrawFace(ssRightBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scDrawDiagonalVertical(const Redraw : Boolean);
procedure DrawBasicShape;
begin
with Canvas do begin
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
Pen.Color := clBtnFace;
FillRect(Rect(scTopLeft.X, scTopLeft.Y, scBottomRight.X, scBottomRight.Y));
scDrawLine(scBottomLeft, scTopRight, True, ltSingle);
scDrawLine(scBottomLeft, scTopLeft, True, ltTopBevel);
scDrawLine(scTopLeft, scTopRight, True, ltTopBevel);
scDrawLine(scBottomLeft, scBottomRight, True, ltBottomBevel);
scDrawLine(scBottomRight, scTopRight, True, ltBottomBevel);
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssUpBtn : begin
scDrawArrow(Rect(0, 0, Width div 2, (Height div 2)), not(Up), dUp);
scDrawLine(scTopLeft, scTopRight, Up, ltTopBevel);
scDrawLine(scTopLeft, scBottomLeft, Up, ltTopBevel);
scDrawLine(scBottomLeft, scTopRight, Up, ltBottomSlice);
end;
ssDownBtn : begin
scDrawArrow(Rect((Width+1) div 2, (Height+1) div 2, Width, Height), not(Up), dDown);
scDrawLine(scBottomLeft, scBottomRight, Up, ltBottomBevel);
scDrawLine(scTopRight, scBottomRight, Up, ltBottomBevel);
scDrawLine(scBottomLeft, scTopRight, Up, ltTopSlice);
end;
end;
end;
end;
begin
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssUpBtn, True);
DrawFace(ssDownBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scDrawFourWayButton(const Redraw : Boolean);
procedure DrawBasicShape;
begin
with Canvas do begin
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
Pen.Color := clBtnFace;
FillRect(Rect(scTopLeft.X, scTopLeft.Y, scBottomRight.X, scBottomRight.Y));
scDrawLine(scTopLeft, scBottomRight, True, ltSingle);
scDrawLine(scBottomLeft, scTopRight, True, ltSingle);
scDrawLine(scBottomLeft, scTopLeft, True, ltTopBevel);
scDrawLine(scTopLeft, scTopRight, True, ltTopBevel);
scDrawLine(scBottomLeft, scBottomRight, True, ltBottomBevel);
scDrawLine(scBottomRight, scTopRight, True, ltBottomBevel);
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssUpBtn : begin
scDrawArrow(Rect(0, 0, Width, (Height div 3)), not(Up), dUp);
scDrawLine(scTopLeft, scTopRight, Up, ltTopBevel);
scDrawLine(scTopRight, scCenter, Up, ltBottomSliceSquare);
scDrawLine(scTopLeft, scCenter, Up, ltBottomSliceSquare);
end;
ssDownBtn : begin
scDrawArrow(Rect(0, Height - (Height div 3), Width, Height), not(Up), dDown);
scDrawLine(scBottomLeft, scBottomRight, Up, ltBottomBevel);
scDrawLine(scBottomLeft, scCenter, Up, ltTopSliceSquare);
scDrawLine(scBottomRight, scCenter, Up, ltTopSliceSquare);
end;
ssLeftBtn : begin
scDrawArrow(Rect(0, 0, (Width div 3), Height), not(Up), dLeft);
scDrawLine(scTopLeft, scBottomLeft, Up, ltTopBevel);
scDrawLine(scBottomLeft, scCenter, Up, ltBottomSliceSquare);
scDrawLine(scTopLeft, scCenter, Up, ltTopSliceSquare);
end;
ssRightBtn : begin
scDrawArrow(Rect(Width - (Width div 3), 0, Width, Height), not(Up), dRight);
scDrawLine(scTopRight, scBottomRight, Up, ltBottomBevel);
scDrawLine(scTopRight, scCenter, Up, ltTopSliceSquare);
scDrawLine(scBottomRight, scCenter, Up, ltBottomSliceSquare);
end;
end;
end;
end;
begin
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssUpBtn, True);
DrawFace(ssDownBtn, True);
DrawFace(ssLeftBtn, True);
DrawFace(ssRightBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scDrawLine(P1, P2 : TPoint; const Up : Boolean; LineType : TOvcSpinnerLineType);
{-this routine draws a parallel line}
{The Offset is required because of the nature of Bressenham's algorithm}
{Negative Offsets are above the line, and Positive Offsets are Below}
function GetSlope(const P1, P2 : TPoint) : Extended;
var
dX, dY : Integer;
begin
dY := (P1.y - P2.y);
dX := (P1.x - P2.x);
if (dX = 0) then
if dY > 0 then
Result := 999999.0
else
Result := -999999.0
else
Result := dY / dX;
end;
procedure DrawLine(P1, P2 : TPoint; Offset : Integer; const Square : Boolean);
var
Slope : Extended;
P : TPoint;
P1Square, P2Square : Boolean;
begin
P2Square := Square;
P1Square := False;
if P1.x > P2.X then begin
P := P1;
P1 := P2;
P2 := P;
P2Square := False;
P1Square := Square;
end;
Slope := GetSlope(P1, P2);
if Slope >= 0 then begin
if P1.x > scTopMiddle.x then
Offset := -Offset;
end;
if abs(Slope) <= 1 then begin
if Slope = 0 then begin
P1.y := P1.y + Offset;
P2.y := P2.y + Offset;
{these are to shorten the lines a little}
P1.X := P1.X - Abs(Offset);
P2.X := P2.X + Abs(Offset);
end else if (Slope = 1) and (Offset > 0) then begin
if P1Square then begin
P1.X := P1.X + 0 * Abs(Offset);
P1.y := P1.y + 1 * Abs(Offset);
end else begin
P1.X := P1.X + 2 * Abs(Offset);
P1.y := P1.y + 3 * Abs(Offset);
end;
if P2Square then begin
P2.X := P2.X - 1 * Abs(Offset);
P2.y := P2.y - 0 * Abs(Offset);
end else begin
P2.X := P2.X - 3 * Abs(Offset);
P2.y := P2.y - 2 * Abs(Offset);
end;
end else if (Slope = 1) and (Offset < 0) then begin
if P1Square then begin
P1.X := P1.X + 1 * Abs(Offset);
P1.y := P1.y + 0 * Abs(Offset);
end else begin
P1.X := P1.X + 3 * Abs(Offset);
P1.y := P1.y + 2 * Abs(Offset);
end;
if P2Square then begin
P2.X := P2.X - 0 * Abs(Offset);
P2.y := P2.y - 1 * Abs(Offset);
end else begin
P2.X := P2.X - 2 * Abs(Offset);
P2.y := P2.y - 3 * Abs(Offset);
end;
end else if (Slope = -1) and (Offset > 0) then begin
if P1Square then begin
P1.X := P1.X + 1 * Abs(Offset);
P1.y := P1.y - 0 * Abs(Offset);
end else begin
P1.X := P1.X + 3 * Abs(Offset);
P1.y := P1.y - 2 * Abs(Offset);
end;
if P2Square then begin
P2.X := P2.X - 0 * Abs(Offset);
P2.y := P2.y + 1 * Abs(Offset);
end else begin
P2.X := P2.X - 2 * Abs(Offset);
P2.y := P2.y + 3 * Abs(Offset);
end;
end else if (Slope = -1) and (Offset < 0) then begin
if P1Square then begin
P1.X := P1.X + 0 * Abs(Offset);
P1.y := P1.y - 1 * Abs(Offset);
end else begin
P1.X := P1.X + 2 * Abs(Offset);
P1.y := P1.y - 3 * Abs(Offset);
end;
if P2Square then begin
P2.X := P2.X - 1 * Abs(Offset);
P2.y := P2.y + 0 * Abs(Offset);
end else begin
P2.X := P2.X - 3 * Abs(Offset);
P2.y := P2.y + 2 * Abs(Offset);
end;
end else begin
P1.y := P1.y + Offset;
P2.y := P2.y + Offset;
end;
end else begin
P1.x := P1.x + Offset;
P2.x := P2.x + Offset;
if ((P1.x - P2.x) = 0) then begin
{These are to shorten the lines a little}
if (P1.y - P2.y) > 0 then begin
P1.Y := P1.Y - Abs(Offset);
P2.Y := P2.Y + Abs(Offset);
end else begin
P1.Y := P1.Y + Abs(Offset);
P2.Y := P2.Y - Abs(Offset);
end;
end;
end;
scPolyLine([P1, P2]);
end;
const
BtnColor : array[Boolean, 0..7] of TColor = (
(clBtnShadow, clBtnShadow, clBtnFace,
clBtnHighlight, clWindowFrame, clBtnHighLight, clRed, clWindowFrame),
(clBtnHighlight, clBtnFace, clBtnShadow,
clWindowFrame, clBtnHighlight, clBtnFace, clGreen, clWindowFrame));
SpinnerLines : array[TOvcSpinnerLineType, 0..1] of -1..7 = (
(7, -1), {ltSingle}
(4, 1), {ltTopBevel}
(3, 2), {ltBottomBevel}
(4, 7), {ltTopSlice}
(3, 7), {ltBottomSlice}
(4, 7), {ltTopSliceSquare}
(3, 7), {ltBottomSliceSquare}
(4, 1), {ltDiagTopBevel}
(3, 2), {ltDiagBottomBevel}
(0, -1), {ltStarLine0}
(3, -1), {ltStarLine1}
(4, 1), {ltStarLine2}
(3, 2), {ltStarLine3}
(4, 7), {ltStarLine4}
(2, 7) {ltStarLine5}
);
{ComplementLine is used for shading the Left/Right Lines}
ComplementLine : array[TOvcSpinnerLineType] of TOvcSpinnerLineType = (
ltSingle, {ltSingle}
ltTopBevel, {ltTopBevel}
ltBottomBevel, {ltBottomBevel}
ltBottomSlice, {ltTopSlice}
ltTopSlice, {ltBottomSlice}
ltBottomSliceSquare, {ltTopSliceSquare}
ltTopSliceSquare, {ltBottomSliceSquare}
ltDiagBottomBevel, {ltDiagTopBevel}
ltDiagTopBevel, {ltDiagBottomBevel}
ltStarLine1, {ltStarLine0}
ltStarLine0, {ltStarLine1}
ltStarLine3, {ltStarLine2}
ltStarLine2, {ltStarLine3}
ltStarLine5, {ltStarLine4}
ltStarLine4 {ltStarLine5}
);
var
DrawSquare : Boolean;
Offset : Integer;
begin
with Canvas do begin
{if the line is on the other side then ComplementLine}
if (GetSlope(P1, P2) > 1) then
linetype := ComplementLine[LineType];
Pen.Color := BtnColor[Up, SpinnerLines[LineType, 0]];
DrawSquare := False;
Offset := 0;
case LineType of
ltTopSlice :
begin
Offset := 1;
end;
ltBottomSlice :
begin
Offset := -1;
end;
ltTopSliceSquare :
begin
DrawSquare := True;
Offset := 1;
end;
ltBottomSliceSquare :
begin
DrawSquare := True;
Offset := -1;
end;
ltDiagTopBevel :
begin
Offset := 1;
end;
ltDiagBottomBevel :
begin
Offset := -1;
end;
ltStarLine2 :
begin
if P1.X = P2.X then begin
Inc(P1.X);Inc(P1.y);Inc(P2.X);Dec(P2.y);
end else begin
Inc(P1.X);Inc(P1.y);Dec(P2.X);Inc(P2.y);
end;
end;
ltStarLine3 :
begin
if P1.X = P2.X then begin
Dec(P1.X);Inc(P1.y);Dec(P2.X);Dec(P2.y);
end else begin
Inc(P1.X);Dec(P1.y);Dec(P2.X);Dec(P2.y);
end;
end;
ltStarLine4 :
begin
DrawSquare := True;
Offset := 1;
end;
ltStarLine5 :
begin
DrawSquare := True;
Offset := -1;
end;
end;
DrawLine(P1, P2, Offset, DrawSquare);
if SpinnerLines[LineType, 1] = -1 then
Exit;
Pen.Color := BtnColor[Up, SpinnerLines[LineType, 1]];
DrawSquare := False;
Offset := 0;
case LineType of
ltTopBevel :
begin
Offset := 1;
end;
ltBottomBevel :
begin
Offset := -1;
end;
ltTopSliceSquare :
begin
DrawSquare := True;
end;
ltBottomSliceSquare :
begin
DrawSquare := True;
end;
ltDiagTopBevel :
begin
Offset := 2;
end;
ltDiagBottomBevel :
begin
Offset := -2;
end;
ltStarLine2 :
begin
if P1.X = P2.X then begin
Inc(P1.X);Inc(P1.y);Inc(P2.X);Dec(P2.y);
end else begin
Inc(P1.X);Inc(P1.y);Dec(P2.X);Inc(P2.y);
end;
end;
ltStarLine3 :
begin
if P1.X = P2.X then begin
Dec(P1.X);Inc(P1.y);Dec(P2.X);Dec(P2.y);
end else begin
Inc(P1.X);Dec(P1.y);Dec(P2.X);Dec(P2.y);
end;
end;
end;
DrawLine(P1, P2, Offset, DrawSquare);
end;
end;
procedure TOvcSpinner.scDrawNormalButton(const Redraw : Boolean);
var
TopPressed : Boolean;
BottomPressed : Boolean;
UpRect : TRect;
DownRect : TRect;
begin
{$IFDEF MSWINDOWS}
if (csClicked in ControlState) and scMouseOverBtn then begin
{$ELSE} //csClicked not getting set with GTK
if (csLButtonDown in ControlState) and scMouseOverBtn then begin
{$ENDIF}
TopPressed := (scCurrentState in [ssUpBtn, ssRightBtn]);
BottomPressed := (scCurrentState in [ssDownBtn, ssLeftBtn]);
end else begin
TopPressed := False;
BottomPressed := False;
end;
{$IFNDEF LCL}
GetRgnBox(scUpRgn, UpRect);
GetRgnBox(scDownRgn, DownRect);
{$ELSE}
MyMisc.GetRgnBox(scUpRgn, @UpRect);
MyMisc.GetRgnBox(scDownRgn, @DownRect);
{$ENDIF}
if FStyle = stNormalVertical then begin
Inc(UpRect.Right);
Inc(UpRect.Bottom);
Inc(DownRect.Top);
end else begin
Inc(UpRect.Bottom);
Dec(DownRect.Right);
end;
Inc(DownRect.Bottom);
Inc(DownRect.Right);
DrawButtonFace(Canvas, UpRect, 1, bsNew, False, TopPressed, False);
DrawButtonFace(Canvas, DownRect, 1, bsNew, False, BottomPressed, False);
if FStyle = stNormalVertical then begin
scDrawArrow(UpRect, TopPressed, dUp);
scDrawArrow(DownRect, BottomPressed, dDown);
end else begin
scDrawArrow(UpRect, TopPressed, dRight);
scDrawArrow(DownRect, BottomPressed, dLeft);
end;
end;
procedure TOvcSpinner.scDrawPlainStar(const Redraw : Boolean);
var
PC : TColor;
procedure DrawBasicShape;
begin
with Canvas do begin
Pen.Color := clWindowFrame;
Brush.Color := PC;
Brush.Style := bsSolid;
FillRect(Rect(scTopLeft.X, scTopLeft.Y, scBottomRight.X, scBottomRight.Y));
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssUpBtn :
begin
scDrawArrow(Rect(scTopLeftCenter.X, scTopMiddle.Y, scTopRightCenter.X, scCenter.Y), not(Up), dUp);
scDrawLine(scTopMiddle, scTopRightCenter, Up, ltStarLine0);
scDrawLine(scTopRightCenter, scCenter, Up, ltStarLine5);
scDrawLine(scCenter, scTopLeftCenter, Up, ltStarLine5);
scDrawLine(scTopMiddle, scTopLeftCenter, Up, ltStarLine0);
end;
ssDownBtn :
begin
scDrawArrow(Rect(scBottomLeftCenter.X, scCenter.Y, scBottomRightCenter.X, scBottomMiddle.Y), not(Up), dDown);
scDrawLine(scBottomMiddle, scBottomLeftCenter, Up, ltStarLine1);
scDrawLine(scCenter, scBottomLeftCenter, Up, ltStarLine4);
scDrawLine(scBottomRightCenter, scCenter, Up, ltStarLine4);
scDrawLine(scBottomMiddle, scBottomRightCenter, Up, ltStarLine1);
end;
ssLeftBtn :
begin
scDrawArrow(Rect(scLeftMiddle.X, scTopLeftCenter.Y, scCenter.X, scBottomLeftCenter.Y), not(Up), dLeft);
scDrawLine(scLeftMiddle, scTopLeftCenter, Up, ltStarLine0);
scDrawLine(scTopLeftCenter, scCenter, Up, ltStarLine4);
scDrawLine(scCenter, scBottomLeftCenter, Up, ltStarLine5);
scDrawLine(scBottomLeftCenter, scLeftMiddle, Up, ltStarLine1);
end;
ssRightBtn :
begin
scDrawArrow(Rect(scCenter.X, scTopRightCenter.Y, scRightMiddle.X, scBottomRightCenter.Y),not(Up), dRight);
scDrawLine(scCenter, scTopRightCenter, Up, ltStarLine4);
scDrawLine(scTopRightCenter, scRightMiddle, Up, ltStarLine0);
scDrawLine(scRightMiddle, scBottomRightCenter, Up, ltStarLine1);
scDrawLine(scBottomRightCenter, scCenter, Up, ltStarLine5);
end;
end;
end;
end;
begin
{get current parent color}
{$IFDEF VERSION5}
if (Parent is TCustomForm) then
PC := TForm(Parent).Color
else if (Parent is TCustomFrame) then
PC := TFrame(Parent).Color
{$ELSE}
if Parent is TForm then
PC := TForm(Parent).Color
{$ENDIF}
else
PC := Color;
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssUpBtn, True);
DrawFace(ssDownBtn, True);
DrawFace(ssLeftBtn, True);
DrawFace(ssRightBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scDrawStarButton(const Redraw : Boolean);
var
PC : TColor;
procedure DrawBasicShape;
begin
with Canvas do begin
Pen.Color := clWindowFrame;
Brush.Color := PC;
Brush.Style := bsSolid;
FillRect(Rect(scTopLeft.X, scTopLeft.Y,
scBottomRight.X, scBottomRight.Y));
end;
end;
procedure DrawFace(State : TOvcSpinState; Up : Boolean);
begin
with Canvas do begin
case State of
ssUpBtn :
begin
scDrawArrow(Rect(scTopLeftCenter.X, scTopMiddle.Y,
scTopRightCenter.X, scTopLeftCenter.Y), not(Up), dUp);
scDrawLine(scTopMiddle, scTopRightCenter, Up, ltStarLine0);
scDrawLine(scTopRightCenter, scTopLeftCenter, Up, ltStarLine1);
scDrawLine(scTopMiddle, scTopLeftCenter, Up, ltStarLine0);
end;
ssDownBtn :
begin
scDrawArrow(Rect(scBottomLeftCenter.X, scBottomLeftCenter.Y,
scBottomRightCenter.X, scBottomMiddle.Y),not(Up), dDown);
scDrawLine(scBottomMiddle, scBottomLeftCenter, Up, ltStarLine1);
scDrawLine(scBottomRightCenter, scBottomLeftCenter, Up, ltStarLine0);
scDrawLine(scBottomMiddle, scBottomRightCenter, Up, ltStarLine1);
end;
ssLeftBtn :
begin
scDrawArrow(Rect(scLeftMiddle.X, scTopLeftCenter.Y,
scTopLeftCenter.X, scBottomLeftCenter.Y), not(Up), dLeft);
scDrawLine(scLeftMiddle, scTopLeftCenter, Up, ltStarLine0);
scDrawLine(scTopLeftCenter, scBottomLeftCenter, Up, ltStarLine1);
scDrawLine(scBottomLeftCenter, scLeftMiddle, Up, ltStarLine1);
end;
ssRightBtn :
begin
scDrawArrow(Rect(scTopRightCenter.X, scTopRightCenter.Y,
scRightMiddle.X, scBottomRightCenter.Y), not(Up), dRight);
scDrawLine(scTopRightCenter, scBottomRightCenter, Up, ltStarLine0);
scDrawLine(scRightMiddle, scTopRightCenter, Up, ltStarLine0);
scDrawLine(scBottomRightCenter, scRightMiddle, Up, ltStarLine1);
end;
ssCenterBtn :
begin
scDrawLine(scTopLeftCenter, scTopRightCenter, Up, ltStarLine2);
scDrawLine(scTopLeftCenter, scBottomLeftCenter, Up, ltStarLine2);
scDrawLine(scTopRightCenter, scBottomRightCenter, Up, ltStarLine3);
scDrawLine(scBottomLeftCenter, scBottomRightCenter, Up, ltStarLine3);
end;
end;
end;
end;
begin
{get current parent color}
{$IFDEF VERSION5}
if (Parent is TCustomForm) then
PC := TForm(Parent).Color
else if (Parent is TCustomFrame) then
PC := TFrame(Parent).Color
{$ELSE}
if Parent is TForm then
PC := TForm(Parent).Color
{$ENDIF}
else
PC := Color;
with Canvas do begin
if Redraw then begin
DrawBasicShape;
DrawFace(ssUpBtn, True);
DrawFace(ssDownBtn, True);
DrawFace(ssLeftBtn, True);
DrawFace(ssRightBtn, True);
DrawFace(ssCenterBtn, True);
end;
if scPrevState <> scCurrentState then
DrawFace(scPrevState, True);
if scMouseOverBtn then
DrawFace(scCurrentState, False);
end;
end;
procedure TOvcSpinner.scInvalidateButton(const State : TOvcSpinState);
begin
case State of
ssUpBtn : InvalidateRgn(Handle, scUpRgn, False);
ssDownBtn : InvalidateRgn(Handle, scDownRgn, False);
ssLeftBtn : InvalidateRgn(Handle, scLeftRgn, False);
ssRightBtn : InvalidateRgn(Handle, scRightRgn, False);
ssCenterBtn : InvalidateRgn(Handle, scCenterRgn, False);
end;
end;
procedure TOvcSpinner.scPolyline(const Points: array of TPoint);
begin
Canvas.Polyline(Points);
with Points[High(Points)] do
Canvas.Pixels[X,Y] := Canvas.Pen.Color;
end;
procedure TOvcSpinner.scUpdateNormalSizes;
var
scHeight : Integer; {Height of client area}
scWidth : Integer; {Width of client area}
begin
{get size of client area}
scWidth := scBottomRight.X;
scHeight := scBottomRight.Y;
{setup the TRect structures with new sizes}
if FStyle = stNormalVertical then begin
scUpRgn := CreateRectRgn(0, 0, scWidth, scHeight div 2);
scDownRgn := CreateRectRgn(0, scHeight div 2, scWidth, scHeight);
end else begin
scUpRgn := CreateRectRgn(scWidth div 2, 0, scWidth, scHeight);
scDownRgn := CreateRectRgn(0, 0, scWidth div 2, scHeight);
end;
end;
procedure TOvcSpinner.scUpdateFourWaySizes;
var
Points : array[0..2] of TPoint;
begin
Points[0] := scTopLeft;
Points[1] := scTopRight;
Points[2] := scCenter;
scUpRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scBottomLeft;
Points[1] := scCenter;
Points[2] := scBottomRight;
scDownRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scTopLeft;
Points[1] := scCenter;
Points[2] := scBottomLeft;
scLeftRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scTopRight;
Points[1] := scBottomRight;
Points[2] := scCenter;
scRightRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
end;
procedure TOvcSpinner.scUpdateStarSizes;
var
Points : array[0..3] of TPoint;
begin
{up}
Points[0] := scTopMiddle;
Points[1] := scTopRightCenter;
Points[2] := scTopLeftCenter;
scUpRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
{down}
Points[0] := scBottomMiddle;
Points[1] := scBottomLeftCenter;
Points[2] := scBottomRightCenter;
scDownRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
{left}
Points[0] := scLeftMiddle;
Points[1] := scTopLeftCenter;
Points[2] := scBottomLeftCenter;
scLeftRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
{right}
Points[0] := scRightMiddle;
Points[1] := scBottomRightCenter;
Points[2] := scTopRightCenter;
scRightRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
{center}
Points[0] := scTopLeftCenter;
Points[1] := scTopRightCenter;
Points[2] := scBottomRightCenter;
Points[3] := scBottomLeftCenter;
scCenterRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
end;
procedure TOvcSpinner.scUpdateDiagonalVerticalSizes;
var
Points : array[0..2] of TPoint;
begin
Points[0] := scTopLeft;
Points[1] := scTopRight;
Points[2] := scBottomLeft;
scUpRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scBottomLeft;
Points[1] := scTopRight;
Points[2] := scBottomRight;
scDownRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
end;
procedure TOvcSpinner.scUpdateDiagonalHorizontalSizes;
var
Points : array[0..2] of TPoint;
begin
Points[0] := scTopLeft;
Points[1] := scTopRight;
Points[2] := scBottomLeft;
scLeftRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scBottomLeft;
Points[1] := scTopRight;
Points[2] := scBottomRight;
scRightRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
end;
procedure TOvcSpinner.scUpdateDiagonalFourWaySizes;
var
Points : array[0..3] of TPoint;
begin
Points[0] := scTopLeft4;
Points[1] := scTopRight4;
Points[2] := scBottomLeft4;
scUpRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scTopRight4;
Points[1] := scBottomRight4;
Points[2] := scBottomLeft4;
scDownRgn := CreatePolygonRgn(Points, 3, ALTERNATE);
Points[0] := scTopLeft;
Points[1] := scTopLeft4;
Points[2] := scBottomLeft4;
Points[3] := scBottomLeft;
scLeftRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
Points[0] := scTopRight4;
Points[1] := scTopRight;
Points[2] := scBottomRight;
Points[3] := scBottomRight4;
scRightRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
end;
procedure TOvcSpinner.scUpdatePlainStarSizes;
var
Points : array[0..3] of TPoint;
begin
Points[0] := scTopMiddle;
Points[1] := scTopRightCenter;
Points[2] := scCenter;
Points[3] := scTopLeftCenter;
scUpRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
Points[0] := scBottomLeftCenter;
Points[1] := scCenter;
Points[2] := scBottomRightCenter;
Points[3] := scBottomMiddle;
scDownRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
Points[0] := scLeftMiddle;
Points[1] := scTopLeftCenter;
Points[2] := scCenter;
Points[3] := scBottomLeftCenter;
scLeftRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
Points[0] := scTopRightCenter;
Points[1] := scRightMiddle;
Points[2] := scBottomRightCenter;
Points[3] := scCenter;
scRightRgn := CreatePolygonRgn(Points, 4, ALTERNATE);
end;
procedure TOvcSpinner.scUpdateSizes;
begin
{store info about button locations}
scDeleteRegions;
case FStyle of
stNormalVertical : scUpdateNormalSizes;
stNormalHorizontal : scUpdateNormalSizes;
stFourWay : scUpdateFourWaySizes;
stStar : scUpdateStarSizes;
stDiagonalVertical : scUpdateDiagonalVerticalSizes;
stDiagonalHorizontal : scUpdateDiagonalHorizontalSizes;
stDiagonalFourWay : scUpdateDiagonalFourWaySizes;
stPlainStar : scUpdatePlainStarSizes;
end;
end;
procedure TOvcSpinner.Paint;
begin
scDrawButton(True);
end;
procedure TOvcSpinner.SetAcceleration(const Value : Integer);
begin
if Value <= 10 then
FAcceleration := Value;
end;
{ - Added}
procedure TOvcSpinner.SetAutoRepeat(Value: Boolean);
begin
FAutoRepeat := Value;
if FAutoRepeat and not (csLoading in ComponentState) then
scDoAutoRepeat;
end;
procedure TOvcSpinner.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
L, T, H, W : Integer;
begin
if (csDesigning in ComponentState) and not (csLoading in ComponentState) then begin
{limit smallest size}
if AWidth < scDefMinSize then
AWidth := scDefMinSize ;
if AHeight < scDefMinSize then
AHeight := scDefMinSize ;
end;
L := Left;
T := Top;
H := Height;
W := Width;
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
if (L <> Left) or (T <> Top) or (H <> Height) or (W <> Width) then begin
scTopLeft := Point(0 , 0 );
scTopRight := Point(Width-1 , 0 );
scBottomLeft := Point(0 , Height-1);
scBottomRight := Point(Width-1 , Height-1);
scCenter := Point(Width div 2 , Height div 2 );
scTopLeftCenter := Point(Width * 1 div 3 , Height * 1 div 3 );
scBottomLeftCenter := Point(Width * 1 div 3 , Height * 2 div 3 );
scTopRightCenter := Point(Width * 2 div 3 , Height * 1 div 3 );
scBottomRightCenter:= Point(Width * 2 div 3 , Height * 2 div 3 );
scTopMiddle := Point(Width div 2 , 0 );
scBottomMiddle:= Point(Width div 2 , Height - 1 );
scLeftMiddle := Point(0 , Height div 2 );
scRightMiddle := Point(Width - 1 , Height div 2 );
scTopLeft4 := Point(Width div 4 , 0 );
scBottomLeft4 := Point(Width div 4 , Height - 1 );
scTopRight4 := Point(Width * 3 div 4, 0 );
scBottomRight4:= Point(Width * 3 div 4, Height - 1 );
end;
{update sizes of control and button regions}
scUpdateSizes;
if HandleAllocated then
Invalidate;
end;
procedure TOvcSpinner.SetShowArrows(const Value : Boolean);
begin
if Value <> FShowArrows then begin
FShowArrows := Value;
Invalidate;
end;
end;
procedure TOvcSpinner.SetStyle(Value : TOvcSpinnerStyle);
begin
if Value <> FStyle then begin
FStyle := Value;
{$IFNDEF LCL}
RecreateWnd;
{$ELSE}
MyMisc.RecreateWnd(Self);
{$ENDIF}
if not (csLoading in ComponentState) then
SetBounds(Left, Top, Width, Height); {force resize}
end;
end;
procedure TOvcSpinner.WMGetDlgCode(var Msg : TWMGetDlgCode);
begin
{tell windows we are a static control to avoid receiving the focus}
Msg.Result := DLGC_STATIC;
end;
procedure TOvcSpinner.WMLButtonDown(var Msg : TWMLButtonDown);
begin
inherited;
if Assigned(FFocusedControl) then begin
if GetFocus <> FFocusedControl.Handle then begin
{set focus to ourself to force field validation}
SetFocus;
{allow message processing}
Application.ProcessMessages;
{if we didn't keep the focus, something must have happened--exit}
if (GetFocus <> Handle) then
Exit;
end;
if GetFocus <> FFocusedControl.Handle then
if FFocusedControl.CanFocus then
FFocusedControl.SetFocus;
end;
try
scDoMouseDown(Msg.XPos, Msg.YPos);
except
scDoMouseUp;
raise;
end;
end;
procedure TOvcSpinner.WMLButtonUp(var Msg : TWMLButtonUp);
begin
inherited;
scDoMouseUp;
end;
end.