使用基类对象调用Dervied Class函数

时间:2018-07-24 14:46:53

标签: c++ mfc ribbon

我正在尝试绘制CMFCRibbonTab,其差异要小一些,其中文本的位置要高一点。

为此,我创建了一个名为DCRibbonTab的派生类,该派生类扩展了CMFCRibbonTab并重写了virtual void OnDraw(CDC * pDC)函数,如下所示:

#pragma once
#include "StdAfx.h"

class DCRibbonTab : public CMFCRibbonTab
{
public:
    DCRibbonTab ();

    virtual ~DCRibbonTab ();
    virtual void OnDraw(CDC* pDC);
};

DCRibbonTab::~DCRibbonTab()
{
}

void DCRibbonTab::OnDraw(CDC * pDC)
{
    CMFCRibbonTab::OnDraw(pDC);
    ASSERT_VALID(this);
    ASSERT_VALID(m_pParent);
    ASSERT_VALID(m_pParent->GetParentRibbonBar());

    if (m_rect.IsRectEmpty())
    {
        return;
    }

    COLORREF clrText = CMFCVisualManager::GetInstance()->OnDrawRibbonCategoryTab(pDC, this, m_pParent->IsActive() || GetDroppedDown() != NULL);
    COLORREF clrTextOld = pDC->SetTextColor(clrText);

    CRect rectTab = m_rect;
    CRect rectTabText = m_rect;

    pDC->DrawText(L"test", rectTabText, DT_CALCRECT | DT_SINGLELINE | DT_VCENTER);

    const int cxTabText = rectTabText.Width();
    const int cxTabTextMargin = max(4, (rectTab.Width() - cxTabText) / 2);

    rectTab.DeflateRect(cxTabTextMargin, 0);
    //rectTab.top += nPanelMarginTop;

    pDC->DrawText(GetParentCategory()->GetName(), rectTab, DT_SINGLELINE | DT_VCENTER);
    pDC->SetTextColor(clrTextOld);
}

要能够调用virtual void OnDraw(CDC * pDC)中新的DCRibbonTab,我必须重写void OnPaint()类的CMFCRibbonBar,如下所示:

void DCRibbonBar::OnPaint()
{
    CMFCRibbonBar::OnPaint();

    CPaintDC dc(this); // device context for painting

    int i = 0;

    CMemDC memDC(dc, this);
    CDC* pDC = &memDC.GetDC();

    for (i = 0; i < (int)m_arCategories.GetSize(); i++)
    {
        CMFCRibbonCategory* pCategory = m_arCategories[i];
        ASSERT_VALID(pCategory);

        if (pCategory->IsVisible())
        {
            CMFCRibbonTab * CurrentTab = pCategory->GetTab();

            //Need to Call DCRibbonTab OnDraw function using CMFCRibbonTab object CurrentTab

        }
    }
}

但是,我似乎无法实现的是使用其中是DCRibbonTab对象的基类对象来调用派生类virtual void OnDraw(CDC * pDC) CMFCRibbonTab

那么,如何从基类对象DCRibbonTab调用派生类函数CMFCRibbonTab

2 个答案:

答案 0 :(得分:0)

class DCRibbonTab : public CMFCRibbonTab
{
public:
    DCRibbonTab ();

    virtual ~DCRibbonTab ();
    void OnDraw(CDC* pDC) override;
};

如果您的OnDraw()方法的版本实际上并未覆盖基类中定义的方法,则此版本应提供明确的错误消息。如果看到该错误,则说明您需要仔细检查是否与基类中的函数签名完全匹配,并且当然要确认该函数在基类中被声明为“虚拟”。

如果您没有因添加“覆盖”而出错,那么调用正确的版本应该很简单:

CurrentTab->OnDraw(pDC);

答案 1 :(得分:0)

经过研究,我能够使用函数重载和运行时多态性找到解决方案。 这是该解决方案的源代码:

class DCRibbonTab : public CMFCRibbonTab
{
public:
    DCRibbonTab();
    virtual ~DCRibbonTab();
    void OnDraw(CDC* pDC, BOOL Redraw);
};

static const int nPanelMarginTop = 3;
// DCRibbonTab

DCRibbonTab:: DCRibbonTab ()
{
}

DCRibbonTab::~ DCRibbonTab ()
{
}

void DCRibbonTab::OnDraw(CDC* pDC, BOOL Redraw)
{
    ASSERT_VALID(this);
    ASSERT_VALID(pDC);
    ASSERT_VALID(m_pParent);
    ASSERT_VALID(m_pParent->GetParentRibbonBar());

    if (m_rect.IsRectEmpty())
    {
        return;
    }

    COLORREF clrText = CMFCVisualManager::GetInstance()->OnDrawRibbonCategoryTab(pDC, this, m_pParent->IsActive() || GetDroppedDown() != NULL);
    COLORREF clrTextOld = pDC->SetTextColor(clrText);

    CRect rectTab = m_rect;
    CRect rectTabText = m_rect;

    pDC->DrawText(m_pParent->GetName(), rectTabText, DT_CALCRECT | DT_SINGLELINE | DT_TOP);

    const int cxTabText = rectTabText.Width();
    const int cxTabTextMargin = max(4, (rectTab.Width() - cxTabText) / 2);

    rectTab.DeflateRect(cxTabTextMargin, 0);
    rectTab.top += nPanelMarginTop;

    pDC->DrawText(m_pParent->GetName(), rectTab, DT_SINGLELINE | DT_TOP);
    pDC->SetTextColor(clrTextOld);
}

void DCRibbonBar::OnPaint()
{
    CPaintDC dc(this); // device context for painting

    int i = 0;

    CMemDC memDC(dc, this);
    CDC* pDC = &memDC.GetDC();

    CRect rectClip;
    dc.GetClipBox(rectClip);

    CRgn rgnClip;

    if (!rectClip.IsRectEmpty())
    {
        rgnClip.CreateRectRgnIndirect(rectClip);
        pDC->SelectClipRgn(&rgnClip);
    }

    pDC->SetBkMode(TRANSPARENT);

    CRect rectClient;
    GetClientRect(rectClient);

    OnFillBackground(pDC, rectClient);

    CFont* pOldFont = pDC->SelectObject(GetFont());
    ENSURE(pOldFont != NULL);
    // Draw tabs:
    CRect rectTabs = rectClient;
    rectTabs.top = m_rectCaption.IsRectEmpty() ? rectClient.top : m_rectCaption.bottom;
    rectTabs.bottom = rectTabs.top + m_nTabsHeight;

    COLORREF clrTextTabs = CMFCVisualManager::GetInstance()->OnDrawRibbonTabsFrame(pDC, this, rectTabs);

    for (i = 0; i < (int)m_arCategories.GetSize(); i++)
    {
        CMFCRibbonCategory* pCategory = m_arCategories[i];
        ASSERT_VALID(pCategory);

        if (pCategory->IsVisible())
        {
            DCRibbonTab *TempVnRibbonTab = new DCRibbonTab ();
            CMFCRibbonTab * TempMFCRibbonTab = pCategory->GetTab();
            TempDCRibbonTab = (DCRibbonTab*)TempMFCRibbonTab;
            TempDCRibbonTab->OnDraw(pDC, TRUE);
        }
    }
    // Draw elements on right of tabs:
    COLORREF clrTextOld = (COLORREF)-1;
    if (clrTextTabs != (COLORREF)-1)
    {
        clrTextOld = pDC->SetTextColor(clrTextTabs);
    }
    pDC->SelectObject(pOldFont);
    pDC->SelectClipRgn(NULL);
}