TBitBtn和TButton继承链发生了什么? [英] What happened to TBitBtn and TButton inheritance chain?

查看:103
本文介绍了TBitBtn和TButton继承链发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始将RAD Studio 2007项目升级到RAD Studio2009.我注意到的一件事是,看似简单的代码突然无法编译.

I've recently began to upgrade my RAD Studio 2007 project to RAD Studio 2009. One thing I noticed is when seemingly simple code all of a sudden failed to compile.

示例代码:

class CButtonPopupMenu
{
    // Snip

public:
    void Init( TButton* SrcButton )
    {
        SrcButton->OnClick = OnButtonClick;
    }

private:
    void __fastcall OnButtonClick( TObject* Sender )
    {
        // Do some button click stuff
    }
};

// Snip

TButton button = new TButton( this );
TBitBtn bitBtn = new TBitBtn( this );
CButtonPopupMenu popupButton = new CButtonPopupMenu( button );
CButtonPopupMenu popupBitBtn = new CButtonPopupMenu( bitBtn );

所有这些都用于编译,但是2009年失败了.查看用于从TButton派生的2007 TBitBtn的继承链.因此,TButton类共享任何按钮控件(即OnClick)上预期的事件.因此,我能够将我的TBitBtn类视为TButton.

This all use to compile, but with 2009 it's failing. Looking at the inheritance chain for 2007 TBitBtn used to derive from TButton. Therefore, events that are expected on any button control (i.e. OnClick) were shared by the TButton class. Therefore, I was able to treat my TBitBtn class as a TButton.

2007年继承链:

  • TBitBtn:TButton

2009年继承链:

  • TBitBtn:TCustomButton
  • TButton:TCustomButton

2009年, TButton TBitButton 均来自 TCustomButton ,如果在此保留类似按钮的属性,我认为这很好.如果是这种情况,我可以更改代码以代替 TCustomButton .不幸的是, TCustomButton 不包含 OnClick 之类的东西.因此,我不再将 TBitBtn 视为 TButton .这两个类现在都有自己的独立按钮(例如属性)(即,它们都声明了自己的OnClick事件).我的意思是,至少要提供同时实现 TButton TBitBtn 的接口或诸如 IButton 之类的东西.

In 2009, both TButton and TBitButton derive from TCustomButton, which would be fine I suppose if the button like attributes were held there. If this were the case, I could just change the code to deal with a TCustomButton instead. Unfortunately, TCustomButton does not hold things like OnClick. Therefore, I can no longer treat a TBitBtn like a TButton. Both of these classes, now have their own separate button like attributes (i.e. they both have their own OnClick event declared). I mean, at least provide an interface or something, like IButton that both TButton and TBitBtn implement.

这些看起来无害的变化似乎可以造成不必要的破坏.这似乎很奇怪,并且想知道是否有人知道为什么CodeGear(或任何与此有关的Framework作者)会做这种事情?

It seems that these types of seemingly innocent changes are the ones that can wreak unnecessary havoc. This seems odd and am wondering if anyone knows why CodeGear (or any Framework author for that matter) would do this type of thing?

更重要的是,鉴于这种零散的继承关系,是否有优雅解决方案将 TBitBtn TButton 一样对待?

More importantly, given this fragmented inheritance, is there and elegant solution to treat a TBitBtn like a TButton?

推荐答案

TButton和TBitBtn仍然继续共享一个常见的OnClick事件,因为从开始一直在TControl级别一直实现该事件,并且一直. TButton只是将受保护的TControl :: OnClick事件发布为发布,然后TBitBtn将继承该事件.

TButton and TBitBtn do still continue to share a common OnClick event, as it is implemented all the way down at the TControl level to begin with, and always has been. TButton was merely promoting the protected TControl::OnClick event to published, which TBitBtn would then inherit.

在D2009中,TCustomButton与其他TCustom ...类一样,不会将受保护的成员从基类升级为已发布. TButton和TBitBtn将受保护的TControl :: OnClick事件提升为单独发布.但是事件本身仍然存在于TControl级别.

In D2009, TCustomButton, like other TCustom... classes, does not promote protected members from base classes to published. TButton and TBitBtn promote the protected TControl::OnClick event to published individually. But the event itself still exists at the TControl level.

由于它在TControl级别受到保护,因此可以使用访问器类来访问它,即:

Since it is protected at the TControl level, you can use an accessor class to reach it, ie:

class TCustomButtonAccess
{
public:
    __property OnClick;
};

class CButtonPopupMenu
{
    // Snip

public:
    void Init( TCustomButton* SrcButton )
    {
        ((TCustomButtonAccess*)SrcButton)->OnClick = OnButtonClick;
    }

private:
    void __fastcall OnButtonClick( TObject* Sender )
    {
        // Do some button click stuff
    }
};

或者,对于任何常规TControl指针:

Or, for any general TControl pointer:

class TControlAccess
{
public:
    __property OnClick;
};

class CControlPopupMenu
{
    // Snip

public:
    void Init( TControl* SrcControl )
    {
        ((TControlAccess*)SrcControl)->OnClick = OnControlClick;
    }

private:
    void __fastcall OnControlClick( TObject* Sender )
    {
        // Do some click stuff
    }
};

一个更优雅的解决方案是改用RTTI,它还允许您处理其他类型的对象,例如TSpeedButton,它们具有自己的OnClick事件,即:

A more elegant solution would be to use RTTI instead, which would also allow you to handle other types of objects, such as TSpeedButton, which have their own OnClick event, ie:

#include <TypInfo.hpp>

class TControlAccess
{
public:
    __property OnClick;
};

class CControlPopupMenu
{
    // Snip

public:
    void Init( TControl* SrcControl )
    {
        TMethod m;
        m.Code = &OnControlClick;
        m.Data = this;
        SetMethodProp(SrcControl, "OnClick", m);
    }

private:
    void __fastcall OnControlClick( TObject* Sender )
    {
        // Do some click stuff
    }
};

甚至:

#include <TypInfo.hpp>

class CObjectPopupMenu
{
    // Snip

public:
    void Init( TObject* SrcObject )
    {
        TMethod m;
        m.Code = &OnObjectClick;
        m.Data = this;
        SetMethodProp(SrcObject, "OnClick", m);
    }

private:
    void __fastcall OnObjectClick( TObject* Sender )
    {
        // Do some click stuff
    }
};

这篇关于TBitBtn和TButton继承链发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆