MFC 曲线控件






4.90/5 (37投票s)
2004 年 12 月 19 日
4分钟阅读

104077

10173
一篇关于曲线控件的文章。

引言
- 派生自 CWnd,易于使用
- 适应绘图矩形的宽度和高度
- 缩放
- 鼠标坐标追踪
- 通过单击鼠标按钮单选/多选
- 十字线追踪鼠标
- 通过单击鼠标按钮添加或删除曲线上的点
- 通过按下鼠标并移动来编辑曲线上点的垂直值
- 易于移动、偏移或镜像曲线
- 曲线更改时通知控件的拥有者
- 拥有者通过消息处理函数的返回值决定是否修改曲线数据
- Unicode 支持
- 在 Windows 2000, VC 6.0 下以警告级别 4 编译
背景
最近,我想要在一个应用程序中可视化数据。我搜索了互联网并下载了一些曲线控件。其中大多数都很漂亮并且工作良好,但没有一个能按照我想要的方式工作。在阅读了一些控件的源代码后,我决定开发一个能满足我应用程序需求的曲线控件。
类
CCurve
CCurve 类,派生自 CObject,用于存储数据和曲线属性。它不执行数据添加或删除。
- void ShowCurve(BOOL bShow = TRUE);
- BOOL IsVisible();- 设置/获取可视化状态。 
- void Select(BOOL bSelect = TRUE);
- BOOL IsSelected- 设置/获取选中状态。 
- BOOL SetCurveName(CString& strName);
- CString GetCurveName();- 设置/获取曲线名称。 
- void SetCurveColor(COLORREF color);
- COLORREF GetCurveColor();- 设置/获取曲线的颜色。 
- void SetCurveStyle(int iStyle);
- int GetCurveStyle();- 设置/获取曲线的样式。 
- void SetCurveWidth(int nWidth);
- int GetCurveWidth();- 设置/获取曲线的宽度。 
- float Distance(const CPoint& pt1, const CPoint& pt2);- 获取两点之间的距离。 
- BOOL IsPointNearCurve(const CPoint& point, int& iIndex);- 点是否靠近曲线。 
CCurveCtrl
- BOOL Create(const RECT& rect, CWnd* parent, UINT nID,DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE);- 创建控件,其中 - rect表示尺寸。参考 MSDN。
- int AddCurve(const CString& strName, COLORREF color = RGB(0, 0, 0), int iStyle = PS_SOLID, int nWidth = 1);- 向控件添加一条曲线。 
- BOOL AddData(const CString& strName, float fHori, float fVert);
- BOOL AddData(CCurve* pCurve, float fHori, float fVert);- 通过索引或对象指针向曲线添加数据。 
- BOOL AddCurveData(const CString& strName, const CArray< float, float >& ArrHori, const CArray< float, float >& ArrVert);- 同时添加一条曲线和数据。 
- CCurve* GetCurve(int iIndex);
- CCurve* GetCurve(const CString& strName);- 通过其在 - CCurveCtrl中的索引或名称获取曲线对象的指针。
- int GetIndex(const CCurve* pCurve);- 通过指针获取曲线在 - CCurveCtrl中的索引。
- BOOL Remove(int index);
- BOOL Remove(const CString& strName);
- void RemoveAll();- 移除 - CCurveCtrl中的一条曲线或所有曲线。
- int GetCurveCount();- 获取曲线的总数。 
- int GetSelectedCount();- 获取选中曲线的数量。 
- void Move(BOOL bLeft);
- void MovePage(BOOL bLeft);- 将所有曲线和坐标刻度向左或向右移动(不修改数据)。 
- void CurveLeft(CCurve* pCurve, float fLen); void CurveRight(CCurve* pCurve, float fLen);- 将曲线向左或向右移动(会修改曲线的数据)。 
- void MirrorHori(CCurve* pCurve, float fMid);- 水平镜像曲线。 
- void MirrorVert(CCurve* pCurve, float fMid);- 垂直镜像曲线。 
- void Restore();- 显示所有曲线的所有点。 
- BOOL Zoom(BOOL bIn);- 放大( - bIn:- TRUE)或缩小(- bIn:- FALSE)。
- void SetHoriLabel(CString& str);
- CString GetHoriLabel();- 设置/获取水平轴标签。 
- void SetVertLabel(CString& str);
- CString GetVertLabel();- 设置/获取垂直轴标签。 
- void ShowCross(BOOL bShow);
- BOOL IsShowCross();- 是否显示十字线。 
- void SetMargin(const CRect& rect);
- CRect GetMargin();- 设置/获取用于显示标题等的边距。 
- void EnableEdit(BOOL bEdit);
- BOOL CanEditCurve();- 是否可以通过鼠标编辑曲线数据。 
- void SetGridLineStyle(int iStyle);
- int GetGridLineStyle();- 设置/获取背景网格线的样式。 
Notifications
如果通过鼠标操作选择了/取消选择了曲线或修改了数据,将向控件的拥有者窗口(父窗口或非父窗口)发送以下通知消息:
- CVN_MVALUE_ADD- 向曲线添加了一个点。
- CVN_MVALUE_CHANG- 曲线上的一个点的 Y 值正在改变。
- CVN_MVALUE_DELETE- 删除了一个点。
- CVN_CURVE_SELECTED- 选中了一条曲线。
- CVN_CURVE_CANCELSELECT- 取消选中了一条曲线。
- CVN_CURVE_SELECTNONE- 取消选中了所有曲线。
结构
typedef struct tagNM_CURVECTRL { NMHDR hdr; // curve object pointer void* pCurve; // curve object pointer int iIndex; float fHori; // horizontal value where cursor is float fVert; // vertical value where cursor is } NM_CURVECTRL;
请注意 iIndex 成员:如果发送给拥有者的消息是 CVN_MVALUE_ADD、CVN_MVALUE_CHANGE 或 CVN_MVALUE_DELETE,则它是曲线上点的索引;如果消息是 CVN_CURVE_SELECTED、CVN_CURVE_CANCELSELECT 或 CVN_CURVE_SELECTNONE,则它是 CCurveCtrl 中曲线的索引。
用法
以下步骤演示如何在基于对话框的应用程序中使用 CCurveCtrl
- 将 curvectrl.h 和 curvectrl.cpp 添加到您的项目中;
- 在您的 CDialog类中添加一个CCurveCtrl指针成员CCurveCtrl* m_pCurveCtrl; 同时添加 include语句#include “CurveCtrl.h”
- 在您的对话框构造函数中将 m_pCurveCtrl设置为NULLm_pCurveCtrl = NULL; 在您的 resource.h 文件中添加控件的资源 ID,例如: #define ID_CURVE_CONTROL 9999在您的 CDialog::OnInitDialog()中,添加如下语句:if (NULL == m_pCurveCtrl) { m_pCurveCtrl = new CCurveCtrl; m_pCurveCtrl->Create(CRect(10, 10, 200, 200), this, ID_CURVE_CONTROL); // resorce ID m_pCurveCtrl->SetMargin(CRect(70, 50, 50, 50)); } 
- 添加一条曲线和数据如下:CString strName(TestOne); m_pCurveCtrl->AddCurve(strName, RGB(255, 0, 0)); for (float f = 0.0f; f < 6.28f; f += 0.1f) { m_pCurveCtrl->AddData(strTitle, (m_nCurveCount) * f, 100.f * float(sin(f))); } m_pCurveCtrl->Invalidate(); 如果您想通过鼠标操作添加/删除或编辑点,必须调用: m_pCurveCtrl->EnableEdit(TRUE); 控件的拥有者将收到通知消息,如果消息的返回值不为 0(大于 0 或小于 0),则编辑或选择/取消选择的尝试将被拒绝。 例如,要处理 CVN_MVALUE_CHANG消息,请在您的对话框源文件中添加一个处理程序:BEGIN_MESSAGE_MAP(CTestCurveDlg, CDialog) ... ... ON_NOTIFY(CVN_MVALUE_CHANG, ID_CURVE_CONTROL, OnCurveMouseModify) END_MESSAGE_MAP() // message handle function void CTestCurveDlg::OnCurveMouseModify(NMHDR *pNotifyStruct, LRESULT* pResult) { NM_CURVECTRL* pItem = (NM_CURVECTRL*)pNotifyStruct; CCurve* pCurve = (CCurve*)pItem->pCurve; CString str; str.Format("%s: index: %d, %.1f, %.1f", pCurve->GetCurveName(), pItem->iIndex, pItem->fHori, pItem->fVert); TRACE(str); // Uncomment following statement if to reject changing // *pResult = 1; }
如果您想了解更多信息,请参考示例应用程序 TestCurve。
历史
- V1.0,2004 年 9 月 19 日CCurve,CCurveCtrl首次发布。
