将 TForms 添加到 TPageControl,如何通知 TForm 它正在显示?

发布于 2024-10-17 17:08:17 字数 1103 浏览 2 评论 0原文

我有一个 TPageControl,其中包含许多包含 TForm(或可能是 TFrame,但目前是 TForm)的 TTabSheets。

当选项卡进入视图时,我希望 TForm 或 TFrame 收到通知,它已来到前面。我找不到任何可以做到这一点的东西。

我知道我可以在 OnChange 事件中获取 Active TTabSheet,因此我尝试将此类添加到 TForm:

struct iTab
{
    virtual void DoIt( void ) = 0;
};

OnChange 中使用 this:

  ICPTab *tab = dynamic_cast<ICPTab *>( sheet->Controls[ 0 ] );

我想我可以使用 RTTI获取 iTab 指针并调用 DoIt() 我收到警告:

[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

我对获取所有 IUnknown 不感兴趣,以便表单可以使用接口。

我可以使用以下方法获取 TFrame 或 TForm 指针:

  TForm *tab = dynamic_cast<TForm *>( sheet->Controls[ 0 ] );

但无法使用此指针调用非 TForm 方法。调用 Activate() 方法可以吗?

那么我如何通知 TForm 或 TFrame 现在正在显示呢?

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 TForm 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妄想挽回 2024-10-24 17:08:17

您必须从 IUnknown(或 IInterface)派生 iTab 或顺序将其正确用作接口。编译器警告甚至提示您可以使用 interface_cast 从 Delphi 样式(又名 TObject 派生)对象中提取接口。或者使用 TObject::GetInterface() 代替。

否则,如果您只想调用自定义 TForm 类的方法,则只需将子控件指针从 TTabSheet 类型转换为实际的 TForm 派生类:

TMyForm *tab = dynamic_cast<TMyForm *>( sheet->Controls[ 0 ] );
if( tab != NULL ) tab->DoSomething();

或者:

static_cast<TMyForm *>( sheet->Controls[ 0 ] )->DoSomething();

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();
一指流沙 2024-10-24 17:08:17

我使用了以下代码:

  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 );
           }
        }
     }
  }

由于选项卡上的表单从未调用其 OnActivate 方法,因此效果非常好。

注意:方法示例不完整,没有调用 OnDeactivate

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文