MsChart实现无闪烁动态曲线(MFC)


       实现的原理:MSChart如果要实现动态的曲线就只能在设置的定时器中根据RowCount,到一定的列数后在最后一列插入新一列(m_Chart.GetDataGrid().InsertRows),将最早出现的那一列删除(m_Chart.GetDataGrid().DeleteRows)。对于无闪烁刷新的实现类似于一般MFC画图中创建双缓冲画图避免屏幕闪烁的方法,这里是用CStatic动态创建一个Picture Control图像控件,将它设定和要画的MSChart一样大,然后把mschart的内容利用m_Chart.EditCopy()复制到剪贴板,然后再在picture control中显示出来。

下面是全部的实现的代码:

MSChart需要在view的oncreate中创建出mschart:

int CRTDBView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    CRect rc;
    GetClientRect(&rc);
    VERIFY(m_Picture.Create(_T(""),SS_BITMAP|WS_CHILD|WS_EX_TRANSPARENT| WS_VISIBLE,CRect(0,0,1200,600),this,IDC_PICTURE));
    if(!m_Chart.Create(_T("RTDB"),WS_CHILD| WS_VISIBLE, CRect(0,0,1200,600), this, 10))
        return -1;

    
    return 0;
}

在ONSIZE中设置mschart的位置:

void CRTDBView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    if( m_Chart.GetSafeHwnd())
        m_Chart.MoveWindow( 0, 0, cx, cy );    
}

下面是主要实现部分的代码了,InitChart函数实现了mschart的背景、标题、XY坐标刻度以及颜色字体大小、曲线设定颜色以及数据点的显示等。主要是chart的初始化。

void CRTDBView::InitChart(void)
{
    // 设置标题
    m_Chart.SetTitleText(_T("RTDB"));

    // 设置标题颜色
    m_Chart.GetTitle().GetVtFont().GetVtColor().Set(0,255,0);

    // 改变字体大小
    m_Chart.GetTitle().GetVtFont().SetSize(14);

    // 改变背景色
    m_Chart.GetBackdrop().GetFill().SetStyle(1);
    m_Chart.GetBackdrop().GetFill().GetBrush().GetFillColor().Set(0,0,0);

    // 显示图例
    m_Chart.SetShowLegend(TRUE);
    m_Chart.SetColumn(1);
    m_Chart.SetColumnLabel((LPCTSTR)_T("point num"));

    // 设置图例颜色
    m_Chart.GetLegend().GetVtFont().GetVtColor() .Set(0,255,0);

    // 初始化设置row
    m_Chart.SetRowCount(15);
    m_Chart.SetRow(1);
    m_Chart.SetRowLabel((LPCTSTR)_T(""));
    for (UINT i=1;i<=m_Chart.GetRowCount();i++)
    {
        m_Chart.GetDataGrid().SetData(i,1,0,0);
    }

    
    // 显示类型 组合的方式 0为3D 1为2D
    m_Chart.SetChartType(1|2);
    m_Chart.SetSeriesType(11);

    // 栈模式
    m_Chart.SetStacking(FALSE);

    VARIANT var;

    // X、Y轴名称
    m_Chart.GetPlot().GetAxis(0,var).GetAxisTitle().SetText(_T("时间(s)"));            // X轴名称
    m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().SetText(_T("点数"));    // Y轴名称

    // X轴设置
    m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetAuto(FALSE);            // 不自动标注X轴刻度
    m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerLabel(1);// 每刻度一个标注
    m_Chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerTick(1); // 每刻度一个刻度线

    // X轴每刻度竖线,0为不设置、1为设置
    m_Chart.GetPlot().GetAxis(0,var).GetAxisGrid().GetMajorPen().SetStyle(0);

    // 曲线个数
    m_Chart.SetColumnCount(1); 

    // 曲线颜色
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().GetVtColor().Set(0,255,0);

    // 曲线宽度(对点线图有效)
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().SetWidth(30);

    // 数据点类型显示数据值的模式(对柱柱状图和点线图有效)
    // 0: 不显示    1: 显示在柱状图外
    // 2: 显示在柱状图内上方    3: 显示在柱状图内中间    4: 显示在柱状图内下方
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1).GetDataPointLabel().SetLocationType(1);

    // 设置曲线上数据点颜色
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1).GetDataPointLabel().GetVtFont().GetVtColor().Set(0,255,0);

    // 曲线设置十字标记
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetSeriesMarker().SetAuto(FALSE); // MUST!!
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
        .GetMarker().SetVisible(TRUE);

    // 0横杠,1十字,2是叉,3是星,4是圆圈,5是方块,6菱形
    // 7三角,8倒三角,9实心点,10实心方块,11实心菱形,12实心三角,13实心倒三角,14泛光的点
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
        .GetMarker().SetStyle(1); 

    // 设置曲线上十字颜色
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
        .GetMarker().GetFillColor().Set(255,0,0);
    m_Chart.GetPlot().GetSeriesCollection().GetItem(1).GetDataPoints().GetItem(-1)
        .GetMarker().GetPen().GetVtColor().Set(255,0,0);

    // 设定坐标轴颜色
    m_Chart.GetPlot().GetAxis(0,var).GetPen().GetVtColor().Set(0,255,0);
    m_Chart.GetPlot().GetAxis(1,var).GetPen().GetVtColor().Set(0,255,0);
    m_Chart.GetPlot().GetAxis(2,var).GetPen().GetVtColor().Set(0,255,0);

    // 设置坐标轴轴刻度值颜色
    m_Chart.GetPlot().GetAxis(1,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);
    m_Chart.GetPlot().GetAxis(0,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);
    m_Chart.GetPlot().GetAxis(2,var).GetLabels().GetItem(1).GetVtFont().GetVtColor().Set(0,255,0);

    // 设定坐标轴宽度
    m_Chart.GetPlot().GetAxis(0,var).GetPen().SetWidth(30);
    m_Chart.GetPlot().GetAxis(1,var).GetPen().SetWidth(30);

    //设定X、Y轴标题颜色
    m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().GetVtColor().Set(0,255,0);
    m_Chart.GetPlot().GetAxis(0,var).GetAxisTitle().GetVtFont().GetVtColor().Set(0,255,0);

    // 设置Y轴坐标横线颜色
    m_Chart.GetPlot().GetAxis(1,var).GetAxisGrid().GetMajorPen().GetVtColor().Set(0,255,0);

    // 设置Y轴
    m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetAuto(FALSE);    // 不自动标注Y轴刻度
    m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMaximum(100);    // Y轴最大刻度
    m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMinimum(-100);        // Y轴最小刻度
    m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMajorDivision(10);    // Y轴刻度5等分
    m_Chart.GetPlot().GetAxis(1,var).GetValueScale().SetMinorDivision(1);    // 每刻度一个刻度线

    // 设置Y轴名称大小、类型
    m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().SetStyle(0);
    m_Chart.GetPlot().GetAxis(1,var).GetAxisTitle().GetVtFont().SetSize(12);

    // 隐藏第二Y轴
    m_Chart.GetPlot().GetAxis(2,var).GetAxisScale().SetHide(FALSE);

    // 刷新
    m_Chart.Refresh();

}

最后在OnTimer函数中是动态曲线的实现以及无闪烁的实现:

void CRTDBView::OnTimer(UINT_PTR nIDEvent)
{
    
    //TODO: Add your message handler code here and/or call default
    m_Picture.BringWindowToTop(); 
    m_Picture.ShowWindow(SW_SHOW);
    HANDLE hDib;
    pDC = GetDlgItem(IDC_PICTURE)->GetDC();
    int m_rowPos=m_Chart.GetRowCount()+1;
    
    // 插入新一列
    m_Chart.GetDataGrid().InsertRows(m_rowPos,1);
    m_Chart.SetRow(m_rowPos);
    char buf[32];
    for (int i=0;i<sizeof(buf);i++)
    {
        buf[i]=0;
    }
    sprintf(buf, "%d",m_iCount);

    // X轴坐标值
    m_Chart.SetRowLabel((LPCTSTR)CString(buf));
    
    // 数据设置(随机)
    m_Chart.GetDataGrid().SetData(m_rowPos,1,rand() * 100 / RAND_MAX,0);
    
    // 大于15列就开始删除最后一列
    if (m_Chart.GetRowCount()>15)
    {
        m_Chart.GetDataGrid().DeleteRows(m_rowPos-15,1);
    }
    m_iCount++;
   
    // 把更新复制到粘贴板,在picture中显示
    m_Chart.EditCopy(); 
    if(OpenClipboard())
    {
        hDib = GetClipboardData(CF_DIB);  
        CloseClipboard();
    }
    BITMAPINFO* pbi = (BITMAPINFO*)GlobalLock(hDib);
    if (pbi != NULL)
    {
        BYTE* data = (BYTE*)(pbi->bmiColors);
        if (pbi->bmiHeader.biBitCount <= 8)
        {
            int nColor = (pbi->bmiHeader.biClrUsed==0) ?
                1<<(pbi->bmiHeader.biBitCount) : pbi->bmiHeader.biClrUsed; // nColor颜色表中的颜色数
            data += sizeof(RGBQUAD) *nColor;
        }
        StretchDIBits(pDC->GetSafeHdc(),1,1, pbi->bmiHeader.biWidth-1,
            pbi->bmiHeader.biHeight-1,0, 0, pbi->bmiHeader.biWidth,
            pbi->bmiHeader.biHeight, data, pbi, DIB_RGB_COLORS, SRCCOPY);// 显示,我为了保留外面的方框,前面宽度和高度都减了1
        GlobalUnlock(hDib);
    }
    m_Chart.Refresh();
    CView::OnTimer(nIDEvent);
}



  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值