Skip to content

Stupid PageControl Tricks

Most of the user interface for our Delphi applications is generated dynamically, at runtime. When we display this dynamically-generated user interface in a page control, we don’t generate the user interface for each page until you first go to it. This is for performance reasons, as there is some overhead to this, mostly due to database access.

When we enabled XP themes for our applications, I started noticing a flashing on the screen the first time you went to each tab in the page control. A little testing demonstrated that the gradient background of the tab was being rendered before the controls were created.

This turned out to be a fairly difficult problem to solve. When the user changes tabs, I need to figure out to which tab they are changing, and create the controls for that tab if they are not already created. In the TPageControl.OnChanging event, I don’t know to which tab the user is changing. Unfortunately, both the TPageControl.OnChange and the TTabSheet.OnShow event occur after the background of the tab has already been painted. I needed a way to render the controls, if necessary, in between these events, but after the tab to which the user is changing is already known.

After some rooting around in the VCL source code, I came up with the following solution.

type
  TChangeToPageEvent = procedure (Sender: TObject; const APageIndex: Integer) of object;
  TChangeToEventPageControl = class(TPageControl)
  private
    FOnChangeToPage: TChangeToPageEvent;
    procedure DoOnChangeToPage(const APageIndex: Integer);
  protected
    procedure Change; override;
  public
    property OnChangeToPage: TChangeToPageEvent read FOnChangeToPage write FOnChangeToPage;
  end;

{ TChangeToEventPageControl }

procedure TChangeToEventPageControl.Change;
begin
  DoOnChangeToPage(TabIndex);
  inherited;
end;

procedure TChangeToEventPageControl.DoOnChangeToPage(const APageIndex: Integer);
begin
  if Assigned(FOnChangeToPage) then begin
    FOnChangeToPage(Self, APageIndex);
  end;
end;

Since I also create the page control itself dynamically, I don’t even have to install this on the component palette to make it work. Handling the OnChangeToPage event allows me to create the controls when the page to which the user is changing is known, but before the tab itself renders.

{ 3 } Comments

  1. Andreas Hausladen | May 1, 2008 at 3:23 pm | Permalink

    You might also have a look at the "workaround" in QC Report #56252 which redurces PageControl flickering.

    http://qc.codegear.com/wc/qcmain.aspx?d=56252

  2. Anthony Frazier | May 2, 2008 at 7:49 am | Permalink

    Would it be possible to write this up as a class helper? I’m still trying to think of the benefits to that though.

  3. Craig Stuntz | May 2, 2008 at 8:48 am | Permalink

    Anthony, I can’t see how that would work.

Post a Comment

Your email is never published nor shared. Required fields are marked *
Close