?
Solved

Restore of  component after new starting of app from ini

Posted on 2010-01-06
21
Medium Priority
?
267 Views
Last Modified: 2013-11-23
With code below I'm creating a _Shape (TShape) while run time.
Is it enough if i record next (listed below) proprieties to restore TShape  when app is started again? Or i must add some other things for creating of component in general?

Brush.Color
Width
Height
Top
Left
procedure TForm1.nov1Click(Sender: TObject);
begin
  _Shape:=TShape.Create(self);
  _Shape.Width:=10;
  _Shape.Height:=10;
  _Shape.Brush.Color:=clwhite;
  With _Shape do   begin
     _Shape.Parent:=self;
     Top:=10;
     Left:=10;
   onMouseDown:=ShapeMouseDown;
   onMouseMove:=ShapeMouseMove;
   onMouseUp:=ShapeMouseUp;
  end;
 _Shape:=nil;
end;

Open in new window

0
Comment
Question by:pr2501
  • 9
  • 7
  • 5
21 Comments
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 26197642
you normally store all properties you change

the odd thing in your code : _Shape:=nil;
this removes the reference to the object
where did you declare the variable _Shape ?
0
 
LVL 5

Expert Comment

by:MvanderKooij
ID: 26197852
The attached code is a little more consistant.

Rule of the thumb. If you want to create a component at run time, you can always put it on a form first, make it work, then look into the dfm file to see which properties are set and copy them to you're code. After this copy you can remove the component from the form and make the copied dfm text work.

(Personally i really dislike the with statement and if Embarcadero decided to remove it from the language i would rejoice. Expecially nested with 's are a pain to debug and understand after a while)
procedure TForm1.nov1Click(Sender: TObject);
begin
  With TShape.Create(self) do begin
   Width:=10;
   Height:=10;
   Brush.Color:=clwhite;
   Parent:=self;
   Top:=10;
   Left:=10;
   onMouseDown:=ShapeMouseDown;
   onMouseMove:=ShapeMouseMove;
   onMouseUp:=ShapeMouseUp;
  end;
end;

Open in new window

0
 
LVL 5

Expert Comment

by:MvanderKooij
ID: 26197859
and, yes, it seemes enough to get it working (parent and owner are set), unless you want something different than the default shape.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:pr2501
ID: 26207640
Pen.Width :=1; (from dfm) but in my case irelevant.

(Geert_Gruwez:)
public
  _Shape:TShape;

Do i have to add parent and owner to ini?

Can You pleas help me repair attached code?
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  cmp: tcomponent;
  i: integer;
begin
  //with TINIFile.Create(ChangeFileExt(Paramstr(0), '.ini')) do
     with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do
  try
    i := 1;
    //cmp := FindComponent('SpeedButton' + IntToStr(i));
    cmp := FindComponent('Shape' + IntToStr(i));
    while (cmp <> nil) do
    begin
      //WriteInteger('Form1', cmp.Name + ' Font Color', integer(TSpeedButton(cmp).Font.Color));
       WriteInteger('Form1', cmp.Name + ' Brush Color', integer(TShape(cmp).Brush.Color));
         WriteInteger('Form1', cmp.Name + ' Width', integer(TShape(cmp).Width));
         WriteInteger('Form1', cmp.Name + ' Height', integer(TShape(cmp).Height));
         WriteInteger('Form1', cmp.Name + ' Top', integer(TShape(cmp).Top));
         WriteInteger('Form1', cmp.Name + ' Left', integer(TShape(cmp).Left));
           i := i + 1; 
     // cmp := FindComponent('SpeedButton' + IntToStr(i));
     cmp := FindComponent('Shape' + IntToStr(i)); 
    end; 
  finally
    free; 
  end; 
end;
// get ini
procedure TForm1.FormCreate(Sender: TObject); 
   var 
  cmp: tcomponent; 
  i: integer;
begin 
  with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do 
  try 
    i := 1;
   // cmp := FindComponent('SpeedButton' + IntToStr(i)); 
   cmp := FindComponent('Shape' + IntToStr(i)); 
    while (cmp <> nil) do 
    begin
      //TSpeedButton(cmp).Font.Color := TColor(ReadInteger('Form1', cmp.Name + ' Font Color', integer(clGreen))); 
      TShape(cmp).Brush.Color := TColor(ReadInteger('Form1', cmp.Name + ' Brush Color', integer(clGreen))); 
  TShape(cmp).Width := ReadInteger('Form1', cmp.Name + ' Width', integer(TShape(cmp).Width)); 
  TShape(cmp).Height := ReadInteger('Form1', cmp.Name + ' Height', integer(TShape(cmp).Height));
  TShape(cmp).Top := ReadInteger('Form1', cmp.Name + ' Top', integer(TShape(cmp).Top)); 
  TShape(cmp).Left := ReadInteger('Form1', cmp.Name + ' Left', integer(TShape(cmp).Left)); 
      i := i + 1; 
      //cmp := FindComponent('SpeedButton' + IntToStr(i));
      cmp := FindComponent('Shape' + IntToStr(i)); 
    end; 
  finally 
    free;
  end; 
    Application.Showhint:=true; 
end;
end.

Open in new window

0
 
LVL 5

Expert Comment

by:MvanderKooij
ID: 26207665
On first sight i see no problems with the code assuming you have created enough shape components.

But if that is the problem you will have to store the number of shapes in the ini and use that count to create shapes + reading the relevant information from the ini.
If that is not the case please tell what need to be fixed.
0
 
LVL 38

Accepted Solution

by:
Geert Gruwez earned 1200 total points
ID: 26207802
just a few pointers

your form1 needs a better name for future use
after 67 or more forms you will have a headache remembering what each form is for

you have algorithm missing when you delete shapes
if you save 20 shapes to the ini the first time
then you delete 5 shapes on the form and save
the data for the 5 remaining shapes will remain in the ini

this should work
you didn't create components
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
var 
  cmp: tcomponent; 
  i: integer; 
begin 
  // you have a fixed path --> only works if dir PC1\Montaza exists
  // Allways better to use relative path
  with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do 
  try 
    i := 1; 
    cmp := FindComponent('Shape' + IntToStr(i)); 
    while cmp <> nil do 
    begin 
       WriteInteger(Self.Name, cmp.Name + ' Brush Color', integer(TShape(cmp).Brush.Color)); 
       // I don't think you need to cast a integer value to a integer value ...
       // WriteInteger('Form1', cmp.Name + ' Width', TShape(cmp).Width); --> less complex
       WriteInteger(Self.Name, cmp.Name + ' Width', integer(TShape(cmp).Width)); 
       WriteInteger(Self.Name, cmp.Name + ' Height', integer(TShape(cmp).Height)); 
       WriteInteger(Self.Name, cmp.Name + ' Top', integer(TShape(cmp).Top)); 
       WriteInteger(Self.Name, cmp.Name + ' Left', integer(TShape(cmp).Left)); 
       i := i + 1;  
       cmp := FindComponent('Shape' + IntToStr(i));  
       if cmp = nil then 
         WriteInteger(Self.Name, 'Shapes', i-1);
    end;  
  finally 
    free;  
  end;  
end; 

// get ini 
procedure TForm1.FormCreate(Sender: TObject);  
   var  
  cmp: TShape;  
  i, n: integer; 
begin  
  with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do  
  try  
    n := ReadInteger(Self.Name, 'Shapes', 0);
    for i := 1 to n do 
    begin
      // if you use TShape as class, you only need to cast once
      cmp := TShape(FindComponent('Shape' + IntToStr(i)));  
      if cmp = nil then 
      begin
        cmp := TShape.Create(Self);
        cmp.Name := 'Shape' + IntToStr(I);
        cmp.Parent := Self;
      end;
      cmp.Brush.Color := TColor(ReadInteger(Self.Name, cmp.Name + ' Brush Color', integer(clGreen)));  
      cmp.Width := ReadInteger(Self.Name, cmp.Name + ' Width', cmp.Width);  
      cmp.Height := ReadInteger(Self.Name, cmp.Name + ' Height', cmp.Height); 
      cmp.Top := ReadInteger(Self.Name, cmp.Name + ' Top', cmp.Top);  
      cmp.Left := ReadInteger(Self.Name, cmp.Name + ' Left', cmp.Left);  
    end;  
  finally  
    free; 
  end;  
  Application.Showhint := true;  
end; 

end. 

Open in new window

0
 

Author Comment

by:pr2501
ID: 26207904
Wery good, it works.
thank you

"you have algorithm missing when you delete shapes"
What do i need to do?

now i can see another problem: For my _Shapes i have popupmenu . After reopening of the form it is not present any more.Can you help me fourther?
0
 
LVL 5

Assisted Solution

by:MvanderKooij
MvanderKooij earned 800 total points
ID: 26208259
>"you have algorithm missing when you delete shapes"
>What do i need to do?

Put the shapes in their own section in the read and write to the ini file: Self.Name + '_shapes'
Then you can delete the whole section before you start saving the shapes to the ini.

Tell more about that menu, is is also created dynamicly?
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);  
var  
  cmp: tcomponent;  
  i: integer;  
begin  
  // you have a fixed path --> only works if dir PC1\Montaza exists 
  // Allways better to use relative path 
  with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do  
  try  
    // delete the old shapes in the ini
    EraseSection(Self.Name + '_shapes');
    i := 1;  
    cmp := FindComponent('Shape' + IntToStr(i));  
    while cmp <> nil do  
    begin  
       WriteInteger(Self.Name + '_shapes', cmp.Name + ' Brush Color', integer(TShape(cmp).Brush.Color));  
       // I don't think you need to cast a integer value to a integer value ... 
       // WriteInteger('Form1', cmp.Name + ' Width', TShape(cmp).Width); --> less complex 
       WriteInteger(Self.Name + '_shapes', cmp.Name + ' Width', integer(TShape(cmp).Width));  
       WriteInteger(Self.Name + '_shapes', cmp.Name + ' Height', integer(TShape(cmp).Height));  
       WriteInteger(Self.Name + '_shapes', cmp.Name + ' Top', integer(TShape(cmp).Top));  
       WriteInteger(Self.Name + '_shapes', cmp.Name + ' Left', integer(TShape(cmp).Left));  
       i := i + 1;   
       cmp := FindComponent('Shape' + IntToStr(i));   
       if cmp = nil then  
         WriteInteger(Self.Name + '_shapes', 'Shapes', i-1); 
    end;   
  finally  
    free;   
  end;   
end;  
 
// get ini  
procedure TForm1.FormCreate(Sender: TObject);   
   var   
  cmp: TShape;   
  i, n: integer;  
begin   
  with TINIFile.Create('c:\PC1\Montaza\Montaza.ini') do   
  try   
    n := ReadInteger(Self.Name + '_shapes', 'Shapes', 0); 
    for i := 1 to n do  
    begin 
      // if you use TShape as class, you only need to cast once 
      cmp := TShape(FindComponent('Shape' + IntToStr(i)));   
      if cmp = nil then  
      begin 
        cmp := TShape.Create(Self); 
        cmp.Name := 'Shape' + IntToStr(I); 
        cmp.Parent := Self; 
      end; 
      cmp.Brush.Color := TColor(ReadInteger(Self.Name + '_shapes', cmp.Name + ' Brush Color', integer(clGreen)));   
      cmp.Width := ReadInteger(Self.Name + '_shapes', cmp.Name + ' Width', cmp.Width);   
      cmp.Height := ReadInteger(Self.Name + '_shapes', cmp.Name + ' Height', cmp.Height);  
      cmp.Top := ReadInteger(Self.Name + '_shapes', cmp.Name + ' Top', cmp.Top);   
      cmp.Left := ReadInteger(Self.Name + '_shapes', cmp.Name + ' Left', cmp.Left);   
    end;   
  finally   
    free;  
  end;   
  Application.Showhint := true;   
end;  
 
end.

Open in new window

0
 

Author Comment

by:pr2501
ID: 26208394
No, i don't create popup menu dimamcli.
0
 

Author Comment

by:pr2501
ID: 26208398
And i have also lost hint for _Shape.
0
 
LVL 5

Expert Comment

by:MvanderKooij
ID: 26208577
Please give more information about your problem which menu, how connected and created who is the owner etc.
0
 
LVL 5

Expert Comment

by:MvanderKooij
ID: 26208581
by hint do you mean the hint for each shape? It is just a property for a shape that can be set.
0
 

Author Comment

by:pr2501
ID: 26208703
For other things pleas give me instructions.
popupmenu.JPG
popupmenuitem.JPG
0
 

Author Comment

by:pr2501
ID: 26208717
And next is the event ofclick on popupitem:
procedure TForm1.N0pen1Click(Sender: TObject);
begin
 F:=TForm2.Create(Application);
 F.Caption:=_Shape.hint;
 mname:=_Shape.hint;
 if mname<>'' then  F.Show
 else begin
 s:='';
_shape.Hint:=InputBox('','Najprej poimenuj stroj', s) ;
   end;
end;

Open in new window

0
 

Author Comment

by:pr2501
ID: 26208730
And thn also other two click events.
procedure TForm1.tag1Click(Sender: TObject);
begin
s:='';
  _shape.Hint:= InputBox('','Poimenuj stroj', s) ;
    _Shape.Brush.Color:=clgreen;
    inc(i);
    _shape.Name:= 'shape'+inttostr(i);
    edit1.Text:= _shape.Name;
end;

procedure TForm1.delate1Click(Sender: TObject);
  var ShouldClose: Boolean;
begin
  if MessageDlg('Ali res ~elia zbrisati stroj?', mtConfirmation,
      [mbYes, mbNo], 0) = mrYes then
   _Shape.Free;
  // if Assigned(_Shape) then _Shape.Free;
end;

Open in new window

0
 
LVL 5

Assisted Solution

by:MvanderKooij
MvanderKooij earned 800 total points
ID: 26208945
Can you tell more about the goal of the program, the relation between _shape, i and TForm2?

From what i see:
- _shape is the last created shape, after deletion of a the current shape a 2nd call will raise exceptions
- i is a global or a member of tform1 and keeps track of the last added shape, but is not decremented when deleting the last one. This results in shape1, shape2, shape4 names if shape 3 was deleted.
-TForm2 will be created when selecting open in the menu. It will be created and assigned to F which is also a global or tform1 member. I wonder how many memory leaks are created here. The tform2 will get the hint of the shape.
- the hint is not saved in the current onclose event of tform1, that needs to be added.

To get the menu working you will need to fill _shape with a valid value, for instance the last shape created in the oncreate event.

What i wonder is whether or not you want a popupmenu working on all shapes...
I think you need to rethink the problem you want to solve. Use a array or something like that to create a list of shapes, maybe using a record in the array to link shapes and froms together etc.
The way you are working now will result in a very long conversation :-)

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 26211127
if you want to use the popupmenu for every shape then you need to identify the shape clicked

procedure TForm1.popMenuItem1Click(Sender: TObject);
var shape: TShape;
begin
  shape := TShape(PopupMenu1.Tag);
  ShowMessage(shape.Name);
end;

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var P: TPoint;
begin
  if Button = mbRight then
  begin
    PopupMenu1.Tag := Integer(Sender);
    P := TShape(Sender).ClientToScreen(Point(X, Y));
    PopupMenu1.Popup(P.X, P.Y);
  end;
end;
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 26211143
your delete would be :

procedure TForm1.popMenuItem1Click(Sender: TObject);
var shape: TShape;
begin
  shape := TShape(PopupMenu1.Tag);
  ShowMessage(shape.Name);
end;

procedure delate1Click(Sender: TObject);
 // var ShouldClose: Boolean;  --> this is not used
begin
  shape := TShape(PopupMenu1.Tag);
  if MessageDlg('Ali res ~elia zbrisati stroj?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    Shape.Free;
end;
0
 

Author Comment

by:pr2501
ID: 26281715

I was not working over the weekend. But now i see that i need more time to understand Your replies (even they are very accurate an simple writed) because i don't have enough knowledge about Delphi.
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 26281838
hey,
we all lack knowledge, if anything is unclear
just ask

i was very good at delphi
then they decided to see how good i was at oracle
i know what it is to be in that situation
i'm currently working 5 minutes and reading 20 or 40 minutes to solve every new problem about oracle
the good thing is, some problems are reoccuring
0
 

Author Comment

by:pr2501
ID: 26282099
I will ask relative question in a new post.
thank you
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses
Course of the Month14 days, 8 hours left to enroll

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question