unit mbColorPickerControl; {$MODE DELPHI} interface uses LCLIntf, LCLType, LMessages, SysUtils, Classes, Controls, Graphics, Forms, Themes, HTMLColors, mbColorConv, mbBasicPicker; type TMarkerStyle = (msCircle, msSquare, msCross, msCrossCirc); { TmbCustomPicker } TmbCustomPicker = class(TmbBasicPicker) private FHintFormat: string; FMarkerStyle: TMarkerStyle; FWebSafe: boolean; procedure SetMarkerStyle(s: TMarkerStyle); procedure SetWebSafe(s: boolean); protected FSelected: TColor; mx, my: integer; procedure CreateGradient; override; function GetHintStr({%H-}X, {%H-}Y: Integer): String; override; function GetSelectedColor: TColor; override; procedure InternalDrawMarker(X, Y: Integer; C: TColor); procedure SetSelectedColor(C: TColor); override; procedure WebSafeChanged; dynamic; procedure CMGotFocus(var Message: TLMessage); message CM_ENTER; procedure CMLostFocus(var Message: TLMessage); message CM_EXIT; // procedure CMMouseLeave(var Message: TLMessage); message CM_MOUSELEAVE; property MarkerStyle: TMarkerStyle read FMarkerStyle write SetMarkerStyle; public constructor Create(AOwner: TComponent); override; property ColorUnderCursor; published property HintFormat: string read FHintFormat write FHintFormat; property WebSafe: boolean read FWebSafe write SetWebSafe default false; end; TmbColorPickerControl = class(TmbCustomPicker) published property Anchors; property Align; property BorderSpacing; property ShowHint; property ParentShowHint; property Visible; property Enabled; property PopupMenu; property TabOrder; property TabStop default true; property Color; property ParentColor; property DragCursor; property DragMode; property DragKind; property Constraints; property OnContextPopup; property OnGetHintStr; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnDragDrop; property OnDragOver; property OnEndDrag; property OnEnter; property OnExit; property OnResize; property OnStartDrag; end; TmbHSLVColorPickerControl = class(TmbColorPickerControl) private FBrightnessMode: TBrightnessMode; function GetHue: Integer; function GetLum: Integer; function GetSat: Integer; function GetVal: Integer; function GetRed: Integer; function GetGreen: Integer; function GetBlue: Integer; procedure SetHue(h: integer); procedure SetLum(L: Integer); procedure SetSat(s: integer); procedure SetVal(v: integer); procedure SetRed(R: Integer); procedure SetGreen(G: Integer); procedure SetBlue(B: Integer); protected FHue, FSat, FLum, FVal: Double; FMaxHue, FMaxSat, FMaxLum, FMaxVal: Integer; procedure ColorToHSLV(c: TColor; var H, S, L, V: Double); procedure CorrectCoords(var x, y: integer); function HSLVtoColor(H, S, L, V: Double): TColor; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure SelectColor({%H-}x, {%H-}y: Integer); virtual; procedure SetBrightnessMode(AMode: TBrightnessMode); virtual; procedure SetMaxHue(H: Integer); virtual; procedure SetMaxLum(L: Integer); virtual; procedure SetMaxSat(S: Integer); virtual; procedure SetMaxVal(V: Integer); virtual; procedure SetRelHue(H: Double); virtual; procedure SetRelLum(L: Double); virtual; procedure SetRelSat(S: Double); virtual; procedure SetRelVal(V: Double); virtual; public constructor Create(AOwner: TComponent); override; property RelHue: Double read FHue write SetRelHue; property RelSaturation: Double read FSat write SetRelSat; property RelLuminance: Double read FLum write SetRelLum; property RelValue: Double read FVal write SetRelVal; property Red: Integer read GetRed write SetRed; property Green: Integer read GetGreen write SetGreen; property Blue: Integer read GetBlue write SetBlue; published property BrightnessMode: TBrightnessMode read FBrightnessMode write SetBrightnessMode default bmLuminance; property Hue: integer read GetHue write SetHue; property Luminance: Integer read GetLum write SetLum; property Saturation: integer read GetSat write SetSat; property Value: integer read GetVal write SetVal; property MaxHue: Integer read FMaxHue write SetMaxHue default 360; property MaxSaturation: Integer read FMaxSat write SetMaxSat default 255; property MaxLuminance: Integer read FMaxLum write SetMaxLum default 255; property MaxValue: Integer read FMaxVal write SetMaxVal default 255; end; implementation uses Math, IntfGraphics, fpimage, PalUtils, SelPropUtils, mbUtils; constructor TmbCustomPicker.Create(AOwner: TComponent); begin inherited; //ControlStyle := ControlStyle + [csOpaque] - [csAcceptsControls]; TabStop := true; mx := 0; my := 0; FHintFormat := 'Hex #%hex'#10#13'RGB[%r, %g, %b]'#10#13'HSL[%hslH, %hslS, %hslL]'#10#13'HSV[%hsvH, %hsvS, %hsvV]'#10#13'CMYK[%c, %m, %y, %k]'#10#13'L*a*b*[%cieL, %cieA, %cieB]'#10#13'XYZ[%cieX, %cieY, %cieZ]'; FWebSafe := false; end; procedure TmbCustomPicker.CMGotFocus(var Message: TLMessage); begin inherited; Invalidate; end; procedure TmbCustomPicker.CMLostFocus(var Message: TLMessage); begin inherited; Invalidate; end; (* procedure TmbCustomPicker.CMMouseLeave(var Message: TLMessage); begin mx := 0; my := 0; inherited; end; *) procedure TmbCustomPicker.CreateGradient; var x, y: Integer; col: TColor; fpcol: TFPColor; intfimg: TLazIntfImage; imgHandle, imgMaskHandle: HBitmap; begin if FBufferBmp = nil then begin FBufferBmp := TBitmap.Create; // FBufferBmp.PixelFormat := pf32bit; end; FBufferBmp.Width := FGradientWidth; FBufferBmp.Height := FGradientHeight; intfimg := TLazIntfImage.Create(FBufferBmp.Width, FBufferBmp.Height); try intfImg.LoadFromBitmap(FBufferBmp.Handle, FBufferBmp.MaskHandle); for y := 0 to FBufferBmp.Height - 1 do begin for x := 0 to FBufferBmp.Width - 1 do begin col := GetGradientColor2D(x, y); if WebSafe then col := GetWebSafe(col); fpcol := TColorToFPColor(col); intfImg.Colors[x, y] := fpcol; end; end; intfimg.CreateBitmaps(imgHandle, imgMaskHandle, false); FBufferBmp.Handle := imgHandle; FBufferBmp.MaskHandle := imgMaskHandle; finally intfimg.Free; end; end; function TmbCustomPicker.GetHintStr(X, Y: Integer): String; begin Result := FormatHint(FHintFormat, GetColorUnderCursor); end; function TmbCustomPicker.GetSelectedColor: TColor; begin Result := FSelected; // valid for most descendents end; procedure TmbCustomPicker.InternalDrawMarker(X, Y: Integer; C: TColor); begin case MarkerStyle of msCircle : DrawSelCirc(x, y, Canvas); msSquare : DrawSelSquare(x, y, Canvas); msCross : DrawSelCross(x, y, Canvas, c); msCrossCirc : DrawSelCrossCirc(x, y, Canvas, c); end; end; procedure TmbCustomPicker.SetMarkerStyle(s: TMarkerStyle); begin if FMarkerStyle <> s then begin FMarkerStyle := s; Invalidate; end; end; procedure TmbCustomPicker.SetSelectedColor(C: TColor); begin FSelected := C; //handled in descendents end; procedure TmbCustomPicker.SetWebSafe(s: boolean); begin if FWebSafe <> s then begin FWebSafe := s; WebSafeChanged; end; end; procedure TmbCustomPicker.WebSafeChanged; begin CreateGradient; Invalidate; end; { TmbHSLVColorPickerControl } constructor TmbHSLVColorPickerControl.Create(AOwner: TComponent); begin inherited Create(AOwner); FBrightnessMode := bmLuminance; FMaxHue := 360; FMaxSat := 255; FMaxVal := 255; FMaxLum := 255; end; procedure TmbHSLVColorPickerControl.ColorToHSLV(c: TColor; var H, S, L, V: Double); begin case FBrightnessMode of bmLuminance : ColorToHSL(c, H, S, L); bmValue : ColorToHSV(c, H, S, V); end; end; procedure TmbHSLVColorPickerControl.CorrectCoords(var x, y: integer); begin Clamp(x, 0, Width - 1); Clamp(y, 0, Height - 1); end; function TmbHSLVColorPickerControl.GetBlue: Integer; begin Result := GetBValue(GetSelectedColor); end; function TmbHSLVColorPickerControl.GetGreen: Integer; begin Result := GetGValue(GetSelectedColor); end; function TmbHSLVColorPickerControl.GetHue: Integer; begin Result := Round(FHue * FMaxHue); end; function TmbHSLVColorPickerControl.GetLum: Integer; begin Result := Round(FLum * FMaxLum); end; function TmbHSLVColorPickerControl.GetRed: Integer; begin Result := GetRValue(GetSelectedColor); end; function TmbHSLVColorPickerControl.GetSat: Integer; begin Result := Round(FSat * FMaxSat); end; function TmbHSLVColorPickerControl.GetVal: Integer; begin Result := Round(FVal * FMaxVal); end; function TmbHSLVColorPickerControl.HSLVtoColor(H, S, L, V: Double): TColor; begin case FBrightnessMode of bmLuminance : Result := HSLToColor(H, S, L); bmValue : Result := HSVtoColor(H, S, V); end; if WebSafe then Result := GetWebSafe(Result); end; procedure TmbHSLVColorPickerControl.KeyDown(var Key: Word; Shift: TShiftState); var eraseKey: Boolean; delta: Integer; begin eraseKey := true; delta := IfThen(ssCtrl in Shift, 10, 1); case Key of VK_LEFT : SelectColor(mx - delta, my); VK_RIGHT : SelectColor(mx + delta, my); VK_UP : SelectColor(mx, my - delta); VK_DOWN : SelectColor(mx, my + delta); else eraseKey := false; end; if eraseKey then Key := 0; inherited; end; procedure TmbHSLVColorPickerControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; if csDesigning in ComponentState then Exit; if Button = mbLeft then SelectColor(x, y); SetFocus; end; procedure TmbHSLVColorPickerControl.MouseMove(Shift: TShiftState; X, Y: Integer); begin inherited; if csDesigning in ComponentState then Exit; if ssLeft in Shift then SelectColor(x, y); end; procedure TmbHSLVColorPickerControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; if csDesigning in ComponentState then Exit; if Button = mbLeft then SelectColor(x, y); end; procedure TmbHSLVColorPickerControl.SelectColor(x, y: Integer); begin end; procedure TmbHSLVColorPickerControl.SetBlue(B: Integer); begin Clamp(B, 0, 255); SetSelectedColor(RgbToColor(Red, Green, B)); end; procedure TmbHSLVColorPickerControl.SetBrightnessMode(AMode: TBrightnessMode); var c: TColor; begin c := HSLVtoColor(FHue, FSat, FLum, FVal); FBrightnessMode := AMode; ColorToHSLV(c, FHue, FSat, FLum, FVal); CreateGradient; Invalidate; DoChange; end; procedure TmbHSLVColorPickerControl.SetGreen(G: Integer); begin Clamp(G, 0, 255); SetSelectedColor(RgbToColor(Red, G, Blue)); end; procedure TmbHSLVColorPickerControl.SetHue(H: Integer); begin SetRelHue(H / FMaxHue); end; procedure TmbHSLVColorPickerControl.SetLum(L: Integer); begin SetRelLum(L / FMaxLum); end; procedure TmbHSLVColorPickerControl.SetMaxHue(h: Integer); begin if h = FMaxHue then exit; FMaxHue := h; CreateGradient; Invalidate; end; procedure TmbHSLVColorPickerControl.SetMaxLum(L: Integer); begin if L = FMaxLum then exit; FMaxLum := L; if BrightnessMode = bmLuminance then begin CreateGradient; Invalidate; end; end; procedure TmbHSLVColorPickerControl.SetMaxSat(S: Integer); begin if S = FMaxSat then exit; FMaxSat := S; CreateGradient; Invalidate; end; procedure TmbHSLVColorPickerControl.SetMaxVal(V: Integer); begin if V = FMaxVal then exit; FMaxVal := V; if BrightnessMode = bmLuminance then begin CreateGradient; Invalidate; end; end; procedure TmbHSLVColorPickerControl.SetRed(R: Integer); begin Clamp(R, 0, 255); SetSelectedColor(RgbToColor(R, Green, Blue)); end; procedure TmbHSLVColorPickerControl.SetRelHue(H: Double); begin Clamp(H, 0, 1.0); if FHue <> H then begin FHue := H; FSelected := HSLVtoColor(FHue, FSat, FLum, FVal); CreateGradient; Invalidate; DoChange; end; end; procedure TmbHSLVColorPickerControl.SetRelLum(L: Double); begin Clamp(L, 0, 1.0); if FLum <> L then begin FLum := L; FSelected := HSLVtoColor(FHue, FSat, FLum, FVal); if BrightnessMode = bmLuminance then begin CreateGradient; Invalidate; end; DoChange; end; end; procedure TmbHSLVColorPickerControl.SetRelSat(S: Double); begin Clamp(S, 0, 1.0); if FSat <> S then begin FSat := S; FSelected := HSLVtoColor(FHue, FSat, FLum, FVal); CreateGradient; Invalidate; DoChange; end; end; procedure TmbHSLVColorPickerControl.SetRelVal(V: Double); begin Clamp(v, 0, 1.0); if FVal <> V then begin FVal := V; if BrightnessMode = bmValue then begin FSelected := HSLVtoColor(FHue, FSat, FLum, FVal); CreateGradient; Invalidate; end; DoChange; end; end; procedure TmbHSLVColorPickerControl.SetSat(S: Integer); begin SetRelSat(S / FMaxSat); end; procedure TmbHSLVColorPickerControl.SetVal(V: Integer); begin SetRelVal(V / FMaxVal); end; end.