When I try to add controls to an already existing TTabSheet
at runtime, these controls stay invisible when they are added within the OnShow
event of TTabSheet
.
Steps to reproduce:
TPageControl
to a TForm
in the designerTTabSheet
objects to this TPageControl
in the designer.TTabSheet
active (at design time).Header file:
#ifndef Unit1H
#define Unit1H
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // Von der IDE verwaltete Komponenten
TPageControl *PageControl1;
TTabSheet *TabSheet1;
TTabSheet *TabSheet2;
TTabSheet *TabSheet3;
TButton *Button1;
void __fastcall TabSheet1Show(TObject *Sender);
private: // Benutzer-Deklarationen
TButton *ButtonConstructor;
TButton *ButtonOnTabShow;
public: // Benutzer-Deklarationen
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Source File:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// Adding a TButton in the Form's constructor works
TTabSheet *ts = this->TabSheet1;
if (!this->ButtonConstructor)
{
ButtonConstructor = new TButton( ts );
ButtonConstructor->Name = "ButtonConstructor";
ButtonConstructor->Caption = "Construct";
ButtonConstructor->Parent = ts;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TabSheet1Show(TObject *Sender)
{
// Adding a TButton in the OnShow Event of TTabSheet does NOT work:
// The button stays invisible
TTabSheet *ts = dynamic_cast< TTabSheet * >( Sender );
// TTabSheet *ts = this->ButtonOnTabShow; // does not make any difference
if (!this->ButtonOnTabShow)
{
ButtonOnTabShow = new TButton( ts );
ButtonOnTabShow->Name = "ButtonOnTabShow";
ButtonOnTabShow->Caption = "Show";
ButtonOnTabShow->Parent = ts;
// Button should be placed below the other
ButtonOnTabShow->Top = ButtonConstructor->Top + ButtonConstructor->Height + 2;
}
// The following 2 lines would make the Button visible
// PageControl1->ActivePageIndex = 1;
// PageControl1->ActivePageIndex = 0;
}
The Result is:
ButtonConstructor
is visibleButtonOnTabShow
is not visibleIf you click on TabSheet2
and then go back to TabSheet1
, ButtonOnTabShow
will also be visible.
Is this a bug which cannot be solved, or am I missing something?
I'm not sure exactly why it happens, but I can reproduce it. It probably has to do with the way TPageControl
manages the visibility of its TTabSheet
objects (since the Win32 API has no concept of tab sheets. TTabSheet
is a wholly VCL invention to ease management of tabbed content). However, it is easy to work around using this code:
#define WM_ENSUREBUTTONSHOWN (WM_APP+1)
void __fastcall TForm1::TabSheet1Show(TObject *Sender)
{
// ...
if (!this->ButtonOnTabShow)
{
ButtonOnTabShow = new TButton( ts );
// ...
PostMessage(Handle, WM_ENSUREBUTTONSHOWN, 0, 0);
}
}
void __fastcall TForm1::WndProc(TMessage &Message)
{
TForm::WndProc(Message);
if ((Message.Msg == WM_ENSUREBUTTONSHOWN) && (this->ButtonOnTabShow))
{
this->ButtonOnTabShow->Hide();
this->ButtonOnTabShow->Show();
}
}
Alternatively:
#define WM_REFRESHTABSHEET (WM_APP+1)
void __fastcall TForm1::TabSheet1Show(TObject *Sender)
{
// ...
if (!this->ButtonOnTabShow)
{
ButtonOnTabShow = new TButton( ts );
// ...
PostMessage(Handle, WM_REFRESHTABSHEET, 0, 0);
}
}
void __fastcall TForm1::WndProc(TMessage &Message)
{
TForm::WndProc(Message);
if ((Message.Msg == WM_REFRESHTABSHEET) && (this->TabSheet1->Visible))
{
this->TabSheet1->Hide();
this->TabSheet1->Show();
}
}