覆盖VCL类/组件保护方法 - 如何编码和使用?

时间:2016-02-08 04:26:09

标签: c++ c++builder vcl

我正在重写旧的现有代码,我正在对图标进行大修。我曾经将位图分配给TMenuItem,但我改为支持ImageIndexTImageList colordepth 32位,包含带alpha通道的图标。 ImageList在设计时创建并填充图标。 ImageIndex在程序启动期间分配,并在适当时更改。

我注意到当禁用MenuItem(enabled = false)时,生成的图像看起来不太好(根本),我读到这是due to VCL。提到的链接还链接到可以将图标转换为其灰度值的Delphi代码。

我不熟练使用Delphi,也不会更改VCL组件,继承它们,继承它们等等。我通常只使用可用而无需更改它。所以我从一些基本问题开始:

这是一个非常简单的尝试从TImage继承并覆盖DoDraw(),使其永远不会禁用图标(将第二步中的Delphi代码删除灰度可以完成)

class MyTImageList : public TImageList
    {
    public:

    __fastcall MyTImageList(Classes::TComponent* AOwner)
        : TImageList(AOwner) {} ;

    virtual __fastcall DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned int Style, bool Enabled = true)
        {
        return TImageList::DoDraw(Index, Canvas, X, Y, Style) ;
        }
    };

仅供参考:我使用的是C ++ Builder 2009 它不编译,错误:[BCC32 Error] Main.h(1018): E2113 Virtual function '_fastcall TMainForm::MyTImageList::DoDraw(int,TCanvas *,int,int,unsigned int,bool)' conflicts with base class 'TCustomImageList'

由于我对继承VCL组件类非常不安全,我不确定我是在处理拼写错误还是非常有建设性的错误?请赐教。

假设这个编译我实际上也不确定如何继续进行。 因为ImageList是在设计时创建的,并且在整个代码中使用。要使此更改生效,我必须使用“MyTimageList”。

那么,我在表单构造期间创建MyTimageList并在{ ​​- 1}}设计时 - ImageList的内容中创建,还是有更有效的方法来避免复制所有内容?

实际上,更多地考虑后一个问题I could simply use the internal ImageList of the design time Imagelist instance

2 个答案:

答案 0 :(得分:1)

以下是Delphi代码的C ++翻译:

class MyTImageList : public TImageList
{
protected:
    virtual void __fastcall DoDraw(int Index, Graphics::TCanvas *Canvas, int X, int Y, unsigned Style, bool Enabled = true);

public:
    __fastcall MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList);
};

__fastcall MyTImageList::MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList)
    : TImageList(AOwner)
{
    ColorDepth = DesignImageList->ColorDepth;
    Handle = DesignImageList->Handle; // Use the internally kept List of the design time ImageList
    ShareImages = true;
}

unsigned __fastcall GetRGBColor(TColor Value)
{
    unsigned Result = ColorToRGB(Value);
    switch (Result)
    {
        case clNone: Result = CLR_NONE; break;
        case clDefault: Result = CLR_DEFAULT; break;
    }
    return Result;
}

void __fastcall MyTImageList::DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned Style, bool Enabled)
{
    if ((Enabled) || (ColorDepth != cd32Bit))
    {
        TImageList::DoDraw(Index, Canvas, X, Y, Style, Enabled);
    }
    else if (HandleAllocated())
    {
        IMAGELISTDRAWPARAMS Options = {0};
        Options.cbSize = sizeof(Options);
        Options.himl = (HIMAGELIST) Handle;
        Options.i = Index;
        Options.hdcDst = Canvas->Handle;
        Options.x = X;
        Options.y = Y;
        Options.cx = 0;
        Options.cy = 0;
        Options.xBitmap = 0;
        Options.yBitmap = 0;
        Options.rgbBk = GetRGBColor(BkColor);
        Options.rgbFg = GetRGBColor(BlendColor);
        Options.fStyle = Style;
        Options.fState = ILS_SATURATE; // Grayscale for 32bit images

        ImageList_DrawIndirect(&Options);
    }
}

答案 1 :(得分:0)

好的,答案很简单,需要一些试验和错误才能到达那里,因为我有权访问的documentation并不清楚。 (例如,TCanvas指针也是错误的。

函数/方法返回void。这是最初发布的代码中缺少的内容以及导致错误的原因。我得到了以下代码以便很好地工作。

class MyTImageList : public TImageList
    {
    public:
    __fastcall MyTImageList(Classes::TComponent* AOwner, TImageList *DesignImageList)
        : TImageList(AOwner)
        {
        Handle = DesignImageList->Handle ; // Use the internally kept List of the design time ImageList
        ShareImages = true;
        }

    protected:
    virtual __fastcall void DoDraw(int Index, TCanvas *Canvas, int X, int Y, unsigned int Style, bool Enabled = true)
        {
        return TImageList::DoDraw(Index, Canvas, X, Y, Style, true /*Enabled*/) ; // Always draw enabled
        }
    };

此问题已关闭。