383 lines
9.9 KiB
ObjectPascal
383 lines
9.9 KiB
ObjectPascal
{ rxdice unit
|
|
|
|
Copyright (C) 2005-2017 Lagunov Aleksey alexs75@yandex.ru and Lazarus team
|
|
original conception from rx library for Delphi (c)
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version with the following modification:
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent modules,and
|
|
to copy and distribute the resulting executable under terms of your choice,
|
|
provided that you also meet, for each linked independent module, the terms
|
|
and conditions of the license of that module. An independent module is a
|
|
module which is not derived from or based on this library. If you modify
|
|
this library, you may extend this exception to your version of the library,
|
|
but you are not obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; if not, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
}
|
|
unit rxdice;
|
|
|
|
interface
|
|
|
|
{$I rx.inc}
|
|
|
|
uses SysUtils, LCLType, LCLProc, LCLIntf, LMessages, Classes, Graphics,
|
|
Controls, Forms, StdCtrls, ExtCtrls, Menus, rxlclutils;
|
|
|
|
type
|
|
TRxDiceValue = 1..6;
|
|
|
|
{ TRxDice }
|
|
|
|
TRxDice = class(TCustomControl)
|
|
private
|
|
{ Private declarations }
|
|
FActive: Boolean;
|
|
FAutoSize: Boolean;
|
|
FBitmap: TBitmap;
|
|
FInterval: Cardinal;
|
|
FAutoStopInterval: Cardinal;
|
|
FOnChange: TNotifyEvent;
|
|
FRotate: Boolean;
|
|
FShowFocus: Boolean;
|
|
FTimer: TTimer;
|
|
FTickCount: Longint;
|
|
FValue: TRxDiceValue;
|
|
FOnStart: TNotifyEvent;
|
|
FOnStop: TNotifyEvent;
|
|
procedure CMFocusChanged(var Message: TLMessage); message CM_FOCUSCHANGED;
|
|
procedure WMSize(var Message: TLMSize); message LM_SIZE;
|
|
procedure CreateBitmap;
|
|
procedure SetAutoSize(Value: Boolean);
|
|
procedure SetInterval(Value: Cardinal);
|
|
procedure SetRotate(AValue: Boolean);
|
|
procedure SetShowFocus(AValue: Boolean);
|
|
procedure SetValue(Value: TRxDiceValue);
|
|
procedure TimerExpired(Sender: TObject);
|
|
protected
|
|
{ Protected declarations }
|
|
function GetPalette: HPALETTE; override;
|
|
procedure AdjustSize; override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer); override;
|
|
procedure Paint; override;
|
|
procedure Change; dynamic;
|
|
procedure DoStart; dynamic;
|
|
procedure DoStop; dynamic;
|
|
public
|
|
{ Public declarations }
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure RandomValue;
|
|
published
|
|
{ Published declarations }
|
|
property Align;
|
|
property AutoSize: Boolean read FAutoSize write SetAutoSize default True;
|
|
property AutoStopInterval: Cardinal read FAutoStopInterval write FAutoStopInterval default 0;
|
|
property Color;
|
|
property Cursor;
|
|
property DragMode;
|
|
property DragCursor;
|
|
property Enabled;
|
|
property Interval: Cardinal read FInterval write SetInterval default 60;
|
|
property ParentColor;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property Rotate: Boolean read FRotate write SetRotate;
|
|
property ShowFocus: Boolean read FShowFocus write SetShowFocus;
|
|
property ShowHint;
|
|
property Anchors;
|
|
property Constraints;
|
|
property DragKind;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Value: TRxDiceValue read FValue write SetValue default 1;
|
|
property Visible;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnMouseMove;
|
|
property OnMouseDown;
|
|
property OnMouseUp;
|
|
property OnMouseWheel;
|
|
property OnMouseWheelDown;
|
|
property OnMouseWheelUp;
|
|
property OnKeyDown;
|
|
property OnKeyUp;
|
|
property OnKeyPress;
|
|
property OnDragOver;
|
|
property OnDragDrop;
|
|
property OnEndDrag;
|
|
property OnStartDrag;
|
|
property OnContextPopup;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
property OnStart: TNotifyEvent read FOnStart write FOnStart;
|
|
property OnStop: TNotifyEvent read FOnStop write FOnStop;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
end;
|
|
|
|
{$I RXDICE.INC}
|
|
|
|
implementation
|
|
|
|
{ TRxDice }
|
|
|
|
constructor TRxDice.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Randomize;
|
|
ControlStyle := [csClickEvents, csSetCaption, csCaptureMouse,
|
|
csOpaque, csDoubleClicks];
|
|
FValue := 1;
|
|
FInterval := 60;
|
|
CreateBitmap;
|
|
FAutoSize := True;
|
|
Width := FBitmap.Width + 2;
|
|
Height := FBitmap.Height + 2;
|
|
end;
|
|
|
|
destructor TRxDice.Destroy;
|
|
begin
|
|
FOnChange := nil;
|
|
if FBitmap <> nil then FBitmap.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TRxDice.GetPalette: HPALETTE;
|
|
begin
|
|
if FBitmap <> nil then Result := FBitmap.Palette
|
|
else Result := 0;
|
|
end;
|
|
|
|
procedure TRxDice.RandomValue;
|
|
var
|
|
Val: Byte;
|
|
begin
|
|
Val := Random(6) + 1;
|
|
if Val = Byte(FValue) then
|
|
begin
|
|
if Val = 1 then Inc(Val)
|
|
else Dec(Val);
|
|
end;
|
|
SetValue(TRxDiceValue(Val));
|
|
end;
|
|
|
|
procedure TRxDice.DoStart;
|
|
begin
|
|
if Assigned(FOnStart) then FOnStart(Self);
|
|
end;
|
|
|
|
procedure TRxDice.DoStop;
|
|
begin
|
|
if Assigned(FOnStop) then FOnStop(Self);
|
|
end;
|
|
|
|
procedure TRxDice.CMFocusChanged(var Message: TLMessage);
|
|
var
|
|
Active: Boolean;
|
|
begin
|
|
{ with Message do Active := (Sender = Self);
|
|
if Active <> FActive then begin
|
|
FActive := Active;
|
|
if FShowFocus then Invalidate;
|
|
end;}
|
|
inherited;
|
|
end;
|
|
|
|
procedure TRxDice.WMSize(var Message: TLMSize);
|
|
begin
|
|
inherited;
|
|
AdjustSize;
|
|
end;
|
|
|
|
procedure TRxDice.CreateBitmap;
|
|
begin
|
|
if FBitmap = nil then FBitmap := TBitmap.Create;
|
|
case FValue of
|
|
1:FBitmap.Handle := CreatePixmapIndirect(@DICE1[0], GetSysColor(COLOR_BTNFACE));
|
|
2:FBitmap.Handle := CreatePixmapIndirect(@DICE2[0], GetSysColor(COLOR_BTNFACE));
|
|
3:FBitmap.Handle := CreatePixmapIndirect(@DICE3[0], GetSysColor(COLOR_BTNFACE));
|
|
4:FBitmap.Handle := CreatePixmapIndirect(@DICE4[0], GetSysColor(COLOR_BTNFACE));
|
|
5:FBitmap.Handle := CreatePixmapIndirect(@DICE5[0], GetSysColor(COLOR_BTNFACE));
|
|
6:FBitmap.Handle := CreatePixmapIndirect(@DICE6[0], GetSysColor(COLOR_BTNFACE));
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.AdjustSize;
|
|
var
|
|
MinSide: Integer;
|
|
begin
|
|
if not (csReading in ComponentState) then
|
|
begin
|
|
if AutoSize and Assigned(FBitmap) and (FBitmap.Width > 0) and
|
|
(FBitmap.Height > 0) then
|
|
SetBounds(Left, Top, FBitmap.Width + 2, FBitmap.Height + 2)
|
|
else
|
|
begin
|
|
{ Adjust aspect ratio if control size changed }
|
|
MinSide := Width;
|
|
if Height < Width then MinSide := Height;
|
|
SetBounds(Left, Top, MinSide, MinSide);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if (Button = mbLeft) and TabStop and CanFocus then SetFocus;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TRxDice.Paint;
|
|
var
|
|
ARect: TRect;
|
|
|
|
procedure DrawBitmap;
|
|
var
|
|
TmpImage: TBitmap;
|
|
IWidth, IHeight: Integer;
|
|
IRect: TRect;
|
|
begin
|
|
IWidth := FBitmap.Width;
|
|
IHeight := FBitmap.Height;
|
|
IRect := Rect(0, 0, IWidth, IHeight);
|
|
TmpImage := TBitmap.Create;
|
|
try
|
|
TmpImage.Width := IWidth;
|
|
TmpImage.Height := IHeight;
|
|
TmpImage.Canvas.Brush.Color := Self.Brush.Color;
|
|
// TmpImage.Canvas.BrushCopy(IRect, FBitmap, IRect, FBitmap.TransparentColor);
|
|
InflateRect(ARect, -1, -1);
|
|
// Canvas.StretchDraw(ARect, TmpImage);
|
|
Canvas.StretchDraw(ARect, FBitmap);
|
|
|
|
finally
|
|
TmpImage.Free;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
ARect := ClientRect;
|
|
if FBitmap <> nil then DrawBitmap;
|
|
{ if Focused and FShowFocus and TabStop and not (csDesigning in ComponentState) then
|
|
begin
|
|
Canvas.DrawFocusRect(ARect);
|
|
end;}
|
|
end;
|
|
|
|
procedure TRxDice.TimerExpired(Sender: TObject);
|
|
var
|
|
ParentForm: TCustomForm;
|
|
Now: Longint;
|
|
begin
|
|
RandomValue;
|
|
if not FRotate then
|
|
begin
|
|
FTimer.Free;
|
|
FTimer := nil;
|
|
if (csDesigning in ComponentState) then
|
|
begin
|
|
ParentForm := GetParentForm(Self);
|
|
if ParentForm <> nil then ParentForm.Designer.Modified;
|
|
end;
|
|
DoStop;
|
|
end
|
|
else
|
|
if AutoStopInterval > 0 then
|
|
begin
|
|
Now := GetTickCount;
|
|
if (Now - FTickCount >= AutoStopInterval) or (Now < FTickCount) then
|
|
Rotate := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.Change;
|
|
begin
|
|
if Assigned(FOnChange) then FOnChange(Self);
|
|
end;
|
|
|
|
procedure TRxDice.SetValue(Value: TRxDiceValue);
|
|
begin
|
|
if FValue <> Value then
|
|
begin
|
|
FValue := Value;
|
|
CreateBitmap;
|
|
Invalidate;
|
|
Change;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.SetAutoSize(Value: Boolean);
|
|
begin
|
|
if Value <> FAutoSize then
|
|
begin
|
|
FAutoSize := Value;
|
|
AdjustSize;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.SetInterval(Value: Cardinal);
|
|
begin
|
|
if FInterval <> Value then
|
|
begin
|
|
FInterval := Value;
|
|
if FTimer <> nil then FTimer.Interval := FInterval;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.SetRotate(AValue: Boolean);
|
|
begin
|
|
if FRotate <> AValue then
|
|
begin
|
|
if AValue then
|
|
begin
|
|
if FTimer = nil then FTimer := TTimer.Create(Self);
|
|
try
|
|
with FTimer do
|
|
begin
|
|
OnTimer := @TimerExpired;
|
|
Interval := FInterval;
|
|
Enabled := True;
|
|
end;
|
|
FRotate := AValue;
|
|
FTickCount := GetTickCount;
|
|
DoStart;
|
|
except
|
|
FTimer.Free;
|
|
FTimer := nil;
|
|
raise;
|
|
end;
|
|
end
|
|
else
|
|
FRotate := AValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TRxDice.SetShowFocus(AValue: Boolean);
|
|
begin
|
|
if FShowFocus <> AValue then
|
|
begin
|
|
FShowFocus := AValue;
|
|
if not (csDesigning in ComponentState) then Invalidate;
|
|
end;
|
|
end;
|
|
|
|
end.
|