I have a TPageControl with a number of TTabSheets that contain TForms (or possibly TFrames, but TForms for now).
When a tab comes into view I would like the TForm or TFrame to be notified it has come to the front. I can't find anything that does that.
I know I can get the Active TTabSheet in the OnChange
event, so I tried to add this class to the TForm:
struct iTab
{
virtual void DoIt( void ) = 0;
};
with the this in the OnChange
:
ICPTab *tab = dynamic_cast<ICPTab *>( sheet->Controls[ 0 ] );
Thinking I could use RTTI to get the iTab
pointer and call DoIt()
from the
And I get the warning:
[BCC32 Warning] Unit1.h(18): W8130 Interface 'IPTab' does not derive from IUnknown. (Interfaces should derive from IUnknown)
[BCC32 Warning] MainWindow.cpp(612): W8131 Casting Delphi style class 'TControl' to an interface. Use 'System::interface_cast<ICPTab>(cls)' instead
I am not interested in getting all of IUnknown just so that the form can use an interface.
I can get the TFrame or TForm pointer using:
TForm *tab = dynamic_cast<TForm *>( sheet->Controls[ 0 ] );
but can't call a non TFo开发者_StackOverflow中文版rm method with this pointer. Would it be ok to call the Activate()
method?
So how do I notify the TForm or TFrame that it is now showing?
You have to derive iTab
from IUnknown
(or IInterface
) or order to use it as an interface correctly. The compiler warning even hints that you can use interface_cast
to extract an interface from a Delphi-style (aka TObject
-derived) object. Alternatively use TObject::GetInterface()
instead.
Otherwise, if you just want to call methods of your custom TForm class, then just type-cast the child control pointer from your TTabSheet to your actual TForm-derived class:
TMyForm *tab = dynamic_cast<TMyForm *>( sheet->Controls[ 0 ] );
if( tab != NULL ) tab->DoSomething();
Or:
static_cast<TMyForm *>( sheet->Controls[ 0 ] )->DoSomething();
I went with the following code:
void __fastcall TgMainWindow::mPageControlChange( TObject* Sender )
{
NOT_USED( Sender );
TTabSheet* sheet = mPageControl->ActivePage;
if ( sheet->ControlCount > 0 )
{
// form or frame, we will attempt to call the OnActivate method
TForm* form = dynamic_cast<TForm *>( sheet->Controls[ 0 ] );
if ( form == NULL )
{
ShowMessageDlg( this, L"Programming Error: Initial child on tabsheet must be a TForm", mtError, TMsgDlgButtons( ) << mbOK );
}
else
{
if ( form->OnActivate != NULL )
{
form->OnActivate( this );
}
else
{
ShowMessageDlg( this, L"Programming Error: From must have an OnActivate event", mtError, TMsgDlgButtons( ) << mbOK );
}
}
}
}
Since a form on a tabsheet never has its OnActivate method called, this works quite well.
note: the method sample is not complete, there is no call to OnDeactivate
精彩评论