⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spcolorctrls.pas

📁 一款支持Delphi和C++ Builder的VCL控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    Value := 0;
    SkinData := CtrlSkinData;
    JumpWhenClick := True;
    OnChange := HSLEditChange;
  end;

  ColorViewer := TspColorViewer.Create(Form);
  with ColorViewer do
  begin
    Parent := Form;
    SetBounds(HEdit.Left + HEdit.Width + 5,
              PalettePSPPanel.Top + PalettePSPPanel.Height + 10,
              PalettePSPPanel.Left + PalettePSPPanel.Width - (HEdit.Left + HEdit.Width + 5),
              PalettePSPPanel.Left + PalettePSPPanel.Width - (HEdit.Left + HEdit.Width + 5));
  end;

  ButtonTop := LEdit.Top + LEdit.Height + 15;
  ButtonWidth := 70;
  ButtonHeight := 25;


  OkButton := TspSkinButton.Create(Form);
  with OkButton do
   begin
     Parent := Form;
     DefaultFont := DefaultButtonFont;
     UseSkinFont := Self.UseSkinFont;
     if (CtrlSkinData <> nil) and (CtrlSkinData.ResourceStrData <> nil)
     then
       Caption := CtrlSkinData.ResourceStrData.GetResStr('MSG_BTN_OK')
     else
       Caption := SP_MSG_BTN_OK;
     ModalResult := mrOk;
     Default := True;
     SetBounds(5, ButtonTop, ButtonWidth, ButtonHeight);
     DefaultHeight := ButtonHeight;
     SkinDataName := FButtonSkinDataName;
     SkinData := CtrlSkinData;
   end;

  CancelButton := TspSkinButton.Create(Form);
  with CancelButton do
  begin
    Parent := Form;
    DefaultFont := DefaultButtonFont;
    UseSkinFont := Self.UseSkinFont;
    if (CtrlSkinData <> nil) and (CtrlSkinData.ResourceStrData <> nil)
    then
      Caption := CtrlSkinData.ResourceStrData.GetResStr('MSG_BTN_CANCEL')
    else
      Caption := SP_MSG_BTN_CANCEL;
    ModalResult := mrCancel;
    Cancel := True;
    SetBounds(90, ButtonTop, ButtonWidth,
              ButtonHeight);
    DefaultHeight := ButtonHeight;
    SkinDataName := FButtonSkinDataName;
    SkinData := CtrlSkinData;
  end;

  AddCustomColorButton := TspSkinButton.Create(Form);
  with AddCustomColorButton do
   begin
     Parent := Form;
     DefaultFont := DefaultButtonFont;
     UseSkinFont := Self.UseSkinFont;
     if (CtrlSkinData <> nil) and (CtrlSkinData.ResourceStrData <> nil)
     then
       Caption := CtrlSkinData.ResourceStrData.GetResStr('ADDCUSTOMCOLORBUTTON_CAP')
     else
       Caption := SP_ADDCUSTOMCOLORBUTTON_CAP;
     SetBounds(PalettePSPPanel.Left, ButtonTop, PalettePSPPanel.Width, ButtonHeight);
     DefaultHeight := ButtonHeight;
     SkinDataName := FButtonSkinDataName;
     SkinData := CtrlSkinData;
     OnClick := AddCustomColorButtonClick;
   end;

  Form.ClientHeight := AddCustomColorButton.Top + AddCustomColorButton.Height + 10;
  InitPSPPalette;

  ColorViewer.ColorValue := Color;
  ColorGrid.ColorValue := Color;
  ColorToR_G_B(Color, R, G, B);


  REdit.Value := R;
  GEdit.Value := G;
  BEdit.Value := B;

    if Form.ShowModal = mrOk
    then
      begin
        Color := ColorViewer.ColorValue;
        for I := 1 to 12 do
          Self.CustomColorValues[I] := CustomColorGrid.CustomColorValues[I];
        CustomColorValuesCount := CustomColorGrid.FColorsCount;  
        Result := True;
      end
    else
      Result := False;

  finally
    Form.Free;
  end;
end;

procedure TspSkinColorDialog.CalcAngle360(var Angle: Double);
begin
  while (Angle < 0) do Angle := Angle + 360;
  while (Angle >= 360) do Angle:=Angle - 360;
end;

function TspSkinColorDialog.CalcAngle3Points(X1, Y1, Xc, Yc, X2, Y2: Double): Double;
var
  Angle1, Angle2, Angle: Double;
begin
  Angle1 := CalcAnglePoints(Xc, Yc, X1, Y1);
  Angle2 := CalcAnglePoints(Xc, Yc, X2, Y2);
  Angle := Angle2-Angle1;
  CalcAngle360(Angle);
  CalcAngle3Points := Angle;
end;

procedure TspSkinColorDialog.CalcRotationPoint(Xc, Yc, Angle, X1, Y1: Double; var X2,Y2: Double);
var
  Angle0: Double;
  Distance: Double;
begin
  Angle0 := CalcAnglePoints(Xc, Yc, X1, Y1);
  Distance := CalcDistancePoints(Xc, Yc, X1, Y1);
  CalcPointSurEllipse(Xc, Yc, Distance, Distance, Angle0 + Angle, X2, Y2);
end;

procedure TspSkinColorDialog.CalcPointSurEllipse(Xc, Yc, RayonX, RayonY, Angle: Double;
  var X, Y: Double);
var
  Angle1, AngleA: Double;
  A, B: Double;
begin
  CalcAngle360(Angle);
  Angle1 := 90 - Angle;
  A := Cos(Angle1 * CalcRadian) * RayonX;
  B := Sin(Angle1 * CalcRadian) * RayonY;
  if (Abs(B) < CalcEpsilon)
  then
    if (Abs(Angle - 90) < 1E-7)
    then
      AngleA := 90
    else
      AngleA := 270
  else
  begin
    AngleA := CalcArcTan(A/B);
    if (Angle < 90)
    then
    else
      if (Angle < 270)
      then
        AngleA := AngleA + 180
      else
        AngleA := AngleA + 0;
  end;
  Y := Yc + Sin(AngleA * CalcRadian) * RayonY;
  X := Xc + Cos(AngleA * CalcRadian) * RayonX;
end;

function TspSkinColorDialog.CalcArcTan(TanAngle: Double): Double;
begin
  CalcArcTan := Arctan(TanAngle) / CalcRadian;
end;

function TspSkinColorDialog.CalcAnglePoints(X1, Y1, X2, Y2: Double): Double;
var
  Distance, CosAngle, Angle: Double;
begin
  Distance := CalcDistancePoints(X1, Y1, X2, Y2);
  if (Abs(Distance) < CalcEpsilon)
  then
    Angle := 0
  else
  begin
    CosAngle := Abs(X1 - X2) / Distance;
    Angle := CalcArcCosRadians(CosAngle);
    if (Abs(Y1 - Y2) >= CalcEpsilon) and (Y2 < Y1) then Angle := -Angle;
    if (Abs(X1-X2) >= CalcEpsilon) and (X2 < X1) then Angle := Pi-Angle;
    if (Abs(Angle) < CalcEpsilon) then Angle:=0;
    if (Angle < 0) then Angle := Angle + 2 * Pi;
    Angle := Angle / CalcRadian;
  end;
  CalcAnglePoints := Angle;
end;

function TspSkinColorDialog.CalcArcCosRadians(CosAngle: Double): Double;
var
  Angle: Double;
begin
  Angle := Pi/2 - CalcArcSinRadians(CosAngle);
  CalcArcCosRadians := Angle;
end;

function TspSkinColorDialog.CalcArcSinRadians(SinAngle: Double): Double;
var
  Diviseur, Angle: Double;
begin
  Diviseur := Sqrt(1 - Sqr(SinAngle));
  if (Abs(Diviseur) < CalcEpsilon)
  then
    if (SinAngle > 0)
    then
      Angle := Pi/2
    else
      Angle := -Pi/2
  else
    Angle := ArcTan(SinAngle / Diviseur);
  CalcArcSinRadians := Angle;
end;

function TspSkinColorDialog.CalcDistancePoints(X1, Y1, X2, Y2: Double): Double;
begin
  CalcDistancePoints := Sqrt(Sqr(Y2 - Y1) + Sqr(X2 - X1));
end;

procedure TspSkinColorDialog.InitPSPPalette;
var
  GCircle, PCircle, Disque: HRGN;
  PLigneCircle: pointer;
  I, J : Integer;
  C_X, C_Y: Integer;
  Col: TPSPColor;
  Col2: THSL;
  Val: THSL;
  TabCol: array[0..359]of TRGB;
  Angle: Integer;
  Buffer: TBitMap;
begin

  Col := TPSPColor.Create;

  GCircle := CreateEllipticRgn(PalettePSPCoord.Left, PalettePSPCoord.Top,
    PalettePSPCoord.Right, PalettePSPCoord.Bottom);
  PCircle := CreateEllipticRgn((PalettePSPCoord.Left + 20),
    (PalettePSPCoord.Top + 20), (PalettePSPCoord.Right - 20), (PalettePSPCoord.Bottom - 20));

  Disque := CreateRectRgn(0, 0, 2, 2);
  CombineRgn(Disque, GCircle, PCircle, RGN_DIFF);

  Val.S := 1;
  Val.L := 0.47;
  for I := 0 to 359 do
  begin
    Val.H := I/359;
    Col.HSL := Val;
    TabCol[I] := Col.RGB;
  end;

  C_X := PalettePSPCoord.Left + 98;
  C_Y := PalettePSPCoord.Left + 98;

  Val.S := 0.93;
  Val.L := 0.47;

  // Draw background
  if (FCtrlFSD <> nil) and not FCtrlFSD.Empty and
     (FCtrlFSD.GetControlIndex('panel') <> -1)
  then
    begin
       Buffer := TBitMap.Create;
       Buffer.Width := PalettePSPPanel.Width;
       Buffer.Height := PalettePSPPanel.Height;
       GetParentImage(PalettePSPPanel, Buffer.Canvas);
       PalettePSP.Canvas.Draw(0, 0, Buffer);
       Buffer.Free;
     end
  else
    begin
      PalettePSP.Canvas.Pen.Color := ColorToRGB(clBtnFace);
      PalettePSP.Canvas.Brush.Color := ColorToRGB(clBtnFace);
      Rectangle(PalettePSP.Canvas.Handle, 0, 0, PalettePSP.Width, PalettePSP.Height);
    end;
  //

  for J := 0 to PalettePSPCoord.Bottom - 1 do
  begin
    PLigneCircle := PalettePSP.Picture.Bitmap.ScanLine[PalettePSPCoord.Top+J];
    for I := 0 to PalettePSPCoord.Bottom - 1 do
      if PtInRegion(Disque,PalettePSPCoord.Left+I,PalettePSPCoord.Top+J) then
      begin
        Angle := Round(CalcAngle3Points(C_X, 0, C_X, C_Y, I, J));
        if Angle = 360 then Angle := 0;
        Angle := 359 - Angle;
        TLineB(PLigneCircle)[(PosCircle+I)*4 + 0] := TabCol[Angle].B;
        TLineB(PLigneCircle)[(PosCircle+I)*4 + 1] := TabCol[Angle].G;
        TLineB(PLigneCircle)[(PosCircle+I)*4 + 2] := TabCol[Angle].R;

      end;
  end;

  Col.Assign(PSPColor);
  Col2 := Col.HSL;

  for J :=RectPSP.Top to RectPSP.Bottom do
  begin
    PLigneCircle := PalettePSP.Picture.Bitmap.ScanLine[J];
    Col2.L := (J-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top);
    for I := RectPSP.Left to (RectPSP.Right) do
      begin
        Col2.S := (I-RectPSP.Left)/(RectPSP.Right-RectPSP.Left);
        Col.HSL := Col2;
        TLineB(PLigneCircle)[(I+PosCar)*4    ] := Col.RGB.B;
        TLineB(PLigneCircle)[(I+PosCar)*4 + 1] := Col.RGB.G;
        TLineB(PLigneCircle)[(I+PosCar)*4 + 2] := Col.RGB.R;
      end;
  end;
  PalettePSP.Canvas.Pen.Color := $FFFFFF;
  PalettePSP.Canvas.Pen.Mode := pmXor;
  PalettePSP.Canvas.Brush.Style := bsClear;
  DrawCursor;
  PalettePSP.Picture.Bitmap.modified := true;
  Col.Free;
end;

procedure TspSkinColorDialog.DrawPSPPalette;
  procedure DrawRect;
  var
    PLigneCircle : pointer;
    I, J : Integer;
    Col : TPSPColor;
    Col2 : THSL;
  begin
    Col := TPSPColor.Create;
    Col.Assign(PSPColor);
    Col2 := Col.HSL;
    for J :=RectPSP.Top to RectPSP.Bottom do
    begin
      PLigneCircle := PalettePSP.Picture.Bitmap.ScanLine[J];
      Col2.L := (J-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top);
      for I := RectPSP.Left to (RectPSP.Right) do
        begin
          Col2.S := (I-RectPSP.Left)/(RectPSP.Right-RectPSP.Left);
          Col.HSL := Col2;
          TLineB(PLigneCircle)[(I+PosCar)*4    ] := Col.RGB.B;
          TLineB(PLigneCircle)[(I+PosCar)*4 + 1] := Col.RGB.G;
          TLineB(PLigneCircle)[(I+PosCar)*4 + 2] := Col.RGB.R;
        end;
    end;
    Col.free;
  end;
begin
  DrawRect;
  DrawCursor;
  PalettePSP.Picture.Bitmap.Modified := true;
end;


procedure TspSkinColorDialog.DrawCursor;
  procedure DrawCircle(X,Y,R:Integer);
  begin
    Ellipse(PalettePSP.Canvas.Handle,X - R, Y - R,X + R, Y + R);
  end;
var
  Angle: Integer;
  X,Y: Double;
  C_X,C_Y:  Integer;
begin
  X := round((PSPColor.HSL.S * (RectPSP.Right-RectPSP.Left)) + (PosCar + RectPSP.Left));
  Y := round((PSPColor.HSL.L * (RectPSP.Bottom-RectPSP.Top)) + RectPSP.Top);
  DrawCircle(Round(X), Round(Y),5);
  C_X := PosCar + RectPSP.Left + (RectPSP.Right-RectPSP.Left)div 2;
  C_Y := RectPSP.Top + (RectPSP.Bottom - RectPSP.Top)div 2;
  Angle := Round(PSPColor.HSL.H * 360);
  CalcRotationPoint(C_X, C_Y, -Angle, C_X, C_Y-((PalettePSPCoord.Bottom-20) div 2), X,Y);
  DrawCircle(Round(X),Round(Y),5);
end;

procedure TspSkinColorDialog.PalettePSPMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  GCircle, PCircle, Disque, Car: HRGN;
  HSLPSP: THSLPSP;
  C_X,C_Y: Integer;
  Angle: Integer;
begin
  GCircle := CreateEllipticRgn(PosCircle+PalettePSPCoord.Left,PalettePSPCoord.Top,PosCircle+PalettePSPCoord.Right,PalettePSPCoord.Bottom);
  PCircle := CreateEllipticRgn(PosCircle+PalettePSPCoord.Left+20,PalettePSPCoord.Top+20,PosCircle+PalettePSPCoord.Right-21,PalettePSPCoord.Bottom-21);
  Disque := CreateRectRgn(0,0,2,2);
  CombineRgn(Disque,GCircle,PCircle,RGN_DIFF);

  Car := CreateRectRgn(PosCar+RectPSP.Left,RectPSP.Top,PosCar+RectPSP.Right,RectPSP.Bottom);
  if PtInRegion(Car,X,Y)
  then
    ClickImg := czpspPCar
  else
  if PtInRegion(Disque,X,Y)
  then
    ClickImg := czpspPCircle
  else
    ClickImg := czpspPnone;
  if mbLeft = Button then
  case ClickImg of
    czpspPCircle :
    begin
      C_X := PosCar+RectPSP.Left+(RectPSP.Right-RectPSP.Left)div 2;
      C_Y := RectPSP.Top+(RectPSP.Bottom-RectPSP.Top)div 2;;
      Angle := Round(CalcAngle3Points(C_X, 0, C_X, C_Y, X, Y));
      if Angle = 360 then Angle := 0;
      Angle := 359 - Angle;
      HSLPSP := PSPColor.HSLPSP;
      HSLPSP.H := Round(255 * (Angle / 359));
      if HSLPSP.H <> PSPColor.HSLPSP.H
      then
        begin
          DrawCursor;
          PSPColor.HSLPSP := HSLPSP;
          ChangeEdits;
          DrawPSPPalette;
        end;
    end;
    czpspPCar :
    begin
      C_X := X;
      C_Y := Y;
      if C_X<PosCar+RectPSP.Left
      then
        C_X:= PosCar+RectPSP.Left
      else
      if C_X>PosCar+RectPSP.Right
      then
        C_X:= PosCar+RectPSP.Right;

      if C_Y<RectPSP.Top
      then
        C_Y:= RectPSP.Top
      else
      if C_Y>RectPSP.Bottom
      then
        C_Y:= RectPSP.Bottom;

      HSLPSP := PSPColor.HSLPSP;
      HSLPSP.S := Round(255 * ((C_X - (PosCar+RectPSP.Left)) / (RectPSP.Right-RectPSP.Left)));
      HSLPSP.L := Round(255 * ((C_Y - RectPSP.Top)/(RectPSP.Bottom - RectPSP.Top)));
      DrawCursor;
      PSPColor.HSLPSP := HSLPSP;
      ChangeEdits;
      DrawCursor;
      PalettePSP.Repaint;
    end;
  end;
   
end;

procedure TspSkinColorDialog.PalettePSPMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  HSLPSP : THSLPSP;
  C_X,C_Y : Integer;
  Angle : Integer;
begin
  if ssLeft in Shift then
  case ClickImg of
    czpspPCircle:
    begin
      C_X := PosCar + RectPSP.Left + (RectPSP.Right - RectPSP.Left)div 2;
      C_Y := RectPSP.Top + (RectPSP.Bottom - RectPSP.Top) div 2;
      Angle := Round(CalcAngle3Points(C_X, 0, C_X, C_Y, X, Y));
      if Angle = 360 then Angle := 0;
      Angle := 359 - Angle;
      HSLPSP := PSPColor.HSLPSP;
      HSLPSP.H := Round(255*(Angle/359));
      if HSLPSP.H <> PSPColor.HSLPSP.H
      then
        begin
          DrawCursor;
          PSPColor.HSLPSP := HSLPSP;
          ChangeEdits;
          DrawPSPPalette;
        end;
    end;
    czpspPCar :
    begin
      C_X := X;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -