Embarking on creating my first component. I'm uncertain about one aspect and based on past practice I'd normally just go ahead and create the packaged component using test code to see if it works. But I read that it's very important to test the component code extensively first before packaging it into a component and that it's definitely not a good idea to package code that contains a flaw as the conseqences can be dire for your copy of Lazarus itself. So I'd like to resolve the uncertainty before going on to the packaging stage.
The uncertainty is how the component's OnClick event will behave after a program developer selects it for use in his application using his object inspector. I have two questions.
By way of background, the component displays two images that alternate with each other. One image is of a switch in the up position and the other is of the switch in the down position. I can create the component in a couple of different ways :
1. As a TCustomControl object that contains two separate TImages – one each for the two different switch positions. In the object's constructor each image gets its own switch position by using its picture.LoadFromFile function, or
2. As a TImage object that dynamically changes its picture property at run time to show one or other of the two different switch positions using the LoadFromFile function.
The first question concerns case 1. In that case in the object constructor both of the two TImages' OnClick events are pointed to a single method called SwitchClick that alternates the display of the images. Of course the TCustomControl object also has its own OnClick event but that is not triggered when the user clicks on one or other of the two images. In effect, the images hide the object's OnClick event. But the object's OnClick event can be triggered if the code line “Click” is included in SwitchClick. The following code extract shows this using a dummy procedure ObjectClick to illustrate the point.
TSwitch = class(TCustomControl)
private
fImageUp: TImage;
fImageDown: TImage;
procedure SwitchClick(Sender:TObject);
procedure ObjectClick(Sender:TObject); (*****)
procedure flip;
public
constructor Create(aOwner: TComponent);
published
end;
constructor TSwitch.Create(aOwner: TComponent);
begin
inherited;
fImageUp := TImage.create (aOwner as TForm);
fImageDown := TImage.create (aOwner as TForm);
fImageUp.parent := aOwner as TForm;
fImageUp.picture.LoadFromFile('Brown_switch_up.jpg');
fImageUp.onClick := @SwitchClick;
fImageDown.parent := aOwner as TForm;
fImageDown.picture.LoadFromFile('Brown_switch_down.jpg');
fImageDown.onClick := @SwitchClick;
onClick := @ObjectClick; (*****)
end;
procedure TSwitch.SwitchClick(Sender:TObject);
begin
flip;
Click;
end;
procedure TSwitch.ObjectClick(Sender:TObject); (*****)
begin (*****)
showmessage('Component was clicked'); (*****)
end; (*****)
procedure TSwitch.Flip;
begin
fUp := not fUp;
if fUp then
begin
fImageUp.show;
fImageDown.hide;
.....
end
else
begin
fImageUp.hide;
fImageDown.show;
.....
end;
end;
The first question is : assuming that the code lines marked (*****) are removed before packaging the component and the program developer creates an OnClick event for the component in his application that includes the code line “ShowMessage('Component was clicked')”, what will be the outcome after an end user clicks one of the component's images? Ideally the component's SwitchClick method should first alternate the display of the two images by calling flip and then the OnClick event in the application should show the message. But will that in fact be the case?
The second question concerns case 2. Since in that case the object itself is derived from TImage it's OnClick event is immediately available to user action. In the object's constructor that OnClick event is pointed to the SwitchClick method which alternates the display of the switch position by using the LoadFromFile function to get the appropriate switch-up or switch-down image. The following code extract shows this :
TSwitch = class(TImage)
private
procedure SwitchClick(Sender:TObject);
procedure flip;
public
constructor Create(aOwner: TComponent);
published
end;
constructor TSwitch.Create(aOwner: TComponent);
begin
inherited;
picture.LoadFromFile('Brown_switch_up.jpg');
parent := aOwner as TForm;
onClick := @SwitchClick;
end;
procedure TSwitch.SwitchClick(Sender:TObject);
begin
flip;
end;
procedure TSwitch.Flip;
begin
fUp := not fUp;
if fUp then
begin
picture.LoadFromFile('Brown_switch_up.jpg');
.....;
end
else
begin
picture.LoadFromFile('Brown_switch_down.jpg');
.....
end;
The second question is what will be the outcome of an end user clicking the component if the program developer, as before, creates an OnClick event in the application that shows the same message? My guess is that, as written, only the actions in SwitchClick will be implemented and the OnClick event in the application will not be triggered. But is that correct? If that's not correct and the message does in fact get displayed – all well and good. But if the analysis is correct then adding the code line “Click” to SwitchClick to try to solve the problem would seem to be problematic as that would be a recursive call to itself and that might create havoc. So what then is the solution?
Any response would be much appreciated. Thanks.