| MFC扩展编程实例3D并列叠加柱形图创建与交互操作 
 三维的柱形图还可以细分很多类别,比如叠加的,簇形的,并列叠加等等。
 当前这个例程实现两个并列叠加显示的三维柱形图,效果如下图:
 
 MFC扩展编程实例3D并列叠加柱形图创建与交互操作   图中两个系列叠加为一根柱形,两柱形为一组并列显示。
 界面上还有按钮可以设置数据标签的显示位置,另一按钮可以设置数据系列的填充渐变样式。
 圆形控件可以对图表进行左右上下等旋转操作。
 例程也实现通过鼠标来交互操作图表,鼠标右键按着不放可以上下左右滚动图表。
 键盘左shift按着,鼠标左键可以平移图表,鼠标中键可以缩放图表。
 
 下面是实现过程与关键代码。
 创建基于class CMy123View : public CBCGPFormView 的单文档工程,
 视窗对话框界面添加图片控件IDC_ROTATE,IDC_CHART,用于操作图表和显示图表。
 再添加变量与函数与虚函数Create,在Create内初始化变量。
 CBCGPChartCtrl      m_wndChart;
 CBCGPRotationCtrl        m_wndRotate;
 void RotateChart(CBCGPRotationObject::RotationElement hit, double xDelta = 10., double yDelta = 10., double persperctiveDelta = 0.1);
 
 
 复制代码void CMy123View::RotateChart(CBCGPRotationObject::RotationElement hit, double xDelta, double yDelta, double persperctiveDelta)
{
        CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
        if (pChart == NULL)
                return;
        ASSERT_VALID(pChart);
        CBCGPChartDiagram3D* pDiagram3D = pChart->GetDiagram3D();
        if (pDiagram3D == NULL)
                return;
        double xRotation = pDiagram3D->GetXRotation();
        double yRotation = pDiagram3D->GetYRotation();
        double dblPerspectivePercent = pDiagram3D->GetPerspectivePercent();
        switch (hit)
        {
        case CBCGPRotationObject::BCGP_ROTATION_RESET:
                pDiagram3D->Reset(TRUE);
                return;
        case CBCGPRotationObject::BCGP_ROTATION_UP:
                yRotation += yDelta;
                break;
        case CBCGPRotationObject::BCGP_ROTATION_DOWN:
                yRotation -= yDelta;
                break;
        case CBCGPRotationObject::BCGP_ROTATION_LEFT:
                xRotation -= xDelta;
                break;
        case CBCGPRotationObject::BCGP_ROTATION_RIGHT:
                xRotation += xDelta;
                break;
        case CBCGPRotationObject::BCGP_ROTATION_NARROW_FIELD_OF_VIEW:
                dblPerspectivePercent -= persperctiveDelta;
                break;
        case CBCGPRotationObject::BCGP_ROTATION_WIDEN_FIELD_OF_VIEW:
                dblPerspectivePercent += persperctiveDelta;
                break;
        }
        pDiagram3D->SetPosition(xRotation, yRotation, dblPerspectivePercent);
        pChart->SetDirty(TRUE,TRUE);
}
在创建图表时,关键代码是设置图表种类与样式,复制代码BOOL CMy123View::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
        BOOL bRst = CBCGPFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);;
        m_wndRotate.SubclassDlgItem(IDC_ROTATE,this);
        m_wndRotate.GetRotationObject()->SetAutorepeatMode(100);
        m_wndRotate.GetRotationObject()->SetColorTheme(CBCGPRotationObject::BCGP_COLOR_THEME_VISUAL_MANAGER);
        m_wndRotate.GetRotationObject()->EnablePart(CBCGPRotationObject::BCGP_ROTATION_CLOCKWISE, FALSE);
        m_wndRotate.GetRotationObject()->EnablePart(CBCGPRotationObject::BCGP_ROTATION_COUNTER_CLOCKWISE, FALSE);
        m_wndRotate.GetRotationObject()->EnableFlatIcons();
        //获取图表指针;
        m_wndChart.SubclassDlgItem(IDC_CHART,this);//子类化图表;
        CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
        pChart->SetChartTitle(_T("3D叠加柱形图"));//图表标题设置;
        pChart->SetThemeOpacity(70);//图表主题透明度设置;
        pChart->EnableMouseTrackingMode(BCGPChartHitInfo::HIT_DIAGRAM);
        BCGPChartCategory category = BCGPChartColumn3D;//图表种类,F12查看全部;
        BCGPChartType type = BCGP_CT_100STACKED;//BCGP_CT_SIMPLE;//BCGP_CT_STACKED;//图表类型,按F12查看全部;
        pChart->SetChartType(category, type);//设置图表类别;
//        pChart->GetDiagram3D()->SetGrouped(TRUE, FALSE);//配合BCGP_CT_SIMPLE可设置为簇状类型图表;
        //设置3D背部与底部;
        DWORD dwoFlags = CBCGPChartDiagram3D::DWO_OUTLINE_ALL;
        dwoFlags |= (CBCGPChartDiagram3D::DWO_DRAW_ALL_WALLS | CBCGPChartDiagram3D::DWO_DRAW_FLOOR);
        pChart->GetDiagram3D()->SetDrawWallOptions((CBCGPChartDiagram3D::DrawWallOptions)dwoFlags);
        pChart->GetDiagram3D()->SetThickWallsAndFloor(true);
        //创建4个数据系列;
        CBCGPChartBarSeries* pBarSeries1 = DYNAMIC_DOWNCAST(CBCGPChartBarSeries, pChart->CreateSeries(_T("能源")));
        CBCGPChartBarSeries* pBarSeries2 = DYNAMIC_DOWNCAST(CBCGPChartBarSeries, pChart->CreateSeries(_T("税收")));
        CBCGPChartBarSeries* pBarSeries3 = DYNAMIC_DOWNCAST(CBCGPChartBarSeries, pChart->CreateSeries(_T("维护")));
        CBCGPChartBarSeries* pBarSeries4 = DYNAMIC_DOWNCAST(CBCGPChartBarSeries, pChart->CreateSeries(_T("其他")));
        //将系列设置相同组ID,可实现并列显示;
        pBarSeries1->SetGroupID(0);
        pBarSeries2->SetGroupID(0);
        pBarSeries3->SetGroupID(1);
        pBarSeries4->SetGroupID(1);
        
        //向四个数据系列添加数据;
        srand((unsigned)time(NULL));
        COleDateTime now = COleDateTime::GetCurrentTime();
        CString sYear;
        for(int i=5;i>0;i--)
        {
                sYear.Format(_T("%d"), now.GetYear() - i);
                pBarSeries1->AddDataPoint(sYear, rand()%20+1);
        }
        pBarSeries2->AddDataPoint(10);
        pBarSeries2->AddDataPoint(12);
        pBarSeries2->AddDataPoint(15);
        pBarSeries2->AddDataPoint(17);
        pBarSeries2->AddDataPoint(12);
        pBarSeries3->AddDataPoint(5);
        pBarSeries3->AddDataPoint(7);
        pBarSeries3->AddDataPoint(11);
        pBarSeries3->AddDataPoint(14);
        pBarSeries3->AddDataPoint(19);
        pBarSeries4->AddDataPoint(2);
        pBarSeries4->AddDataPoint(3);
        pBarSeries4->AddDataPoint(5);
        pBarSeries4->AddDataPoint(3);
        pBarSeries4->AddDataPoint(2);
        //添加添加到布局管理器统一管理布局;
        if (GetLayout() == NULL)
                return bRst;
        CBCGPStaticLayout* pLayout = (CBCGPStaticLayout*)GetLayout();
        if (pLayout == NULL)
                return bRst;
        pLayout->AddAnchor(m_wndChart.GetDlgCtrlID(), CBCGPStaticLayout::e_MoveTypeNone, CBCGPStaticLayout::e_SizeTypeBoth);
        //
        return bRst;
}
BCGPChartCategory category = BCGPChartColumn3D;//图表种类,F12查看全部;
 BCGPChartType type = BCGP_CT_100STACKED;//BCGP_CT_SIMPLE;//BCGP_CT_STACKED;//图表类型,按F12查看全部;
 pChart->SetChartType(category, type);//设置图表类别;
 如果还想实现并列显示,可以type设置为叠加样式BCGP_CT_STACKED,BCGP_CT_100STACKED,再对数据系列分组。
 pBarSeries1->SetGroupID(0);
 pBarSeries2->SetGroupID(0);
 pBarSeries3->SetGroupID(1);
 pBarSeries4->SetGroupID(1);
 例程有用到布局管理,所以在视窗类构造函数中调用函数EnableLayout()开启。
 这样图表就创建好了。
 
 然后是对图表操作控件m_wndRotate点击函数响应,关联函数OnRotate。
 
 这样通过m_wndRotate控件就可以操作图表了。复制代码void CMy123View::OnRotate() 
{
        RotateChart(m_wndRotate.GetRotationObject()->GetClicked());
}
 最后是实现鼠标交互操作,关联鼠标点击与平移函数。
 通过上两函数来实现图表交互操作。
 afx_msg LRESULT OnMouseTrack(WPARAM wp, LPARAM lp);
 afx_msg LRESULT OnMouseDown(WPARAM wp, LPARAM lp);
 
 ON_REGISTERED_MESSAGE(BCGM_ON_CHART_MOUSE_TRACK, OnMouseTrack)
 ON_REGISTERED_MESSAGE(BCGM_ON_CHART_MOUSE_DOWN, OnMouseDown)
 
 
 例程用到的MFC扩展库可以在网站搜索下载,内带有使用教程。复制代码CPoint ptOrigin;
LRESULT CMy123View::OnMouseDown(WPARAM /*wp*/, LPARAM lp)
{
        BCGPChartHitInfo* pHitInfo = (BCGPChartHitInfo*)lp;
        if(pHitInfo->m_nMouseButton ==0)
                ptOrigin = pHitInfo->m_ptHit;
        return false;
}
LRESULT CMy123View::OnMouseTrack(WPARAM /*wp*/, LPARAM lp)
{
        CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
        if(pChart == NULL)
                return false;
        BCGPChartHitInfo* pHitInfo = (BCGPChartHitInfo*)lp;
        if(pHitInfo->m_ptHit == CBCGPPoint(-1, -1))
                return false;
        if(0x8000 & GetKeyState(VK_RBUTTON ) )
        {
                CString sText;
                CBCGPPoint pt = pHitInfo->m_ptHit;
                double p = sqrt( pow(pt.x-ptOrigin.x,2)+pow(pt.y-ptOrigin.y,2) );
                if(p<10)
                        return false;
                double dbAng = asin( (pt.y-ptOrigin.y) /p)*(180.0 / 3.1415926);
                
                //dbAng转换为对应逆时针一圈角度(0-360);
                if( pt.x>ptOrigin.x)
                {
                        if(dbAng<0)
                                dbAng = abs(dbAng);
                        else
                                dbAng= abs(360-dbAng);
                }
                else
                {
                        if(dbAng<0)
                                dbAng = 180+dbAng;
                        else
                                dbAng = 180+dbAng;
                }
                sText.Format(_T("%.03lf"),dbAng);
                SetDlgItemText(IDC_EDIT1,sText);
                //
                int nDir=0,nDel=360/16;
                if(0<=dbAng && dbAng<nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_LEFT;
                else if(nDel<=dbAng && dbAng<3*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_NONE;//BCGP_ROTATION_NARROW_FIELD_OF_VIEW;
                else if(3*nDel<=dbAng && dbAng<5*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_DOWN;
                else if(5*nDel<=dbAng && dbAng<7*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_NONE;//BCGP_ROTATION_CLOCKWISE;
                else if(7*nDel<=dbAng && dbAng<9*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_RIGHT;
                else if(9*nDel<=dbAng && dbAng<11*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_NONE;//BCGP_ROTATION_WIDEN_FIELD_OF_VIEW;
                else if(11*nDel<=dbAng && dbAng<13*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_UP;
                else if(13*nDel<=dbAng && dbAng<15*nDel)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_NONE;//BCGP_ROTATION_COUNTER_CLOCKWISE;
                else if(15*nDel<=dbAng && dbAng<360)
                        nDir = CBCGPRotationObject::BCGP_ROTATION_LEFT;
                RotateChart((CBCGPRotationObject::RotationElement)nDir,10.0,10.0);
        }
        if(0x8000 & GetKeyState(VK_LSHIFT ))
                pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_WHEEL_PAN);
        else
                pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_NONE);
        ptOrigin = pHitInfo->m_ptHit;
        return false;
}
例程源代码下载地址:
 
 
   如果您认可,可联系功能定制! 如果您着急,充值会员可直接联系发您资料!    
 
 
 |