Matej mtj
Matej mtj

Reputation: 83

How can I check if OnResize event is created on TTabSheet control?

I have multiple TTabSheet on TPageControl and on certain action, user click on a button, I would like run OnResize event on a selected TTabSheet. The problem is that not all TTabSheet controls have OnResize event created.

I have this code on button:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TTabSheet(PageControl1.ActivePage).OnResize(PageControl1.ActivePage);
end;

procedure TForm1.TabSheet1Resize(Sender: TObject);
begin
  // actions on Resize
end;

It works when TabSheet1 is active. But when TabSheet2 is active and it doesn't have OnResize event I get error:

Project Project1.exe raised exception class $C0000005 with message 'access vialotion at 0x00000000: read of address 0x00000000'.

I tried to check for nil, like this:

If TTabSheet(PageControl1.ActivePage).OnResize(PageControl1.ActivePage) <> nil then...

But it doesn't compile:

E2008 Incompatible type.

The workaround I discovered is for each TTabSheet control to have empty OnResize event, with just a comment, no code.

Is there any better check than <> nil, that doesn't work, if TTabSheet has OnResize event?

Thank you

Upvotes: 2

Views: 349

Answers (3)

MartynA
MartynA

Reputation: 30715

Judging by this comment of yours

I set OnResize events, but nothing for TabSheet2. So TabSheet2 has OnResize in Object Inspector but not in code in unit1.

I think you may be confused about exactly what goes on the Form Designer, it terms of defining event-handling code.

Try this:

  1. On a newly-created blank form, drop a TPageControl, PageControl1, right-click it and create two TabSheets in it, TabSheet1 and TabSheet2.

  2. In the OI, click TabSheet1, click its Events tab in the OI and click the drop-down button in the OnResize event property. You will find the drop down list empty.

  3. Now double-click in Tabsheet1's OnResize event. Doing this causes the OI to create an empty event handling procedure TabSheet1Resize in the form's code. It also assigns the OnResize property of TabSheet1 to this procedure, TabSheet1Resize. Don't save the form at this point, or the IDE will detect that this procedure contains no code (or comments) and will delete it.

  4. In TabSheet1Resize add this code

    Caption := 'TabSheet1.Resize';

and save the form's unit.

  1. Now select TabSheet2's event tab in the OI and single-click in its OnResize event. At this point TabSheet2's OnResize property is not assigned to any procedure so attempting to call TabSheet2.OnResize() will result in an AV, because the value of its OnResize property is Nil.

  2. Now, In TabSheet2's OnResize, click the drop-down button and you will see TabSheet1Resize as the single entry in the list. Select it from the list and now the value of TabSheet2's OnResize property is the same as TabSheet1'1, i.e. the procedure TabSheet1Resize.

Steps 3 and 6 are the ones which are vital for TabSheet1 and TabSheet2 to have the same OnResize event-handler code.

In other words, your comment seems to overlook the difference between the event-handler property (e.g. OnResize) which the object, in this case a TTabSheet always has (which is why the OI shows you the event-handler property) and the code in the event-handler procedure, if any, to which the event-handler property is assigned.

Sorry if all the above is painfully obvious, if it is then I've misunderstood several of your comments.

If you want all the other tabsheets to have the same OnResize handler as TabSheet1, you can set this up in, e.g., your FormCreate event handler, like so:

procedure TForm1.FormCreate(Sender: TObject);
var
  i : integer;
begin
  for i := 1 to PageControl1.PageCount - 1 do
    PageControl1.Pages[i].OnResize := PageControl1.Pages[0].OnResize;
  //  PageControl1.Pages[0] will be equal to TabSheet1, if that's the first Tabsheet
  //   you created
end;

Upvotes: 3

David Heffernan
David Heffernan

Reputation: 612964

You are probably going about this the wrong way. You should not invoke event handlers in your code. Leave that to the framework. Instead write it like this:

procedure TForm1.DoTabsheet1Resize;
begin
  // actions on Resize
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoTabsheet1Resize;
end;

procedure TForm1.TabSheet1Resize(Sender: TObject);
begin
  DoTabsheet1Resize;
end;

Here DoTabsheet1Resize is a private method that you define.

Upvotes: 6

Michael Gendelev
Michael Gendelev

Reputation: 481

procedure TForm1.Button1Click(Sender: TObject); 
begin
  If Assigned(PageControl‌​1.ActivePage.OnResize‌​) 
    then PageControl‌​1.ActivePage.OnResize‌​(Sender);       
end;

Upvotes: 5

Related Questions