zoukankan      html  css  js  c++  java
  • ChartCtrl源码剖析之——CChartLegend类

    CChartLegend类用来绘制每一个波形的描述信息,它处于该控件的区域,如下图所示: 

    CChartLegend类的头文件。

    #if !defined(AFX_CHARTLEGEND_H__CD72E5A0_8F52_472A_A611_C588F642080B__INCLUDED_)
    #define AFX_CHARTLEGEND_H__CD72E5A0_8F52_472A_A611_C588F642080B__INCLUDED_
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    #include "ChartObject.h"
    #include "ChartCtrl.h"
    #include "ChartString.h"
    class CChartSerie;
    class CChartLegend : public CChartObject  
    {
        friend CChartCtrl;
    public:
        void SetFont(int iPointSize, const TChartString& strFaceName);
        CChartLegend(CChartCtrl* pParent);
        virtual ~CChartLegend();
        enum DockSide
        {
            dsDockRight,
            dsDockLeft,
            dsDockTop,
            dsDockBottom
        };
        void DockLegend(DockSide dsSide);
        void UndockLegend(int iLeftPos, int iTopPos);
        void SetTransparent(bool bTransparent);  
        void SetHorizontalMode(bool bHorizontal);
    private:
        void Draw(CDC* pDC);
        void ClipArea(CRect& rcControl, CDC* pDC);
        void UpdatePosition(CDC* pDC, const CRect& rcControl);
        TChartString m_strFontName;
        int          m_iFontSize;
        bool m_bDocked;    // true if the legend is docked
        DockSide m_DockSide;
        // If the legend is not docked:
        int m_iLeftPos;
        int m_iTopPos;
        bool m_bIsTransparent;
        bool m_bIsHorizontal;
        CSize m_BitmapSize;
    };
    #endif // !defined(AFX_CHARTLEGEND_H__CD72E5A0_8F52_472A_A611_C588F642080B__INCLUDED_)

    CChartLegend类的源文件。

    #include "stdafx.h"
    #include "ChartLegend.h"
    #include "ChartSerie.h"
    #include "ChartCtrl.h"
    #ifdef _DEBUG
    #undef THIS_FILE
    static char THIS_FILE[]=__FILE__;
    #define new DEBUG_NEW
    #endif
    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////
    CChartLegend::CChartLegend(CChartCtrl* pParent):CChartObject(pParent)
    {
        m_ObjectColor = RGB(255,255,255);
        m_iFontSize = 100;
        m_strFontName = _T("Times New Roman");
        m_bIsVisible = false;
        m_bDocked = true;
        m_DockSide = dsDockRight;
        m_iLeftPos = m_iTopPos = 0;
        m_bIsTransparent = false;
        m_bIsHorizontal = false;
        m_bShadow = true;
        m_iShadowDepth = 3;
        m_BitmapSize.cx = 16;
        m_BitmapSize.cy = 16;
    }
    CChartLegend::~CChartLegend()
    {
    }
    void CChartLegend::SetFont(int iPointSize, const TChartString& strFaceName)
    {
        m_iFontSize = iPointSize;
        m_strFontName = strFaceName;
        m_pParent->RefreshCtrl();
    }
    void CChartLegend::SetTransparent(bool bTransparent)
    {
        m_bIsTransparent = bTransparent;
        m_pParent->RefreshCtrl();
    }
    void CChartLegend::SetHorizontalMode(bool bHorizontal)
    {
        m_bIsHorizontal = bHorizontal;
        m_pParent->RefreshCtrl();
    }
    void CChartLegend::DockLegend(DockSide dsSide)
    {
        m_bDocked = true;
        m_DockSide = dsSide;
        m_pParent->RefreshCtrl();
    }
    void CChartLegend::UndockLegend(int iLeftPos, int iTopPos)
    {
        m_bDocked = false;
        m_iLeftPos = iLeftPos;
        m_iTopPos = iTopPos;
        m_pParent->RefreshCtrl();
    }
    void CChartLegend::ClipArea(CRect& rcControl, CDC* pDC)
    {
        UpdatePosition(pDC,rcControl);
        if (m_ObjectRect.IsRectEmpty())
            return;
        if (m_bDocked)
        {
            switch (m_DockSide)
            {
            case dsDockRight:
                rcControl.right = m_ObjectRect.left + 2;
                break;
            case dsDockLeft:
                rcControl.left = m_ObjectRect.right - 2;
                break;
            case dsDockTop:
                rcControl.top = m_ObjectRect.bottom + 2;
                break;
            case dsDockBottom:
                rcControl.bottom = m_ObjectRect.top - 2;
                break;
            }
        }
    }
    void CChartLegend::UpdatePosition(CDC* pDC, const CRect& rcControl)
    {
        CRect NewPosition;
        NewPosition.SetRectEmpty();
        if (!m_bIsVisible)
        {
            SetRect(NewPosition);
            return;
        }
        CFont* pOldFont;
        CFont NewFont;
        NewFont.CreatePointFont(m_iFontSize,m_strFontName.c_str(),pDC);
        pOldFont = pDC->SelectObject(&NewFont);
        int Height = 0;        
        int Width = 0;        
        int MaxText = 0;
        CSize TextSize;
        size_t SeriesCount = m_pParent->GetSeriesCount();
        int Drawn = 0;
        for (size_t i=0;i<SeriesCount;i++)
        {
            CChartSerie* pSerie = m_pParent->GetSerie(i);
            if ( (pSerie->GetName() == _T("")) || !pSerie->IsVisible() )
                continue;
            Drawn++;
            TextSize = pDC->GetTextExtent(pSerie->GetName().c_str());
            if (!m_bIsHorizontal)
            {
                if (TextSize.cy>m_BitmapSize.cy)
                    Height += TextSize.cy + 2;
                else
                    Height += m_BitmapSize.cy + 2;
                if (TextSize.cx > MaxText)
                    MaxText = TextSize.cx;
            }
            else
            {
                Width += TextSize.cx + 4 + m_BitmapSize.cx + 10;
                if (TextSize.cy > MaxText)
                    MaxText = TextSize.cy;
            }
        }
        pDC->SelectObject(pOldFont);
        DeleteObject(NewFont);
        if (!Drawn)
        {
            SetRect(NewPosition);
            return;
        }
        if (!m_bIsHorizontal)
        {
            Width += MaxText + m_BitmapSize.cx + 12;
            Height += 4 + 4 - 2;    // Top and bottom margins. -2 because space counted once too much
        }
        else
        {
            Width += 2 + 2 - 10;
            Height = 4 + max(m_BitmapSize.cy,MaxText) + 4;
        }
        
        if (!m_bDocked)
        {
            NewPosition.top = m_iTopPos;
            NewPosition.left = m_iLeftPos;
            NewPosition.bottom = m_iTopPos + Height + 2;
            NewPosition.right = m_iLeftPos + Width;
        }
        else
        {
            switch (m_DockSide)
            {
            case dsDockRight:
                NewPosition.top = ((rcControl.bottom-rcControl.top)/2) - ((Height + 2)/2);
                NewPosition.left = rcControl.right - (Width + 6);
                NewPosition.bottom = NewPosition.top + Height;
                NewPosition.right = NewPosition.left + Width;
                break;
            case dsDockLeft:
                NewPosition.top = ((rcControl.bottom-rcControl.top)/2) - ((Height + 2)/2);
                NewPosition.left = rcControl.left + 3;
                NewPosition.bottom = NewPosition.top + Height;
                NewPosition.right = NewPosition.left + Width;
                break;
            case dsDockTop:
                NewPosition.top = rcControl.top + 3;  //((rcControl.bottom-rcControl.top)/2) - ((Height + 2)/2);
                NewPosition.left = ((rcControl.right-rcControl.left)/2) - (Width/2);  // rcControl.left + 3;
                NewPosition.bottom = NewPosition.top + Height;
                NewPosition.right = NewPosition.left + Width;
                break;
            case dsDockBottom:
                NewPosition.top = rcControl.bottom - (Height + 2);  //((rcControl.bottom-rcControl.top)/2) - ((Height + 2)/2);
                NewPosition.left = ((rcControl.right-rcControl.left)/2) - (Width/2);  // rcControl.left + 3;
                NewPosition.bottom = NewPosition.top + Height;
                NewPosition.right = NewPosition.left + Width;
                break;
            }
        }
        SetRect(NewPosition);
    }
    void CChartLegend::Draw(CDC *pDC)
    {
        if (!pDC->GetSafeHdc())
            return;
        if (!m_bIsVisible)
            return;
        if (m_ObjectRect.IsRectEmpty())
            return;
        CPen SolidPen(PS_SOLID,0,RGB(0,0,0));
        CPen* pOldPen;
        CFont* pOldFont;
        CFont NewFont;
        NewFont.CreatePointFont(m_iFontSize,m_strFontName.c_str(),pDC);
        // Draw the shadow
        if (m_bShadow)
        {
            CRect ShadowRect = m_ObjectRect;
            ShadowRect.OffsetRect(m_iShadowDepth,m_iShadowDepth);
            CBrush BrushShadow;
            BrushShadow.CreateSolidBrush(m_ShadowColor) ;
            pDC->FillRect(ShadowRect,&BrushShadow);
        }
        if (!m_bIsTransparent)
        {
            //Fill back color
            CBrush BrushBack;
            BrushBack.CreateSolidBrush(m_ObjectColor) ;
            pDC->FillRect(m_ObjectRect,&BrushBack);
        }
        pOldFont = pDC->SelectObject(&NewFont);
        pOldPen = pDC->SelectObject(&SolidPen);
        //Draw rectangle:
        pDC->MoveTo(m_ObjectRect.left,m_ObjectRect.top);
        pDC->LineTo(m_ObjectRect.right,m_ObjectRect.top);
        pDC->LineTo(m_ObjectRect.right,m_ObjectRect.bottom);
        pDC->LineTo(m_ObjectRect.left,m_ObjectRect.bottom);
        pDC->LineTo(m_ObjectRect.left,m_ObjectRect.top);
        int iPrevMode = pDC->SetBkMode(TRANSPARENT);
        CRect rectBitmap(m_ObjectRect.left+2,m_ObjectRect.top+5,
                         m_ObjectRect.left+2+m_BitmapSize.cx,
                         m_ObjectRect.top+6+m_BitmapSize.cy);
        int SeriesCount = m_pParent->GetSeriesCount();
        for (int i=0;i<SeriesCount;i++)
        {
            CChartSerie* pSerie = m_pParent->GetSerie(i);
            if ( (pSerie->GetName() == _T("")) || !pSerie->IsVisible() )
                continue;
            int MaxHeight = 0;
            CSize TextSize = pDC->GetTextExtent(pSerie->GetName().c_str());
            if (TextSize.cy > m_BitmapSize.cy)
            {
                pDC->ExtTextOut(rectBitmap.right+4,rectBitmap.top,ETO_CLIPPED,NULL,pSerie->GetName().c_str(),NULL);
                CRect rectTemp(rectBitmap);
                int YOffset = TextSize.cy/2 - rectBitmap.Height()/2;
                rectTemp.OffsetRect(0,YOffset);
                pSerie->DrawLegend(pDC,rectTemp);
                MaxHeight = TextSize.cy;
            }
            else
            {
                int YOffset = rectBitmap.CenterPoint().y - TextSize.cy/2;
                pDC->ExtTextOut(rectBitmap.right+4,YOffset,ETO_CLIPPED,NULL,pSerie->GetName().c_str(),NULL);
                MaxHeight = m_BitmapSize.cy;
                pSerie->DrawLegend(pDC,rectBitmap);
            }
            
            if (!m_bIsHorizontal)
                rectBitmap.OffsetRect(0,MaxHeight+2);
            else
                rectBitmap.OffsetRect(m_BitmapSize.cx+4+TextSize.cx+10,0);
        }
        pDC->SetBkMode(iPrevMode);
        pDC->SelectObject(pOldFont);
        DeleteObject(NewFont);
        pDC->SelectObject(pOldPen);
        DeleteObject(SolidPen);
    }

    ClipArea函数的作用是将ChartLegend与波形绘制区域分离开,其中rcControl表示的是绘制波形的区域,m_ObjectRect表示的是绘制ChartLegend的区域。UpdatePosition函数用来在当前绘制区域里面计算ChartLegend所处的位置并记录下该位置。Draw函数用来绘制ChartLegend控件,调用CChartSeries类的DrawLegend用来绘制ChartLegend里面的波形图像信息。 

    作者:常想一二
    出处:http://www.cnblogs.com/wolfmvp/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    Java对象初始化
    some tool collections
    链接、单选按钮虚线框与focus:this.blur()与outline
    火狐拓展开发 基础知识
    Multidimensional Array And an Array of Arrays
    Byte Array to Hexadecimal String
    Comparer<T> IComparer<T> IComparable<T>
    Little Puzzlers–List All Anagrams in a Word
    JavaScript-Curry
    OOP in JS Public/Private Variables and Methods
  • 原文地址:https://www.cnblogs.com/wolfmvp/p/7206700.html
Copyright © 2011-2022 走看看