You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Visual C++绘制XY数据图的最简程序示例(光谱仪应用)

Visual C++ XY数据图绘制示例(光谱仪用)

以下是基于MFC的极简XY数据图实现,仅保留核心绘图功能,方便你后续扩展COM端口读取、异步线程等逻辑:

实现步骤

  1. 创建一个MFC单文档应用程序(项目名比如SpectroChart)
  2. 在视图类(比如CSpectroChartView)的OnDraw函数中替换为以下代码:
void CSpectroChartView::OnDraw(CDC* pDC)
{
    CSpectroChartDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // 获取客户区尺寸
    CRect clientRect;
    GetClientRect(&clientRect);
    int nWidth = clientRect.Width();
    int nHeight = clientRect.Height();

    // 绘图区域边距
    const int nMargin = 50;
    CRect plotRect(nMargin, nMargin, nWidth - nMargin, nHeight - nMargin);

    // 绘制坐标轴
    pDC->MoveTo(plotRect.left, plotRect.bottom);
    pDC->LineTo(plotRect.right, plotRect.bottom); // X轴
    pDC->MoveTo(plotRect.left, plotRect.bottom);
    pDC->LineTo(plotRect.left, plotRect.top); // Y轴

    // 绘制网格线(可选)
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(128, 128, 128));
    int nXGridCount = 10;
    int nYGridCount = 8;
    for (int i = 1; i < nXGridCount; i++)
    {
        int x = plotRect.left + (plotRect.Width() * i) / nXGridCount;
        pDC->MoveTo(x, plotRect.top);
        pDC->LineTo(x, plotRect.bottom);
        // 绘制X轴刻度标签
        CString strLabel;
        strLabel.Format(_T("%.1f"), (double)i * 100 / nXGridCount); // 模拟波长刻度
        pDC->TextOut(x - 15, plotRect.bottom + 5, strLabel);
    }
    for (int i = 1; i < nYGridCount; i++)
    {
        int y = plotRect.bottom - (plotRect.Height() * i) / nYGridCount;
        pDC->MoveTo(plotRect.left, y);
        pDC->LineTo(plotRect.right, y);
        // 绘制Y轴刻度标签
        CString strLabel;
        strLabel.Format(_T("%.1f"), (double)i * 1.0 / nYGridCount); // 模拟强度刻度
        pDC->TextOut(plotRect.left - 40, y - 10, strLabel);
    }

    // 生成模拟光谱数据(替换为你的真实数据)
    const int nDataCount = 100;
    double dXData[nDataCount];
    double dYData[nDataCount];
    for (int i = 0; i < nDataCount; i++)
    {
        dXData[i] = (double)i * 100 / nDataCount; // 模拟0-100nm波长
        dYData[i] = 0.8 * sin(dXData[i] * 0.1) + 0.1 * rand() / RAND_MAX; // 模拟光谱曲线
    }

    // 转换数据点为屏幕坐标并绘制曲线
    pDC->SetPen(CreatePen(PS_SOLID, 2, RGB(255, 0, 0)));
    POINT points[nDataCount];
    for (int i = 0; i < nDataCount; i++)
    {
        // X坐标映射:数据范围[0,100] → 绘图区域宽度
        points[i].x = plotRect.left + (int)((dXData[i] / 100.0) * plotRect.Width());
        // Y坐标映射:数据范围[0,1] → 绘图区域高度(注意Y轴向下为正,所以反转)
        points[i].y = plotRect.bottom - (int)((dYData[i] / 1.0) * plotRect.Height());
    }
    pDC->Polyline(points, nDataCount);

    // 绘制坐标轴标题
    pDC->SetTextColor(RGB(0, 0, 0));
    pDC->TextOut(plotRect.right / 2 - 20, plotRect.bottom + 20, _T("波长(nm)"));
    pDC->TextOut(plotRect.left - 30, plotRect.top / 2, _T("强度"));
}

关键说明

  • 核心逻辑:通过CDC类的绘图函数实现坐标轴、网格、曲线的绘制
  • 坐标映射:将光谱数据的数值范围转换为屏幕像素坐标,适配窗口大小
  • 模拟数据:当前用正弦波+随机噪声模拟光谱曲线,你后续只需替换为从COM端口读取的真实数据
  • 扩展方向:
    • 添加异步线程读取COM端口数据,存储到文档类的全局数据结构中
    • 线程中调用Invalidate()触发视图重绘,更新图表
    • 后续可添加按钮、输入框等控件,通过MFC消息机制控制数据读取

内容的提问来源于stack exchange,提问作者DrM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:26:17