Как изменить флажок на сплошной цвет и изменить цвет его границы в Delphi

Я построил элемент управления, который представляет собой интегральную схему.

введите здесь описание изображения

Каждая булавка является флажком, и я основал элемент управления на этом сообщении из @Andreas Rebrand отличный пример редактирования байта Флажок может иметь до 4 значений, которые я хотел бы представить в виде 4 разных цветов. Я также хотел бы установить границу выбранного флажка в цвет, чтобы указать, когда он выбран. Кто-нибудь может подсказать, как это можно сделать?


person John Barrat    schedule 09.05.2021    source источник


Ответы (1)


Код в связанном вопросе использует API темы для рисования флажков в собственном стиле. Это отличная идея, если вы этого хотите.

Однако в этом случае вам нужно что-то отличное от флажка в собственном стиле, поэтому, вероятно, лучше рисовать поля вручную. Тогда, конечно, вы можете дать им любое количество состояний.

Например,

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    const
      BoxCount = 8;
    type
      TBoxState = (bsRed, bsGreen, bsBlue, bsBlack);
    var
      FBoxes: array[0..BoxCount - 1] of TBoxState;
      FHotBox: Integer;
    const
      Margin = 64;
      InternalPadding = 24;
      BoxSize = 36;
      BoxColors: array[TBoxState] of TColor = ($A6A6FF, $A6FFA6, $FFA6A6, $A6A6A6);
    function GetBoxRect(AIndex: Integer): TRect;
    function GetBoxAt(const APoint: TPoint): Integer;
    procedure DrawBox(AIndex: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DrawBox(AIndex: Integer);
begin
  Canvas.Brush.Color := BoxColors[FBoxes[AIndex]];
  Canvas.Pen.Width := 4;
  if AIndex = FHotBox then
    Canvas.Pen.Color := clBlack
  else
    Canvas.Pen.Color := clWindow;
  Canvas.Rectangle(GetBoxRect(AIndex));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FHotBox := -1;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  var Idx := GetBoxAt(Point(X, Y));
  if Idx <> -1 then
  begin
    FBoxes[Idx] := TBoxState((Succ(Ord(FBoxes[Idx])) mod 4));
    DrawBox(Idx);
  end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  var LOldHotBox := FHotBox;
  FHotBox := GetBoxAt(Point(X, Y));
  if LOldHotBox <> FHotBox then
  begin
    if LOldHotBox <> -1 then
      DrawBox(LOldHotBox);
    if FHotBox <> -1 then
      DrawBox(FHotBox);
  end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  Canvas.Brush.Color := clWindow;
  Canvas.FillRect(ClientRect);
  for var i := 0 to High(FBoxes) do
    DrawBox(i);
end;

function TForm1.GetBoxAt(const APoint: TPoint): Integer;
begin
  for var i := 0 to High(FBoxes) do
    if GetBoxRect(i).Contains(APoint) then
      Exit(i);
  Result := -1;
end;

function TForm1.GetBoxRect(AIndex: Integer): TRect;
begin
  Result.Left := Margin + AIndex * (BoxSize + InternalPadding);
  Result.Top := Margin;
  Result.Width := BoxSize;
  Result.Height := BoxSize;
end;

end.

Запись экрана программы в действии

person Andreas Rejbrand    schedule 09.05.2021
comment
Да, это имеет смысл, и к этому выводу я пришел, теперь я лучше понимаю, как используются процедуры Mouse Down и Move. Еще раз спасибо за ваш оригинальный пост, он дал мне действительно сильную отправную точку. - person John Barrat; 10.05.2021
comment
Если вы используете HighFormPaint и GetBoxAt), вы также должны использовать Low вместо 0 — просто чтобы быть последовательным... - person HeartWare; 10.05.2021
comment
@HeartWare: я это учитывал, но в данном случае я по-прежнему предполагаю, что нижняя граница равна 0 в FormMouseDown. (На самом деле, я даже предполагаю, что количество состояний равно 4.) - person Andreas Rejbrand; 10.05.2021
comment
Тогда зачем использовать High ? Почему бы просто не использовать 3? :-) - person HeartWare; 11.05.2021