FCanvas.Brush.Color:= FButtonColor;
FCanvas.FillRect(RC);
InflateRect(RC, 1, 1);
ifIsFocused then begin
RC:= ClientRect;
InflateRect(RC, -1, -1);
end;
ifIsDown thenOffsetRect(RC, 1, 1);
FCanvas.Font:= Self.Font;
DrawButtonText(Caption, RC, State, 0);
ifIsFocused andIsDefault then begin
RC:= ClientRect;
InflateRect(RC, -4, -4);
FCanvas.Pen.Color:= clWindowFrame;
Windows.DrawFocusRect(FCanvas.Handle, RC);
end;
FCanvas.Handle:= 0;
end;
procedureTColorBtn.CalcuateTextPosition( constCaption: string; varTRC: TRect; BiDiFlags: Integer);
var
TB: TRect;
TS, TP: TPoint;
begin
withFCanvas do begin
TB:= Rect(0, 0, TRC.Right + TRC.Left, TRC.Top + TRC.Bottom);
DrawText(Handle, PChar(Caption), Length(Caption), TB, DT_CALCRECT orBiDiFlags);
TS := Point(TB.Right - TB.Left, TB.Bottom - TB.Top);
TP.X := ((TRC.Right - TRC.Left) - TS.X + 1) div2;
TP.Y := ((TRC.Bottom - TRC.Top) - TS.Y + 1) div2;
OffsetRect(TB, TP.X + TRC.Left, TP.Y + TRC.Top);
TRC:= TB;
end;
end;
procedureTColorBtn.DrawButtonText( constCaption: string; TRC: TRect; State: TButtonState; BiDiFlags: Integer);
begin
withFCanvas do begin
CalcuateTextPosition(Caption, TRC, BiDiFlags);
Brush.Style:= bsClear;
ifState = bsDisabled then begin
OffsetRect(TRC, 1, 1);
Font.Color:= clBtnHighlight;
DrawText(Handle, PChar(Caption), Length(Caption), TRC, DT_CENTER orDT_VCENTER orBiDiFlags);
OffsetRect(TRC, -1, -1);
Font.Color:= clBtnShadow;
DrawText(Handle, PChar(Caption), Length(Caption), TRC, DT_CENTER orDT_VCENTER orBiDiFlags);
end elseDrawText(Handle, PChar(Caption), Length(Caption), TRC, DT_CENTER orDT_VCENTER orBiDiFlags);
end;
end;
procedure Register;
begin
RegisterComponents('Controls', [TColorBtn]);
end;
end.
Небольшое дополнение. Кнопку по прежнему рисует WINDOWS, а раскрашивает ее ColorBtn. Код компонента на 90% повторяет код BitBtn, ничего необычного здесь нет. Хочется повторить слова Калверта — «Пользуйтесь исходным кодом». Чаще заглядывайте в VCL – можно найти много интересного.
Обработка щелчка нескольких кнопок, используя их заголовок
…с ваших слов я понял, что вы все уже реализовали, но давайте все повторим: вы должны убедиться в том, что событие OnClick привязано к каждой кнопке калькулятора (числовые кнопки 0..9) и указывают на общий обработчик события.
В разделяемом обработчике события получите заголовок обрабатываемой кнопки следующим образом:
Edit1.Text := TButton(Sender).Caption;
…я думаю в этом случае самым разумным будет использование свойства Tag каждой кнопки:
1. назначьте уникальный Tag для каждой кнопки (например, эквивалент арабским цифрам)
2. procedureTForm1.Button1Click(Sender: TObject);
begin
if(Sender isTButton) then with(Sender asTButton) do
{используем Tag}
end;
Если вам нужен только заголовок, то есть изящный способ получить к нему доступ. Подключите общий обработчик события для всех кнопок и используйте приведение типа как показано ниже:
procedureTForm1.Edit1Click(Sender: TObject);
begin
edit1.text := (sender asTButton).caption;
end;
Приведенная ниже конструкция будет недостаточной:
sender.caption
поскольку компилятор не знает о том, имеет ли «sender» свойство caption, или нет.
Массив из CheckBox – использование разделяемого обработчика события I
Поместите несколько Checkbox в компонент TGroupBox. Во время прогона (или проектирования) назначьте общий обработчик события Click для всех checkbox'в. Чтобы в цикле обойти все «дочерние» TCheckBox'ы, можно воспользоваться свойством-массивом Controls TGroupBox (и заодно привести их к типу TCheckBox). Приблизительно так:
fori := 0 toGroupBox1.ControlCount -1 do
if (GroupBox1.Controls[i] asTCheckBox).checked then
{что-то там еще};
Вы можете получить имя sender следующим образом:
procedureTMain1.CheckBoxClick(Sender: TObject);
varwhodidit: string[63];
begin
whodidit := TComponent(sender).name;
end;
После приведения типа можно добраться и до других свойств. К примеру, очень полезным может оказаться свойство Tag. Во время создания, вы можете присвоить каждому checkbox.tag свой ID номер. А в обработчике события, читая ID, можно идентифицировать sender.
Читать дальше