procedure TmainScreen.SpeedButton_newTabClick(Sender: TObject);
var
k: integer;
newtab: TTabSheet;
newlabel: TLabel;
aPic : TPicture;
// start duplicating all the components in the POS tabsheet
// toolbar in the POS tabsheet
newBevel_toolbar: TBevel;
newSpeedButton_toolbarFirst: TSpeedButton;
newSpeedButton_toolbarPrevious: TSpeedButton;
begin
k := PageControl.PageCount + 1;
// we stablish the limit of 15 POS sessions opened at a time
if k <= 15 then begin
newtab := TTabSheet.Create(PageControl);
newtab.PageControl := PageControl;
newtab.name := 'tab'+inttostr(k);
newtab.Caption := 'TPV '+inttostr(k);
//---------------------------------------
//newlabel := TLabel.Create(newtab);
//newlabel.name := 'tablabel'+inttostr(k);
//newlabel.caption := 'Test'+inttostr(k);
//newlabel.left := 20;
//newlabel.top := 20;
//newlabel.visible := true;
//newlabel.parent := newtab;
// nueva barra de herramientas
newBevel_toolbar:= TBevel.Create(newtab);
newBevel_toolbar.Left := 0;
newBevel_toolbar.Height := 30;
newBevel_toolbar.Top := 0;
newBevel_toolbar.Width := 1765;
newBevel_toolbar.Align := alTop;
newBevel_toolbar.Shape := bsBottomLine;
newBevel_toolbar.visible := true;
newBevel_toolbar.parent := newtab;
// botón 1
newSpeedButton_toolbarFirst := TSpeedButton.Create(newtab);
newSpeedButton_toolbarFirst.Left := 5;
newSpeedButton_toolbarFirst.Height := 22;
newSpeedButton_toolbarFirst.Top := 3;
newSpeedButton_toolbarFirst.Width := 23;
newSpeedButton_toolbarFirst.Flat := True;
aPic := TPicture.Create;
aPic.LoadFromFile('C:\Users\Raúl\Proyectos\img-general\toolbars\1.png');
newSpeedButton_toolbarFirst.Glyph.Assign(aPic.Bitmap);
newSpeedButton_toolbarFirst.Transparent := False;
//OnClick = SpeedButton_toolbarFirstClick
newSpeedButton_toolbarFirst.ShowCaption := False;
newSpeedButton_toolbarFirst.visible := true;
newSpeedButton_toolbarFirst.parent := newtab;
(...)
Have you tried a Component-Stream ?
[Edit]
Suggestion post an example-Program.
BTW. How Do you want to access the components of the cloned tab ?
Is the Form fixed or is it dynamically created ?
Can you put the content of the first Tab in a frame? Then you only have to generate a new tab and add a new instance of the frame, Done.
Can you put the content of the first Tab in a frame? Then you only have to generate a new tab and add a new instance of the frame, Done.
Do you mean something like this:
https://github.com/joecare99/Public/blob/master/Projects/bin/x86_64-win64/Prj_CopyComplexFrame.exe
Source:
https://github.com/joecare99/Public/tree/master/Examples/Source/CopyComplexFrame
https://github.com/joecare99/Public/tree/master/Examples/FPC Prj_CopyComplexFrame.* (https://github.com/joecare99/Public/blob/master/Examples/FPC/Prj_CopyComplexFrame.lpr)
As far as I've read, I think that's the kind of solution I need. But the TFrames doc it's SOO confusing for a newbe.My solution is done with frames, just use my source as a template ...
Please, can you provide a link to a clear & concise tutorial or maybe even a clean and simple example of exactly this? It would be very clarifying.
thanks!
As far as I've read, I think that's the kind of solution I need. But the TFrames doc it's SOO confusing for a newbe.
Please, can you provide a link to a clear & concise tutorial or maybe even a clean and simple example of exactly this? It would be very clarifying.
Do you mean something like this:
https://github.com/joecare99/Public/blob/master/Projects/bin/x86_64-win64/Prj_CopyComplexFrame.exe
Source:
https://github.com/joecare99/Public/tree/master/Examples/Source/CopyComplexFrame
https://github.com/joecare99/Public/tree/master/Examples/FPC Prj_CopyComplexFrame.* (https://github.com/joecare99/Public/blob/master/Examples/FPC/Prj_CopyComplexFrame.lpr)
Thanks for the example Joe,Sorry for the first one, If adding more than one frame you/I have to name the components, Duplicate names are not allowed,
It gives two problems:
1- The program crashes when adding more than one tab:
Duplicate name: A component named "Frame1" already exists.
ok, Abort
and the new tabsheet appears empty.
I'm trying to see where's the problem.
2- when exiting the program gives the followin error message:
Error:
Heap dumb by heaptrc unit
101838 memory blocks allocated: numbers...
101383 memory blocks freed: the same numbers...
0 unfreed memory block: 0
True heap size: 819200
True free heap: 819040
Should be: 819200
Accept.
Thanks taazz, I'm going to experiment with your code! Now I think I need a break...erm let it be for now its a bit ahead still sorry.
Ok. This is getting more complex...I think I'm going to blow a circuit in my brain. How to manage procedures and properties between the frame and the owner.where did you wrote this code? the frame? how about going on the form selecting the button inside the frame you have there and adding a new event for the buttons click (double the button for short).
procedure TFrame1.BitBtn2Click(Sender: TObject); begin // implement close active tabsheet method // Change the caption of the window (or a label or whatever) to say that // tab number x has been deleted. Form1.Caption := 'Deleting tab ' + InttoStr(PageControl1.ActivePageIndex); // delete the tabsheet PageControl1.Page[PageControl1.ActivePageIndex].Destroy; end;
This code belongs to Unit2, the frame code. It gives the obvious error that Form1 and PageControl1 have not been declared (they belong to Unit1, the Form control). What I am doing wrong?
Thank you taazz.Yes. a frame should be seen as a single entity what ever you write in there should only be about the frame it self, behavior rules etc that cavern the controls and their interaction with each other nothing more.
Actually, is the Lazarus IDE itself that places the procedure TFrame1.BitBtn2Click(Sender: TObject) inside the frame source code file, not in the Form1, when double-clicking on the designer. So I thought that's the place should be. It would be possible to achieve the same using this approach instead?
And excuse my dummy question, In this piece of code:it is a way to instruct the compiler that you do not want to execute the method and assign the results but you want to assign the method it self as a value to the event.
BitBtn2.click := @framebutton2Click;
What does the @ mean? it has something to do with @override?
And excuse my dummy question, In this piece of code:The @-operator generally gives you the address/reference of something instead of the object/variable.
BitBtn2.click := @framebutton2Click;
What does the @ mean? it has something to do with @override?
We've seen how to access a component inside the Frame1 from the code in the Form1. What if I want to access from Frame1 a component in Form1? (opposite direction)from a component point of view, you do not. a Frame might be placed inside form1, form43 or even dialog54. Frame1 code should never have the need to access anything outside it self. Form1 might want to be informed on various events in the frame1 you create those events in frame1 and implement their handler in form1 and in form45 or which ever parent you choose.
Example:In this case I would say you have write two event handlers one inside the frame1 and one inside the form1. As I said (I think I said it) in one of my previous messages you can override the events of the frame in their parent and you should be able call the inherited event. So after you have finished the code on frame1 you place it on a form you double click the button inside the frame and you write your code that accesses your status bar before or after calling the inherited method.
In Form1 I have StatusBar1.
Whenever I click in Button1 of Frame1 the caption of StatusBar1 has to change:
StatusBar1.Caption := 'Button1 has been clicked'
I have a bit of confusion about who can see who in this form-frame model. Form1.StatusBar1.Caption := whatever doesn't seem to work.
thanks!
Hi friends, I am missing something. I am not really sure about how to proceed to destroy and free the components.show us some code. From what you describe I'm guessing that you do not have the proper owner hierarchy set, when creating the tabsheets and frames. when you create the frame you must pass the tabsheet as the owner on the create call.
It happens the following and I think that is because I'm not freeing correctly the frames or tabsheets. I don't want to destroy the page control, I will just make it unvisible if it's empty and visible again when a new tab is added.
Example:
Frame1 is in tabshheet1 of Pagecontrol.
Frame2 is in tabshheet2
...
Each time I click "add new tab" button a new tab is added
and a new frame is inserted in the tab. Everything fine.
Let's continue. When I click the "close active tab" button in Form1, the active tab closes. Fine. But if I try to add a new tab:
Duplicate name: a component named "Frame4" already exists. Ok to ignore and risk data corruption. Abort to kill the program.
If I remove all the tabs (in theory I empty the pagecontrol)
and I try to add a new tab I will get the same message refering to "Frame1".
It's like destroying the active tab does not destroy and free it's dependant frame %)
regards,
@Raul_ESthat code gave me various ticks while reading it.
I have modified your code to let the frame to be able to call form's status bar. Try to click the 'add', 'subtraction', 'division', 'multiplication' buttons.
I found no information about parentform. Where is the documentation?sorry my bad, its a function in the forms unit called GetParentForm. I have no knowledge of any documentation other than the source code that is.
show us some code. From what you describe I'm guessing that you do not have the proper owner hierarchy set, when creating the tabsheets and frames. when you create the frame you must pass the tabsheet as the owner on the create call.
It's like destroying the active tab does not destroy and free it's dependant frame %)
regards,
@Raul_ES
I have modified your code to let the frame to be able to call form's status bar. Try to click the 'add', 'subtraction', 'division', 'multiplication' buttons.
procedure TFrame1.BitBtn3Click(Sender: TObject); var StatusBar: TStatusBar; begin Label3.caption := 'Add'; StatusBar := GetParentStatusBar; if (StatusBar = nil) then Exit; StatusBar.SimpleText := 'You have pressed addition button.'; end; procedure TFrame1.BitBtn4Click(Sender: TObject); var StatusBar: TStatusBar; begin Label3.caption := 'Substraction'; StatusBar := GetParentStatusBar; if (StatusBar = nil) then Exit; StatusBar.SimpleText := 'You have pressed subtraction button.'; end; procedure TFrame1.BitBtn5Click(Sender: TObject); var StatusBar: TStatusBar; begin Label3.caption := 'Division'; StatusBar := GetParentStatusBar; if (StatusBar = nil) then Exit; StatusBar.SimpleText := 'You have pressed division button.'; end; procedure TFrame1.BitBtn6Click(Sender: TObject); var StatusBar: TStatusBar; begin Label3.caption := 'Multiplication'; StatusBar := GetParentStatusBar; if (StatusBar = nil) then Exit; StatusBar.SimpleText := 'You have pressed multiplication button.'; end; function TFrame1.GetParentStatusBar: TStatusBar; var Caller: TWinControl; StatusBar: TComponent; begin Result := nil; Caller := Parent.Parent.Parent; // tab1 > PageControl1 > Form if not(Caller is TForm) then Exit; StatusBar := Caller.FindComponent('StatusBar1'); Result := (StatusBar as TStatusBar); end;
---edit---
I forget to set result = nil at the beginning of the function.
Do you mean something like this:
Button2.OnClick := @Button2Click; Button1.OnClick := @SharedClickEvent; MenuItem.OnClick := @SharedClickEvent;
Just another point: Why the following doesn't work?
newframePOS : TObject; (something more generic, let's say that I don't want to specify what
kind of control I will use)
newinput: somegenericalobject;
newinput := TComboBox.Create(....
or
newinput := TEdit.Create(... whatever