lazarus-ccr/components/mbColorLib/mbBasicPicker.pas

236 lines
5.9 KiB
ObjectPascal

unit mbBasicPicker;
{$mode objfpc}{$H+}
interface
uses
LMessages, Classes, SysUtils, Graphics, Controls, ExtCtrls, Forms;
type
THintState = (hsOff, hsWaitingToShow, hsWaitingToHide);
TGetHintStrEvent = procedure (Sender: TObject; X, Y: Integer; var AText: String) of object;
{ TmbBasicPicker }
TmbBasicPicker = class(TCustomControl)
private
FOnChange: TNotifyEvent;
FOnGetHintStr: TGetHintStrEvent;
FLockChange: Integer;
protected
FBufferBmp: TBitmap;
FGradientWidth: Integer;
FGradientHeight: Integer;
FHintShown: Boolean;
procedure CreateGradient; virtual;
procedure DoChange; virtual;
function GetColorUnderCursor: TColor; virtual;
function GetGradientColor({%H-}AValue: Integer): TColor; virtual;
function GetGradientColor2D({%H-}X, {%H-}Y: Integer): TColor; virtual;
function GetHintPos(X, Y: Integer): TPoint; virtual;
function GetHintStr(X, Y: Integer): String; virtual;
function GetSelectedColor: TColor; virtual; abstract;
procedure PaintParentBack; virtual; overload;
procedure PaintParentBack(ACanvas: TCanvas); overload;
procedure PaintParentBack(ACanvas: TCanvas; ARect: TRect); overload;
procedure PaintParentBack(ABitmap: TBitmap); overload;
procedure SetSelectedColor(c: TColor); virtual; abstract;
procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
procedure CMParentColorChanged(var Message: TLMessage); message CM_PARENTCOLORCHANGED;
property ColorUnderCursor: TColor read GetColorUnderCursor;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnGetHintStr: TGetHintStrEvent read FOnGetHintStr write FOnGetHintStr;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetColorAtPoint(X, Y: Integer): TColor; virtual;
function GetHexColorAtPoint(X, Y: integer): string;
function GetHexColorUnderCursor: string; virtual;
procedure Lock;
function IsLocked: Boolean;
procedure Unlock;
published
property ParentColor default true;
property SelectedColor: TColor read GetSelectedColor write SetSelectedColor;
end;
implementation
uses
LCLIntf,
HTMLColors, mbUtils;
constructor TmbBasicPicker.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// ControlStyle := ControlStyle - [csOpaque];
ParentColor := true;
{$IFDEF WINDOWS}
DoubleBuffered := true;
{$ENDIF}
end;
destructor TmbBasicPicker.Destroy;
begin
FBufferBmp.Free;
inherited;
end;
procedure TmbBasicPicker.CMHintShow(var Message: TCMHintShow);
var
cp: TPoint;
hp: TPoint;
begin
if GetColorUnderCursor <> clNone then
with TCMHintShow(Message) do
if not ShowHint then
Message.Result := 1
else
if Hint <> '' then
Message.Result := 0
else
begin
cp := HintInfo^.CursorPos;
hp := GetHintPos(cp.X, cp.Y);
HintInfo^.ReshowTimeout := 0; // must be zero!
HintInfo^.HideTimeout := Application.HintHidePause;
HintInfo^.HintStr := GetHintStr(cp.X, cp.Y);
HintInfo^.HintPos := ClientToScreen(Point(hp.X + 16, hp.Y));
HintInfo^.CursorRect := Rect(cp.X, cp.Y, cp.X+1, cp.Y+1);
Result := 0; // 0 means: show hint
end;
inherited;
end;
procedure TmbBasicPicker.CMParentColorChanged(var Message: TLMessage);
begin
{
if ParentColor then
ControlStyle := ControlStyle - [csOpaque]
else
ControlStyle := ControlStyle + [csOpaque];
}
inherited;
end;
procedure TmbBasicPicker.CreateGradient;
begin
// to be implemented by descendants
end;
procedure TmbBasicPicker.DoChange;
begin
if (FLockChange = 0) and Assigned(FOnChange) and (ComponentState = []) then
FOnChange(self);
end;
function TmbBasicPicker.GetColorAtPoint(x, y: integer): TColor;
begin
Result := Canvas.Pixels[x, y]; // valid for most descendents
end;
function TmbBasicPicker.GetColorUnderCursor: TColor;
var
P: TPoint;
begin
P := ScreenToClient(Mouse.CursorPos);
Result := GetColorAtPoint(P.X, P.Y);
end;
function TmbBasicPicker.GetGradientColor(AValue: Integer): TColor;
begin
Result := clNone;
end;
function TmbBasicPicker.GetGradientColor2D(X, Y: Integer): TColor;
begin
Result := clNone;
end;
function TmbBasicPicker.GetHexColorAtPoint(X, Y: integer): string;
begin
Result := ColorToHex(GetColorAtPoint(x, y));
end;
function TmbBasicPicker.GetHexColorUnderCursor: string;
begin
Result := ColorToHex(GetColorUnderCursor);
end;
function TmbBasicPicker.GetHintPos(X, Y: Integer): TPoint;
begin
Result := Point(X, Y);
end;
function TmbBasicPicker.GetHintStr(X, Y: Integer): String;
begin
Result := '';
if Assigned(FOnGetHintStr) then
FOnGetHintStr(Self, X, Y, Result);
end;
function TmbBasicPicker.IsLocked: Boolean;
begin
Result := FLockChange > 0;
end;
procedure TmbBasicPicker.Lock;
begin
inc(FLockChange);
end;
procedure TmbBasicPicker.PaintParentBack;
begin
PaintParentBack(Canvas);
end;
procedure TmbBasicPicker.PaintParentBack(ABitmap: TBitmap);
begin
ABitmap.Width := Width;
ABitmap.Height := Height;
if Color = clDefault then begin
ABitmap.Transparent := true;
ABitmap.TransparentColor := clForm;
ABitmap.Canvas.Brush.Color := clForm;
end else
ABitmap.Canvas.Brush.Color := Color;
ABitmap.Canvas.FillRect(ABitmap.Canvas.ClipRect);
end;
procedure TmbBasicPicker.PaintParentBack(ACanvas: TCanvas);
var
R: TRect;
begin
R := Rect(0, 0, Width, Height);
PaintParentBack(ACanvas, R);
end;
procedure TmbBasicPicker.PaintParentBack(ACanvas: TCanvas; ARect: TRect);
var
OffScreen: TBitmap;
begin
Offscreen := TBitmap.Create;
try
if Color = clDefault then begin
Offscreen.Transparent := true;
Offscreen.TransparentColor := clForm;
end;
Offscreen.Width := WidthOfRect(ARect);
Offscreen.Height := HeightOfRect(ARect);
PaintParentBack(Offscreen);
ACanvas.Draw(ARect.Left, ARect.Top, Offscreen);
finally
Offscreen.Free;
end;
end;
procedure TmbBasicPicker.Unlock;
begin
dec(FLockChange);
end;
end.