我想创建一个"面板组件"通过y按钮按住x(实际上不是按钮,但你明白了)。
它应该看起来像扫雷,你可以点击任何按钮,每个按钮都有相同的"全局点击"事件。但是使用发件人和按钮作为参数,例如:Sender: TObject; Button: TButton
)作为面板组件的wherin Sender和按钮面板内的按钮。
到目前为止,我对水平方向的按钮数量和垂直方向的按钮数量设置了两个属性。
property ButtonsHeight: Integer read fButtonsHeight write SetButtonsHeight;
property ButtonsWidth: Integer read fButtonsWidth write SetButtonsWidth;
procedure TMultipleDrawPanel.SetButtonsHeight(const Value: Integer);
begin
if Value < 1 then begin
raise Exception.Create('Mumarul minim de butoane este 1!');
end;
InflateButtonsHeight(fButtonsHeight, Value);
fButtonsHeight := Value;
end;
这是在一个方向上改变按钮数量的伪代码:
procedure TMultipleDrawPanel.InflateButtonsHeight(oldValue, newValue: Integer);
begin
if oldValue < newValue then begin
// free extra buttons
end else begin
// create new buttons
end;
end;
有人能指点我一些意见吗?
答案 0 :(得分:0)
这样的东西?
unit ButtonPanel;
interface
uses
System.Classes, System.SysUtils, Vcl.Controls, Vcl.StdCtrls, System.Math;
type
TCoord = record
Col: Integer;
Row: Integer;
end;
TCustomButtonPanel = class;
TButtonClickEvent = procedure(Sender: TCustomButtonPanel;
Coord: TCoord) of object;
TCustomButtonPanel = class(Vcl.Controls.TWinControl)
private
FColCount: Integer;
FOnClick: TButtonClickEvent;
FRowCount: Integer;
procedure ButtonClick(Sender: TObject);
function CoordFromIndex(Index: Integer): TCoord;
function CoordToIndex(Col, Row: Integer): Integer;
function GetButton(Col, Row: Integer): TButton; overload;
function GetButton(Index: Integer): TButton; overload;
function GetButtonCount: Integer;
procedure SetColCount(Value: Integer);
procedure SetRowCount(Value: Integer);
procedure SizeChanged;
protected
function CanResize(var NewWidth, NewHeight: Integer): Boolean; override;
procedure DoClick(Index: Integer); virtual;
procedure Resize; override;
procedure ValidateInsert(AComponent: TComponent); override;
property ButtonCount: Integer read GetButtonCount;
property Buttons[Col, Row: Integer]: TButton read GetButton;
property ColCount: Integer read FColCount write SetColCount default 5;
property OnClick: TButtonClickEvent read FOnClick write FOnClick;
property RowCount: Integer read FRowCount write SetRowCount default 5;
public
constructor Create(AOwner: TComponent); override;
end;
TButtonPanel = class(TCustomButtonPanel)
public
property ButtonCount;
property Buttons;
published
property ColCount;
property OnClick;
property RowCount;
end;
implementation
type
TButtonPanelButton = class(Vcl.StdCtrls.TButton);
resourcestring
SInvalidControlType = 'Invalid control type for ButtonPanel child';
function Round(Value, Rounder: Integer): Integer; overload;
begin
if Rounder = 0 then
Result := Value
else
Result := (Value div Rounder) * Rounder;
end;
{ TCustomButtonPanel }
procedure TCustomButtonPanel.ButtonClick(Sender: TObject);
begin
DoClick(TButton(Sender).Tag);
end;
function TCustomButtonPanel.CanResize(var NewWidth, NewHeight: Integer): Boolean;
var
EdgeSize: Integer;
begin
Result := inherited CanResize(NewWidth, NewHeight);
EdgeSize := 2 * (BorderWidth + BevelWidth);
NewWidth := Round(NewWidth - EdgeSize, FColCount) + EdgeSize;
NewHeight := Round(NewHeight - EdgeSize, FRowCount) + EdgeSize;
end;
function TCustomButtonPanel.CoordFromIndex(Index: Integer): TCoord;
begin
Result.Col := Index mod ColCount;
Result.Row := Index div ColCount;
end;
function TCustomButtonPanel.CoordToIndex(Col, Row: Integer): Integer;
begin
Result := FColCount * Row + Col;
end;
constructor TCustomButtonPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := [];
FColCount := 5;
FRowCount := 5;
SizeChanged;
end;
procedure TCustomButtonPanel.DoClick(Index: Integer);
begin
if Assigned(FOnClick) then
FOnClick(Self, CoordFromIndex(Index));
end;
function TCustomButtonPanel.GetButton(Col, Row: Integer): TButton;
begin
Result := GetButton(CoordToIndex(Col, Row));
end;
function TCustomButtonPanel.GetButton(Index: Integer): TButton;
begin
Result := TButton(Controls[Index]);
end;
function TCustomButtonPanel.GetButtonCount: Integer;
begin
Result := ControlCount;
end;
procedure TCustomButtonPanel.Resize;
var
ColWidth: Integer;
RowHeight: Integer;
Col: Integer;
Row: Integer;
begin
inherited Resize;
ColWidth := ClientWidth div FColCount;
RowHeight := ClientHeight div FRowCount;
for Col := 0 to FColCount - 1 do
for Row := 0 to FRowCount - 1 do
Buttons[Col, Row].SetBounds(Col * ColWidth, Row * RowHeight, ColWidth,
RowHeight);
end;
procedure TCustomButtonPanel.SetColCount(Value: Integer);
begin
if FColCount <> Value then
begin
FColCount := Max(1, Value);
SizeChanged;
end;
end;
procedure TCustomButtonPanel.SetRowCount(Value: Integer);
begin
if FRowCount <> Value then
begin
FRowCount := Max(1, Value);
SizeChanged;
end;
end;
procedure TCustomButtonPanel.SizeChanged;
var
I: Integer;
OldCount: Integer;
NewCount: Integer;
Button: TButton;
begin
OldCount := ButtonCount;
NewCount := FColCount * FRowCount;
for I := OldCount - 1 downto NewCount do
GetButton(I).Free;
for I := OldCount to NewCount - 1 do
begin
Button := TButtonPanelButton.Create(Self);
Button.Tag := I;
Button.OnClick := ButtonClick;
Button.Parent := Self;
end;
AdjustSize;
end;
procedure TCustomButtonPanel.ValidateInsert(AComponent: TComponent);
begin
inherited ValidateInsert(AComponent);
if not (AComponent is TButtonPanelButton) then
raise EInvalidInsert.Create(SInvalidControlType);
end;
end.
我确信上面的代码提供了大量的学习资料,思考的食物和定制的空间。简而言之:
Controls
属性以将其含义扩展到按钮。因此,控件不允许插入其他类型的控件。请参阅GetButton
,GetButtonCount
,ValidateInsert
。CanResize
。OnClick
事件,因为不会点击面板自我(它带有按钮已满)。该活动有一个额外的参数,请参阅ButtonClick
,DoClick
。CoordFromIndex
,CoordToIndex
。Tag
属性标识,请参阅创建按钮的SizeChanged
。下一步是使用虚拟方法重新设计它,从而不使用实际的TButton
控件,但是按钮只是模仿的。
玩得开心。