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

MFC应用中如何实现两个图表区域的光标与坐标轴同步

实现方案

1. 定义全局自定义消息和通知结构体

先在公共头文件(比如stdafx.h或者单独的公共定义头文件)里加如下代码:

// 自定义消息定义
#define WM_CHART_MOUSEMOVE (WM_USER + 101)
#define WM_CHART_AXIS_CHANGED (WM_USER + 102)

// 图表通知数据结构体
struct ChartNotifyData {
    double dataX;      // 鼠标对应的数据坐标X
    double dataY;      // 鼠标对应的数据坐标Y
    double axisXMin;   // X轴最小值
    double axisXMax;   // X轴最大值
    double axisYMin;   // Y轴最小值
    double axisYMax;   // Y轴最大值
};

2. 改造CMyChart自定义控件类

MyChart.h 新增内容

class CMyChart : public CWnd // 原有继承关系保持不变即可
{
    // 原有代码全部保留,新增如下内容
public:
    // 外部调用接口:设置自定义光标位置(数据坐标)
    void SetCustomCursorPos(double x, double y);
    // 外部调用接口:设置坐标轴范围
    void SetAxisRange(double xMin, double xMax, double yMin, double yMax);
    // 内部方法:客户区坐标转数据坐标,需根据你CMyChart的内部实现补全逻辑
    void ClientPointToData(CPoint clientPt, double& outX, double& outY);
    // 内部方法:获取当前坐标轴范围,需根据你CMyChart的内部实现补全逻辑
    void GetCurrentAxisRange(double& outXMin, double& outXMax, double& outYMin, double& outYMax);

protected:
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    // 坐标轴修改后调用该方法触发同步通知
    void NotifyAxisChange();
    DECLARE_MESSAGE_MAP()
};

MyChart.cpp 新增内容

BEGIN_MESSAGE_MAP(CMyChart, CWnd)
    ON_WM_MOUSEMOVE()
    // 原有其他消息映射全部保留
END_MESSAGE_MAP()

void CMyChart::OnMouseMove(UINT nFlags, CPoint point)
{
    // 原有鼠标移动逻辑全部保留,新增如下通知逻辑
    double x, y;
    ClientPointToData(point, x, y);
    
    ChartNotifyData notifyData;
    GetCurrentAxisRange(notifyData.axisXMin, notifyData.axisXMax, notifyData.axisYMin, notifyData.axisYMax);
    notifyData.dataX = x;
    notifyData.dataY = y;
    
    // 发送消息到父窗口(即CMyDlg)
    GetParent()->SendMessage(WM_CHART_MOUSEMOVE, GetDlgCtrlID(), (LPARAM)&notifyData);

    CWnd::OnMouseMove(nFlags, point);
}

void CMyChart::NotifyAxisChange()
{
    ChartNotifyData notifyData;
    GetCurrentAxisRange(notifyData.axisXMin, notifyData.axisXMax, notifyData.axisYMin, notifyData.axisYMax);
    GetParent()->SendMessage(WM_CHART_AXIS_CHANGED, GetDlgCtrlID(), (LPARAM)&notifyData);
}

// 以下两个方法需要根据你CMyChart的内部渲染逻辑补全
void CMyChart::SetCustomCursorPos(double x, double y)
{
    // 实现逻辑:将传入的数据坐标转成当前控件的客户区坐标,在对应位置绘制自定义光标后刷新控件
}
void CMyChart::SetAxisRange(double xMin, double xMax, double yMin, double yMax)
{
    // 实现逻辑:修改当前控件的坐标轴参数为传入值,刷新控件
    // 注意:此处不要调用NotifyAxisChange(),避免触发循环同步
}

3. 改造CMyDlg对话框类

MyDlg.h 新增内容

class CMyDlg : public CDialog
{
    // 原有代码全部保留,新增如下内容
protected:
    afx_msg LRESULT OnChartMouseMove(WPARAM wParam, LPARAM lParam);
    afx_msg LRESULT OnChartAxisChanged(WPARAM wParam, LPARAM lParam);
private:
    BOOL m_bIsSyncing = FALSE; // 同步锁,双重避免循环触发
};

MyDlg.cpp 修改内容

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    ON_MESSAGE(WM_CHART_MOUSEMOVE, &CMyDlg::OnChartMouseMove)
    ON_MESSAGE(WM_CHART_AXIS_CHANGED, &CMyDlg::OnChartAxisChanged)
    // 原有其他消息映射全部保留
END_MESSAGE_MAP()

LRESULT CMyDlg::OnChartMouseMove(WPARAM wParam, LPARAM lParam)
{
    ChartNotifyData* pData = (ChartNotifyData*)lParam;
    int senderId = (int)wParam;

    if (senderId == IDC_CHART_TOP)
    {
        m_ChartBottom.SetCustomCursorPos(pData->dataX, pData->dataY);
    }
    else if (senderId == IDC_CHART_BOTTOM)
    {
        m_ChartTop.SetCustomCursorPos(pData->dataX, pData->dataY);
    }
    return 0;
}

LRESULT CMyDlg::OnChartAxisChanged(WPARAM wParam, LPARAM lParam)
{
    if (m_bIsSyncing) return 0;

    ChartNotifyData* pData = (ChartNotifyData*)lParam;
    int senderId = (int)wParam;

    m_bIsSyncing = TRUE;
    if (senderId == IDC_CHART_TOP)
    {
        m_ChartBottom.SetAxisRange(pData->axisXMin, pData->axisXMax, pData->axisYMin, pData->axisYMax);
    }
    else if (senderId == IDC_CHART_BOTTOM)
    {
        m_ChartTop.SetAxisRange(pData->axisXMin, pData->axisXMax, pData->axisYMin, pData->axisYMax);
    }
    m_bIsSyncing = FALSE;
    return 0;
}

补充说明

你需要在所有修改CMyChart坐标轴的操作(比如缩放、平移、手动修改范围等)执行完成后,调用NotifyAxisChange()方法触发同步通知即可完成双向同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:18:02