小弟向各位高手请教一个问题,我现在想将从串行口读出的数据在x,y的坐标轴上用图像来表示,比如说,在坐标轴平面内能显示一个一个数字的坐标点,或者能将此点连成线,数字是从0到10的带浮点的正数,请问怎么实现。
串口连接方面我已经搞定了,现在就是最后不知道怎么将这些数据可视化,希望高手能指点一下,小弟在此感谢不已

解决方案 »

  1.   

    你是要画出这些点的图形,还是显示这些点的坐标数据?如果是前真可以采用 CDC的DrawPoint 在屏幕上画点。
    如果是后者就更简单了 用CListCtrl控件插入两列,将坐标数据插入显示就行了。
      

  2.   

    自己做比较麻烦,需要实现x/y轴控制,打印控制,别的就好说了,在DC上画点,折线,方图
    /////////////////////////////////
    void CElysiumChart::DrawAxes(CDC& dc) const
    {
    VALIDATE;
    ASSERT_VALID(&dc);
    _ASSERTE(CElysiumChart::Pie != m_eGraphType); dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT)); // Draw y axis.
    dc.MoveTo(m_ptOrigin);  
    VERIFY(dc.LineTo(m_ptOrigin.x, m_ptOrigin.y - m_nYAxisHeight)); // Draw x axis.
    dc.MoveTo(m_ptOrigin);   if (m_saLegendLabels.GetSize()) { VERIFY(dc.LineTo(m_ptOrigin.x + 
    (m_nXAxisWidth - m_rcLegend.Width() - (GAP_PIXELS * 2)), 
    m_ptOrigin.y));
    }
    else {
    VERIFY(dc.LineTo(m_ptOrigin.x + m_nXAxisWidth, m_ptOrigin.y));
    } // Create the y-axis label font and draw it.
    CFont fontYAxes; VERIFY(fontYAxes.CreateFont( 
    /* nHeight */ m_rectArea.Width() / 10 / Y_AXIS_LABEL_DIVISOR,
    /* nWidth */ 0, /* nEscapement */ 90 * 10, /* nOrientation */ 0,
    /* nWeight */ FW_DONTCARE, /* bItalic */ false, /* bUnderline */ false,
    /* cStrikeOut */ 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
    CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_DONTCARE, 
    "Arial")); CFont* pFontOld = static_cast<CFont*> (dc.SelectObject(&fontYAxes));
    ASSERT_VALID(pFontOld);
    CSize sizYLabel(dc.GetTextExtent(m_sYAxisLabel));
    VERIFY(dc.TextOut(GAP_PIXELS, (m_rectArea.Height() - sizYLabel.cy) / 2,
    m_sYAxisLabel)); // Create the x-axis label font and draw it.
    CFont fontXAxes;
    VERIFY(fontXAxes.CreatePointFont(m_rectArea.Width() / X_AXIS_LABEL_DIVISOR,
    "Arial", &dc));
    VERIFY(dc.SelectObject(&fontXAxes));
    CSize sizXLabel(dc.GetTextExtent(m_sXAxisLabel)); VERIFY(dc.TextOut(m_ptOrigin.x + (m_nXAxisWidth - sizXLabel.cx) / 2,
    m_rectArea.Height() - GAP_PIXELS - sizXLabel.cy, m_sXAxisLabel)); // We hardwire TITLE_DIVISOR y-axis ticks here for simplicity.
    int nTickCount(min(Y_AXIS_MAX_TICK_COUNT, GetMaxDataValue()));
    int nTickSpace(m_nYAxisHeight / (nTickCount+1)); for (int nTick = 0; nTick < nTickCount; ++nTick) {
    int nTickYLocation(m_ptOrigin.y - (nTickSpace * (nTick + 1)));
    dc.MoveTo(m_ptOrigin.x - TICK_PIXELS, nTickYLocation);
    VERIFY(dc.LineTo(m_ptOrigin.x + TICK_PIXELS, nTickYLocation)); // Draw tick label.
    CString sTickLabel;
    sTickLabel.Format("%d", (GetMaxDataValue() * (nTick + 1)) / nTickCount);
    CSize sizTickLabel(dc.GetTextExtent(sTickLabel));

    VERIFY(dc.TextOut(m_ptOrigin.x - GAP_PIXELS - sizTickLabel.cx - TICK_PIXELS,
    nTickYLocation - sizTickLabel.cy, sTickLabel));
    } // Draw X axis tick s.
    POSITION pos(m_olElysiumChartSeries.GetHeadPosition());
    int nSeries(0); while (pos) {

    CElysiumChartSeries* pSeries =
    static_cast<CElysiumChartSeries*> (m_olElysiumChartSeries.GetNext(pos));
    ASSERT_VALID(pSeries); // Ignore unpopulated series if bar chart.
    if (m_eGraphType != CElysiumChart::Bar  || 
    0 < pSeries->GetNonZeroElementCount()) { // Get the spacing of the series.
    _ASSERTE(GetNonZeroSeriesCount()  &&  "Div by zero coming");
    // int nSeriesSpace(0);
    DWORD nSeriesSpace(0); if (m_saLegendLabels.GetSize()) { nSeriesSpace =
    (m_nXAxisWidth - m_rcLegend.Width() - (GAP_PIXELS * 2)) /
    (m_eGraphType == CElysiumChart::Bar ?
    GetNonZeroSeriesCount() : m_olElysiumChartSeries.GetCount());//hyh
    }
    else {
    nSeriesSpace = m_nXAxisWidth / (m_eGraphType == CElysiumChart::Bar ?
    GetNonZeroSeriesCount() : m_olElysiumChartSeries.GetCount());//hyh
    }// int nTickXLocation(m_ptOrigin.x + ((nSeries + 1) * nSeriesSpace) -
    DWORD nTickXLocation(m_ptOrigin.x + ((nSeries + 1) * nSeriesSpace) -
    (nSeriesSpace / 2)); dc.MoveTo(nTickXLocation, m_ptOrigin.y - TICK_PIXELS);
    VERIFY(dc.LineTo(nTickXLocation, m_ptOrigin.y + TICK_PIXELS)); // Draw x-axis tick label.
    CString sTickLabel(pSeries->GetLabel());
    CSize sizTickLabel(dc.GetTextExtent(sTickLabel)); VERIFY(dc.TextOut(nTickXLocation - (sizTickLabel.cx / 2),
    m_ptOrigin.y + sizTickLabel.cy, sTickLabel)); ++nSeries;
    }
    } VERIFY(dc.SelectObject(pFontOld));
    }
      

  3.   


    //
    void CElysiumChart::DrawSeriesBar(CDC& dc) const
    {
    VALIDATE;
    ASSERT_VALID(&dc); // How much space does each series get (includes interseries space)?
    // We ignore series whose members are all zero.
    int nSeriesSpace(0); if (m_saLegendLabels.GetSize()) { nSeriesSpace = (m_nXAxisWidth - m_rcLegend.Width() - (GAP_PIXELS * 2)) /
    GetNonZeroSeriesCount();
    }
    else {
    nSeriesSpace = m_nXAxisWidth / GetNonZeroSeriesCount();
    } // Determine width of bars.  Data points with a value of zero are assumed 
    // to be empty.  This is a bad assumption.
    int nBarWidth(nSeriesSpace / GetMaxNonZeroSeriesSize()); if (1 < GetNonZeroSeriesCount()) {
    nBarWidth = (int) ((double) nBarWidth * INTERSERIES_PERCENT_USED);
    } // This is the width of the largest series (no interseries space).
    int nMaxSeriesPlotSize(GetMaxNonZeroSeriesSize() * nBarWidth); // Iterate the series.
    POSITION pos(m_olElysiumChartSeries.GetHeadPosition());
    int nSeries(0); while (pos) {

    CElysiumChartSeries* pSeries =
    static_cast<CElysiumChartSeries*> (m_olElysiumChartSeries.GetNext(pos));
    ASSERT_VALID(pSeries); // Ignore unpopulated series.
    if (0 < pSeries->GetNonZeroElementCount()) { // Draw each bar; empty bars are not drawn.
    int nRunningLeft(m_ptOrigin.x + ((nSeries + 1) * nSeriesSpace) - 
    nMaxSeriesPlotSize); for (int nGroup = 0; nGroup < GetMaxSeriesSize(); ++nGroup) { if (pSeries->GetData(nGroup)) { CRect rcBar;
    rcBar.left = nRunningLeft; 
    rcBar.top = m_ptOrigin.y - (m_nYAxisHeight *
    // pSeries->GetData(nGroup)) / (GetMaxDataValue()+1);
    pSeries->GetData(nGroup)) / (GetMaxDataValue());
    rcBar.right = rcBar.left + nBarWidth;
    rcBar.bottom = m_ptOrigin.y; pSeries->SetTipRegion(nGroup, rcBar); COLORREF crBar(m_dwaColors.GetAt(nGroup));
    CBrush br(crBar);
    CBrush* pBrushOld = dc.SelectObject(&br);
    ASSERT_VALID(pBrushOld); VERIFY(dc.Rectangle(rcBar));
    dc.SelectObject(&pBrushOld); nRunningLeft += nBarWidth;
    }
    } ++nSeries;
    }
    }
    }//
    void CElysiumChart::DrawSeriesLine(CDC& dc) const
    {
    VALIDATE;
    ASSERT_VALID(&dc); // Iterate the groups.
    CPoint ptLastLoc(0,0); for (int nGroup = 0; nGroup < GetMaxSeriesSize(); nGroup++) { // How much space does each series get (includes interseries space)?
    int nSeriesSpace(0); if (m_saLegendLabels.GetSize()) { nSeriesSpace = (m_nXAxisWidth - m_rcLegend.Width() - (GAP_PIXELS * 2)) /
    m_olElysiumChartSeries.GetCount();
    }
    else {
    nSeriesSpace = m_nXAxisWidth / m_olElysiumChartSeries.GetCount();
    } // Determine width of bars.
    int nBarWidth(nSeriesSpace / GetMaxSeriesSize()); if (1 < m_olElysiumChartSeries.GetCount()) {
    nBarWidth = (int) ((double) nBarWidth * INTERSERIES_PERCENT_USED);
    } // This is the width of the largest series (no interseries space).
    int nMaxSeriesPlotSize(GetMaxSeriesSize() * nBarWidth); // Iterate the series.
    POSITION pos(m_olElysiumChartSeries.GetHeadPosition());

    for (int nSeries = 0; nSeries < m_olElysiumChartSeries.GetCount(); ++nSeries) { CElysiumChartSeries* pSeries =
    static_cast<CElysiumChartSeries*> (m_olElysiumChartSeries.GetNext(pos));
    ASSERT_VALID(pSeries);

    // Get x and y location of center of ellipse.
    CPoint ptLoc(0,0);

    ptLoc.x = m_ptOrigin.x + (((nSeries + 1) * nSeriesSpace) - 
    (nSeriesSpace / 2));
    double dLineHeight(pSeries->GetData(nGroup) * m_nYAxisHeight /
    // (GetMaxDataValue()+1));//lijt
    (GetMaxDataValue()));

    ptLoc.y = (int) ((double) m_ptOrigin.y - dLineHeight);

    // Build objects.
    COLORREF crLine(m_dwaColors.GetAt(nGroup));
    CBrush br(crLine);
    CBrush* pBrushOld = dc.SelectObject(&br);
    ASSERT_VALID(pBrushOld); // Draw line back to last data member.
    if (nSeries > 0) {
    CPen penLine(PS_SOLID, 1, crLine);
    CPen* pPenOld = dc.SelectObject(&penLine);
    ASSERT_VALID(pPenOld); dc.MoveTo(ptLastLoc.x + 2, ptLastLoc.y - 1);
    VERIFY(dc.LineTo(ptLoc.x - 3, ptLoc.y - 1));
    VERIFY(dc.SelectObject(pPenOld));
    } // Now draw ellipse.
    CRect rcEllipse(ptLoc.x - 3, ptLoc.y - 3, ptLoc.x + 3, ptLoc.y + 3);
    VERIFY(dc.Ellipse(rcEllipse)); pSeries->SetTipRegion(nGroup, rcEllipse);
    dc.SelectObject(&pBrushOld);
    ptLastLoc = ptLoc;
    }
    }
    }