Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Insensitive Top-Left Corner

Status
Not open for further replies.

trutkowski

Programmer
Dec 12, 2011
2
GB
I have a problem with my program that I cannot pin to a logical error. There are no compiler warnings generated, and the code compiles. The problem lies somewhere in this constructor:

Code:
constructor TBar1.Create;
var i:integer;
begin
  for i := 1 to 4 do
  begin
    Images[i] := TImage.Create(Form1);
    Images[i].BringToFront;
    Images[i].Parent := Form1;
    Images[i].Top := 0;
    Images[i].Height := 46;
  end;
  for i := 1 to 2 do
  begin
    Images[i].Left := (i-1)*179;
    Images[i].Width := 179;
  end;
  for i := 3 to 4 do
  begin
    Images[i].Left := 358 + (i-3)*45;
    Images[i].Width := 46;
  end;
  Images[1].Picture.LoadFromFile(GetCurrentDir()+'/Buttons/CategoryButton.bmp');
  Images[2].Picture.LoadFromFile(GetCurrentDir()+'/Buttons/ExtraButton.bmp');
  Images[3].Picture.LoadFromFile(GetCurrentDir()+'/Buttons/SettingButton.bmp');
  Images[4].Picture.LoadFromFile(GetCurrentDir()+'/Buttons/SearchButton.bmp');
  for i := 1 to 3 do
  begin
  Images[i].OnClick := Form1.ClickProc;
  end;
end;

Images 2 and 3 have no issues. Image 1 however, despite displaying perfectly; is almost entirely insensitive to the clicks; only the very bottom few rows actually generate an 'OnClick' method. What could be causing the issue?
 
Fixed; turned out it was caused by a constructor creating 2 instances of an object erroneously because its coordinate setting was proceduralised without prior initialisation in the main body of the constructor. The erroneous instance was located invisibly in the top-left corner and this was blocking the input. The code I posted is fine. Took me 5 hours to locate this bug! You live... you learn! :)
 
One really great practice everyone should follow is this:

Any and every time you ever call a constructor, make sure you immediately go and declare its corresponding destructor before you forget - and before you put any code calling the constructor. Object creation isn't something to play around with, it can lead to major memory leaks.

So if I want to call...

Code:
MyObjInst:= TMyObj.Create(Self);

I need to immediately go and free it in the proper place...

Code:
MyObjInst:= TMyObj.Create(Self);
try
  //Do something with MyObjInst
finally
  MyObjInst.Free;
end;

or even...

Code:
procedure TForm1.Create(Sender: TObject);
begin
  MyObjInst:= TMyObj.Create(Self);
end;

procedure TForm1.Destroy(Sender: TObject);
begin
  MyObjInst.Free;
end;

And the same applies for pointers...

Code:
PMyRecord = ^TMyRecord;
TMyRecord = record
  SomeVal: String;
  AnotherVal: Integer;
end;

...

MyRec:= New(PMyRecord);
try
  //Do something with MyRec
finally
  Dispose(MyRec);
end;


JD Solutions
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top