How to slow down the movement - delphi

I am trying to make the TCanvas move up a little then back down. But with current code it does it so fast you can not see it. Was hopeing someone could give me the proper way to do this..
{this will give the attack amimation}
procedure TGameData.AnimateAttack(slot: Integer);
begin
if slot = 1 then
begin
fgame.slot1.Top := fgame.slot1.Top - 9;
fgame.slot1.Repaint;
fgame.slot1.Top := fgame.slot1.Top + 9;
fgame.slot1.Repaint;
end;
if slot = 2 then
begin
fgame.slot2.Top := fgame.slot2.Top - 9;
fgame.slot2.Repaint;
fgame.slot2.Top := fgame.slot2.Top + 9;
fgame.slot2.Repaint;
end;
if slot = 3 then
begin
fgame.slot3.Top := fgame.slot3.Top - 9;
fgame.slot3.Repaint;
fgame.slot3.Top := fgame.slot3.Top + 9;
fgame.slot3.Repaint;
end;
if slot = 4 then
begin
fgame.slot4.Top := fgame.slot4.Top - 9;
fgame.slot4.Repaint;
fgame.slot4.Top := fgame.slot4.Top + 9;
fgame.slot4.Repaint;
end;
if slot = 5 then
begin
fgame.slot5.Top := fgame.slot5.Top - 9;
fgame.slot5.Repaint;
fgame.slot5.Top := fgame.slot5.Top + 9;
fgame.slot5.Repaint;
end;
if slot = 6 then
begin
fgame.slot6.Top := fgame.slot6.Top - 9;
fgame.slot6.Repaint;
fgame.slot6.Top := fgame.slot6.Top + 9;
fgame.slot6.Repaint;
end;
end;

Store the current animation frame number and use a timer to do the animation. Like this:
FFrameNumber := 0;
FTimer : = TTimer.Create(Self);
FTimer.Interval := Round (1.0 / FrameRate);
FTimer.OnTimer := AnimationHandler;
...
FFrameNumber := 0;
FTimer.Enabled := True; // start the animation
...
procedure AnimationHandler(Sender : TObject)
begin
FTimer.Enabled := False;
case FFrameNumber of
0 : // set the canvas position
1 : // set the canvas position
2 : // set the canvas position
...
end;
Inc(FFrameNumber); // next frame
if (FFrameNumber < FrameCount) then
FTimer.Enabled := True;
end;

Related

How to handle realign of components in runtime after screen resize delphi

I searched a lot in google to get a clearer info on how I could solve my current issue, but I got scalability of components as the best answer, that's... not yet my issue.
So, long story short: I want to realign components on my form after the user resizes the window, the form is populated dinamically from a SQL query, this is the constructor code:
procedure TForm2.MakeWindow;
var
dummyMaskedit, dummyEdit: TEdit;
dummyMemo: TMemo;
dummyCombobox: TComboBox;
dummyLabel: TLabel;
dummyLBox: TListBox;
dummybutton: TButton;
i, f: integer;
buffer, workarea: double;
begin
FDQDB.Close;
FDQDB.Open('SELECT * FROM Defs WHERE active = 1');
i := 0;
f := 1;
buffer := Layout1.Width;
workarea := Layout1.Width;
SetLength(aMasks, 0);
while not FDQDB.Eof do
begin
case AnsiIndexStr(FDQDB.FieldByName('comptype').AsString,
['tedit', 'tcombobox', 'tmaskedit', 'tlistbox']) of
0: // TEdit
begin
dummyEdit := TEdit.Create(self);
dummyEdit.Parent := Form2.Layout1;
dummyEdit.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyEdit.Width >= 0 then
begin
buffer := buffer - dummyEdit.Width - 8;
dummyEdit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyEdit.Position.X := workarea - buffer - dummyEdit.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyEdit.Width - 8;
dummyEdit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyEdit.Position.X := workarea - buffer - dummyEdit.Width + 5;
end;
dummyEdit.Name := 'field' + IntToStr(f);
inc(f);
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyEdit.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyEdit.Position.Y - 17;
Position.X := dummyEdit.Position.X;
end;
end;
1: // TComboBox
begin
dummyCombobox := TComboBox.Create(self);
dummyCombobox.Parent := Form2.Layout1;
dummyCombobox.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyCombobox.Width >= 0 then
begin
buffer := buffer - dummyCombobox.Width - 8;
dummyCombobox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyCombobox.Position.X := workarea - buffer -
dummyCombobox.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyCombobox.Width - 8;
dummyCombobox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyCombobox.Position.X := workarea - buffer -
dummyCombobox.Width + 5;
end;
dummyCombobox.Name := 'field' + IntToStr(f);
dummyCombobox.Items.Delimiter := '|';
dummyCombobox.Items.StrictDelimiter := true;
dummyCombobox.Items.DelimitedText :=
AnsiUpperCase(FDQDB.FieldByName('combovalue').AsString);
inc(f);
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyCombobox.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyCombobox.Position.Y - 17;
Position.X := dummyCombobox.Position.X;
end;
end;
2: // TMaskEdit
begin
dummyMaskedit := TEdit.Create(self);
dummyMaskedit.Parent := Form2.Layout1;
dummyMaskedit.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyMaskedit.Width >= 0 then
begin
buffer := buffer - dummyMaskedit.Width - 8;
dummyMaskedit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyMaskedit.Position.X := workarea - buffer -
dummyMaskedit.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyMaskedit.Width - 8;
dummyMaskedit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyMaskedit.Position.X := workarea - buffer -
dummyMaskedit.Width + 5;
end;
dummyMaskedit.Name := 'field' + IntToStr(f);
inc(f);
SetLength(aMasks, length(aMasks) + 1);
Masks.field := dummyMaskedit.Name;
Masks.mask := FDQDB.FieldByName('mask').AsString;
aMasks[length(aMasks) - 1] := Masks;
dummyMaskedit.OnExit := MaskTextExit;
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyMaskedit.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyMaskedit.Position.Y - 17;
Position.X := dummyMaskedit.Position.X;
end;
end;
3: // TListBox
begin
dummyLBox := TListBox.Create(self);
dummyLBox.Parent := Form2.Layout1;
dummyLBox.Width := FDQDB.FieldByName('size').AsInteger;
inc(i);
buffer := workarea;
if buffer - dummyLBox.Width >= 0 then
begin
buffer := buffer - dummyLBox.Width - 8;
dummyLBox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyLBox.Position.X := workarea - buffer - dummyLBox.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyLBox.Width - 8;
dummyLBox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyLBox.Position.X := workarea - buffer - dummyLBox.Width + 5;
end;
dummyLBox.Name := 'field' + IntToStr(f);
inc(f);
SetLength(aMasks, length(aMasks) + 1);
Masks.field := dummyLBox.Name;
Masks.mask := FDQDB.FieldByName('mask').AsString;
aMasks[length(aMasks) - 1] := Masks;
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyLBox.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyLBox.Position.Y - 17;
Position.X := dummyLBox.Position.X;
end;
dummybutton := TButton.Create(self);
with dummybutton do
begin
Parent := dummyLBox.Parent;
Text := '+';
Width := 20;
Position.X := dummyLBox.Width + dummyLBox.Position.X + 3;
Position.Y := dummyLBox.Position.Y;
Name := 'ba' + dummyLBox.Name;
OnClick := ButtonsAddClick;
end;
dummybutton := TButton.Create(self);
with dummybutton do
begin
Parent := dummyLBox.Parent;
Text := '-';
Width := 20;
Position.X := dummyLBox.Width + dummyLBox.Position.X + 3;
Position.Y := dummyLBox.Position.Y + 28;
Name := 'br' + dummyLBox.Name;
OnClick := ButtonsRemClick;
end;
end;
end;
FDQDB.Next;
end;
FDQDB.Close;
end;
That works nice and pretty on the windowed state of the application, this code is applied to the onCreate event of the form:
procedure TForm2.FormCreate(Sender: TObject);
begin
FDCDB.Params.Database := ExtractFilePath(ParamStr(0)) + 'window.db';
MakeWindow;
end;
The first form, main form of the application, is the one that summons the new form that has the components built in runtime:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
end;
The second form has a TLayout, just like the first form. Then, when I create the form I bring the TLayout of the second form to the first. So far so good, it works when the application is launched in windowed mode.
But when I put form1 in fullscreen mode, then click the Button that creates the form2, the components stays on the same position as in windowed mode. I've tried changing the workarea variable to these:
Screen.width, //components behave as the application were in fullscreen the whole time
Screen.WorkAreaWidth, //same as screen.width
(Layout1.Parent as TLayout).Width, //invalid typecast
(Layout1.GetParentComponent as TLayout).Width //invalid typecast
None of them worked.
I wanna be able to adjust the position of the components on the screen based on its visual width, so if the user resizes the window before creating the new form, the components gets aligned properly.
Anyone knows a solution for that? Thanks in advance
But when I put form1 in fullscreen mode, then click the Button that
creates the form2, the components stays on the same position as in
windowed mode.
At TForm1.SpeedButton1Click() you call Application.CreateForm(TForm2, Form2); which triggers TForm2.FormCreate(Sender: TObject); which calls MakeWindow. At this point Form2 knows only about the design time size.
After MakeWindow is done, the TForm1.SpeedButton1Click() continues:
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
but these do not anymore affect the layout of the controls.
You need to set Form2.Layout1.Width before you call MakeWindow, for example:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
MakeWindow; // remove it from TForm2.FormCreate()
end;
The form has ClientWidth and ClientHeight properties which work well in OnResize to dynamically size a control based on the area available. The OnResize fires before the form is made visible. For example to have a Memo1 with a 100 border around it:
procedure TForm1.FormResize(Sender: TObject);
begin
memo1.Position.X := 100; // Only needs to be done once but here so all code is in one spot
memo1.Position.Y := 100;
memo1.Width := form1.ClientWidth - 200;
memo1.Height := form1.ClientHeight - 200;
end;

FASTREPORT Adding objects dynamically in report script

I try to add TLineView objects to a report.
The number of lines is depending on a certain number, retrieved by the reports dataset.
I have put my code into the scripts initialization part and in a very experimental test version it looks like this:
var nol, i: integer;
child, newChild: TfrxChild;
noteLine1, noteLine2: TfrxLineView;
page: TfrxPage;
begin
page := ReportName;
nol := <DS_MAIN."VOLUME"> /2;
nol := nol + <DS_MAIN."VOLUME"> mod 2;
child3.child := TfrxChild.create(nil);
newchild := child3.child;
newChild.Visible := true;
noteLine1 := TfrxLineView.create(newChild);
noteLine1.name := 'nl1000';
noteLine1.Top := 0.73;
noteLine1.Width := 7.5;
noteLine1.Left := 3;
noteLine1.Visible := true;
noteLine1.Parent.Objects.Remove(noteLine1);
noteLine1.Parent.Objects.Add(noteLine1);
// newChild.Objects.Add(noteLine1);
noteLine2 := TfrxLineView.create(newChild);
noteLine2.name := 'nl1001';
noteLine2.Top := 0.73;
noteLine2.Width := 7.5;
noteLine2.Left := 11.2;
newChild.Objects.Add(noteLine2);
noteLine2.Visible := true;
for i := 1 to nol do begin
Child := TfrxChild.create(nil);
NewChild.child := Child;
newChild := child;
end;
end.
Instead of getting two lines side by side, with a gap between them, I get only a single short line of a length of around 3-4 mm.
The above code is just a snap of my trial-and-error session.
Hope now that there could be anyone to give me some clues.
If I understand your question correctly, you need to consider at least the following:
With your for loop you create bands, not lines. You may try to change the logic and create objects (memos, lines, shapes) with bands as owners.
The objects’ coordinates and sizes are set in pixels, so you need an additional calculation.
From documentation:
Objects’ coordinates and sizes are set in pixels. Since the «Left,»
«Top,» «Width,» and «Height» properties of all objects have the
«Extended» type, you can point out non-integer values. The following
constants are defined for converting pixels into centimeters and
inches:
fr01cm = 3.77953;
fr1cm = 37.7953;
fr01in = 9.6;
fr1in = 96;
The following working example generates five TfrxLineView objects. Just put an empty report on your form and add report title band:
procedure TfrmMain.btnPreviewClick(Sender: TObject);
var
nol, i: integer;
left: Extended;
band: TfrxReportTitle;
line: TfrxLineView;
begin
// Band
band := (report.Report.FindObject('ReportBand') as TfrxReportTitle);
// Lines generation
left := 3;
nol := 5;
for i := 1 to nol do begin
line := TfrxLineView.Create(band);
line.CreateUniqueName;
line.Top := 0.73;
line.Width := fr1cm * 2;
line.Left := left;
left := left + line.Width + 30;
end;
// Report preview
report.ShowReport(False);
end;
This is my final solution:
procedure Child8OnBeforePrint(Sender: TfrxComponent);
var nol, i: integer;
left1, left2: extended;
child, newChild: TfrxChild;
noteLine1, noteLine2, line: TfrxLineView;
page: TfrxPage;
band: TfrxChild;
begin
nol := <DS_MAIN."VOLUME"> /2;
nol := nol + <DS_MAIN."VOLUME"> mod 2;
band := TfrxChild(TRP_ORDER_NOTE.FindObject('Child9'));
// Lines generation
left1 := 3*fr1cm;
left2 := 11.2*fr1cm;
for i := 1 to nol do begin
line := TfrxLineView.Create(band);
line.Name := 'noteLine'+intToStr(1+2*(i-1+trunc(random*1000000))); //Panic solution
line.Top := fr1cm*(0.73 + (i-1)*0.75);
line.Width := 7.5*fr1cm;
line.Left := left1;
if (<DS_MAIN."VOLUME"> mod 2 > 0 ) and (i = nol) then
exit
else
begin
line := TfrxLineView.Create(band);
line.Name := 'noteLine'+intToStr(2*i+trunc(random*1000000));
line.Top := fr1cm*(0.73 + (i-1)*0.75);
line.Width := 7.5*fr1cm;
line.Left := left2;
end;
end;
end;

creating a pause menu in delphi

Background: I have created a maze game that is playable, however when the maze gets bigger there are more chances to go wrong and takes ages to reach the start of the maze again, I've been told that's really annoying.
Question: I want to create a pause game function that when the user presses the button key a menu pops up that allows the user to be able to either return to main menu or restart the maze.
I have very little knowledge on where to start this in the code as I don't want to mess up anything that has already been added.
I've added the draw maze //creates the maze,
initialise visited and walk // removes the walls of the maze,
Form key down//moves the player
and Timer//collision detection procedures below.
hopefully someone can help?
Many Thanks.
`procedure TfrmMazeDesign.draw_maze(square_size: integer);
var
row, col : integer;
begin
// setup default walls as "WWWW" wall on all four sides.
SetLength(Shapes,height+3, width+3, 2 ) ;
for row := 1 to height do
begin
for col := 1 to width+2 do
begin
Shapes[row,col,0]:= TShape.Create(Self);
Shapes[row,col,0].Parent := Self;
with Shapes[row,col,0] do
begin
Width := 5;
Height := square_size;
Left := 100+ ((col-1) * square_size);
Top := 50+ ((row-1) * square_size);
Brush.Color := RGB(255, 255,25);
Shape := stRectangle;
end;
end;
end;
for row := 1 to height+1 do
begin
for col := 1 to width+1 do
begin
Shapes[row,col,1]:= TShape.Create(Self);
Shapes[row,col,1].Parent := Self;
with Shapes[row,col,1] do
begin
Width := square_size;
Height := 5;
Left := 100+ ((col-1) * square_size);
Top := 50+ ((row-1) * square_size);
Brush.Color := RGB(255, 255,25);
Shape := stRectangle;
end;
end;
end;
end;
procedure TfrmMazeDesign.initialise_visited(var visited: Tvisited);
var
row, col: integer;
begin
for row := 0 to height+2 do
for col := 0 to width+2 do
if (col = 0) or (row = 0) or (row = height+1) or (col= width+2) then
visited[row,col] := True
else
visited[row,col] := False;
end;
procedure TFrmMazeDesign.walk(visited: Tvisited; x: integer; y:integer);
var
xx,yy, counter, ran_direction: integer;
direction: Tstringlist; // 1= Up, 2= right, 3 = down, 4 = left
text: string;
begin
visited[x,y] := True;
direction := TStringlist.Create;
direction.Add('1');
direction.Add('2');
direction.Add('3');
direction.Add('4');
for counter := direction.Count - 1 downto 0 do
direction.Exchange(counter, Random(counter+1));
for counter := 0 to direction.Count-1 do
begin
ran_direction := StrtoInt(direction[counter]);
if ran_direction= 1 then
begin
xx := x-1;
yy := y
end;
if ran_direction = 2 then
begin
xx := x+1;
yy := y
end;
if ran_direction = 3 then
begin
xx := x;
yy := y-1
end;
if ran_direction= 4 then
begin
xx := x;
yy := y+1
end;
if visited[xx,yy] = False then
begin
if xx = x then
shapes[x,Max(yy,y),0].visible := False;
if yy = y then
shapes[Max(xx,x),y,1].visible := False;
walk (visited, xx,yy)
end;
end;
end;
procedure TfrmMazeDesign.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_UP:
direction := 1;
VK_DOWN:
direction := 2;
VK_LEFT:
direction := 3;
VK_RIGHT:
direction := 4;
end;
end;
procedure TfrmMazeDesign.FormOpen(Sender: TObject);
var
block_height: integer;
xx,yy: integer;
visited: Tvisited;
monster, monster2: TMonster;
Shape_height : integer;
Shape_Width : integer;
imgfinish_height : integer;
maze_width : integer;
begin
width := frmdifficulty.ScrollBar1.Position;
height := frmdifficulty.ScrollBar1.Position;
maze_width := 650;
block_height := maze_width div width;
Shape_height := round( block_height * 0.5);
imgfinish_height := round(block_height * 0.5);
draw_maze(block_height);
SetLength(visited, height+10, width+10) ;
initialise_visited(visited);
walk(visited,3,3);
ShpUser.height := Shape_height;
ShpUser.Width := Shape_height;
imgfinish.width := Shape_height;
imgfinish.height := shape_height;
ShpUser.Shape := UShapeEditor.frmShape.shpShape.Shape;
ShpUser.Brush.color := UShapeEditor.frmShape.shpShape.Brush.color;
FDateTimeTo := StrToDateTime(FormatDateTime('dd' + FormatSettings.DateSeparator + 'mm' +
FormatSettings.DateSeparator + 'yyyy', Now)); Incsecond(time,120);
Timer1.Enabled := True;
monster := TMonster.Create(Self);
monster.Parent := Self;
monster.SetSizes(width, height, shape_height, 55+ maze_width + 10,665);
monster.start;
monster2 := TMonster.Create(Self);
monster2.Parent := Self;
monster2.SetSizes(width, height, shape_height, 50+ maze_width + 10,565);
monster2.start;
end;
procedure TfrmMazeDesign.Timer1Timer(Sender: TObject);
var IntersectionRect: TRect;
collision, test_collision : boolean;
up : boolean;
right : boolean;
max_width, max_height : integer;
xx, yy : integer ;
aRect1: TRect;
buttonSelected : Integer;
collisionend: boolean;
frmMazeDesign: TfrmMazeDesign;
row, col, hoz_vert : integer;
begin
hoz_vert := 0;
xx := 0;
yy := 0;
case direction of
1:begin //Up
yy := -3;
end;
2: begin //down
yy := + 3;
end;
3: begin //left
xx := -3;
end;
4: begin //right
xx := + 3;
end;
end;
repeat
if hoz_Vert = 0 then begin
max_width := width +3;
max_height := Height+1;
end else begin
max_width := width+2;
max_height := Height+2;
end;
row := 1;
repeat
col := 1;
repeat
aRect1 := Rect(ShpUser.Left+xx, ShpUser.Top+yy, ShpUser.Left+ShpUser.width+xx, ShpUser.top+ ShpUser.Height+yy);
if Shapes[row,col,hoz_vert].visible = True then
collision := IntersectRect(IntersectionRect, aRect1, Shapes[row,col,hoz_vert].BoundsRect) ;
col := col + 1;
until (collision) or (col = max_width);
row := row + 1 ;
until (collision) or (row = max_height);
hoz_vert := hoz_vert +1;
until (collision) or (hoz_vert = 2);
if (collision = False) and (direction <> 0) then begin
ShpUser.Top := ShpUser.Top + yy;
ShpUser.Left := ShpUser.Left + xx;
end;
if IntersectRect(IntersectionRect, imgfinish.BoundsRect, Shpuser.BoundsRect) then
begin
Collisionend := true;
if collisionend = true then
frmfinish.Show;
direction:= 0;
end;`
This is relatively straightforward to add to your program, which is already event driven. In summary you need to do the following:
Add a Boolean flag, perhaps named Paused, set to False when the game starts.
When the user presses the pause button, set the Paused flag to True.
When the user presses the resume button, set the Paused flag to False.
In the time event handler, check the Paused flag before updating the positions. If the Paused flag is True, then simply exit from the timer event handler before doing anything else.

Create run time TTabItem , firemonkey

Seems like i need some help with a project.
I have a routine , that constructs run time multiple TabItems on to a page control in firemonkey, and i want to have a close button on the tab.
The new tab has a checkbox for the close button loading from the styler of the tabitems.
The page has a default tab, and within some button, i am adding run time the new tab items.
I have managed to apply the event for closing the default tab page, but doesn't work within the run time created tab pages. Any help would be appreciated.
This is the piece of code for the runtime tabitems
procedure TForm1.Button1Click(Sender: TObject);
var
t : TTabItem;
o : TFmxObject;
i : Integer;
c : TControl;
begin
t := TTabItem.Create(pgeControl);
t.Parent := pgeControl;
o := FindBinding('imgCloseTabPage');
if o<>nil then
begin
for i := 0 to ComponentCount - 1 do
begin
if Components[i] is TCheckBox then
begin
TCheckBox(Components[i]).OnClick := CheckBox1Click;
end;
end;
end;
if pgeControl.TabCount - 1 <= nTab then
begin
nTab := nTab + 1;
t.Index := nTab
end
else
begin
t.Index := pgeControl.TabCount - 1;
nTab := pgeControl.TabCount - 1;
end;
t.Tag := nTab;
t.Text := 'Some text...' + ' ' + IntToStr(nTab);
t.Name := 'tabPatient' + IntToStr(nTab);
t.Height := 35;
t.Width := 250;
t.Margins.Top := 0;
t.Margins.Left := 0;
t.Margins.Bottom := 0;
t.Margins.Right := 0;
t.Padding.Top := -5;
t.Padding.Left := 0;
t.Padding.Bottom := 0;
t.Padding.Right := 0;
t.TextAlign := TTextAlign.taLeading;
t.Width := (Length(t.Text) * 6 ) + 60;
t.Font.Size := 15;
t.StyleLookup := 'tabMainStyle1';
l := TLayout.Create(t);
l.Parent := t;
l.Align := TAlignLayout.alClient;
l.Margins.Top := -5;
l.Margins.Left := 5;
l.Margins.Right := 5;
l.Margins.Bottom := 5;
l.Padding.Top := 0;
l.Padding.Left := 0;
l.Padding.Bottom := 0;
l.Padding.Right := 0;
pgeControl.ActiveTab := pgeControl.Tabs[pgeControl.TabCount - 1];
end;
You shoud call FindBinding after having applyed the custom style. Currently you call this before, so it can't find the object. Additionally there was a mistake when you was looking for the object.
so put this
o := t.FindBinding('imgCloseTabPage');
if o<>nil then
begin
if o is TCheckBox then
TCheckBox(o).OnClick := CheckBox1Click;
end;
after
t.StyleLookup := 'tabMainStyle1';
and the event should assigned.

How to add buttons created at runtime into an array?

I'm sorry if the question looks stupid,but It seems I can't use my head properly in the last hours.
I have a record,
type
TMain = record
Sub:Array of TSubMain; //another record
Button:TsSpeedButton; //this is what we need!
end;
a variable
Main:Array of TMain;
and function:
procedure TFrameSkilLView.CreateButtons(MainBtns,SubMainBtns:byte;title:Array of string);
var i,t,l,w,h:word;
section:string;
begin
l := 41; t:= 57; w := 58; h := 25;
section := 'TOOLBTN_SKILLS_MAIN';
for i := 0 to MainBtns + subMainBtns - 1 do
with TsSpeedButton.Create(nil) do begin
Width := w; Height := h; Top := t; Left := l;
if(i = 0) then SkinData.SkinSection := section + '_C' else skindata.SkinSection := section;
caption := title[i];
Parent := Self;
inc(l,w+4);
if(i = MainBtns - 1) then begin
l := 52; t := 83; w := 64; h := 28;
section := 'TOOLBTN_SKILLS_SUBMAIN';
end;
end;
end;
Lets focus on the loop 'for i := 0 to MainBtns + subMainBtns - 1'.I'd like to add the button created below to the array created above named 'Main:Array of Tmain'.
It should look like this:
for i:=0 to X do
with TsSpeedButton.Create(nil) do begin
Main[i] := this; //where this is the created sSpeedButton.
Howeve,this code can't even be compiled,so I'm asking for a doable way to accomplish what I'm trying to do.
Thank you.
First off, "this" is C++, not Pascal. The Delphi version is "Self". Second, you can't refer to the with-ed object by name. You're better off not using with at all. Try something like this:
for i:=0 to X do
begin
tempButton := TsSpeedButton.Create(nil);
Main[i] := tempButton;
//whatever else
end;

Resources