An MFC Curve Control






4.90/5 (37 votes)
Dec 19, 2004
4 min read

103280

10173
An article on a curve control.
Introduction
- Derived from
CWnd
, easy to use - Fits width and height of drawing rect
- Zooming in and out
- Mouse coordinates tracing
- Single/multiple selected by clicking mouse button
- Cross-line tracing mouse
- Add or delete a point of a curve by clicking mouse button
- Edit vertical value of a point of a curve by moving mouse with button down
- Easy to move, shift or mirror one curve
- Notify control’s owner when curve changing
- Owner determines whether to modify curve data by return values of message handle functions
- Unicode support
- Compiles under Windows 2000, VC 6.0 with warning level 4
Background
Recently, I wanted to visualize data in one of my applications. I had searched from Internet and downloaded some curve controls. Most of them are beautiful and work well, but none works as I want it to be. After reading source code of some controls, I decided to develop one curve control which would meet my application’s requirements.
Classes
CCurve
CCurve
class, derived from CObject
is used to store data and curve properties. It does not perform data adding or deleting.
void ShowCurve(BOOL bShow = TRUE);
BOOL IsVisible();
Sets/gets visualization.
void Select(BOOL bSelect = TRUE);
BOOL IsSelected
Sets/gets selected.
BOOL SetCurveName(CString& strName);
CString GetCurveName();
Sets/gets curve name.
void SetCurveColor(COLORREF color);
COLORREF GetCurveColor();
Sets/gets curve line color.
void SetCurveStyle(int iStyle);
int GetCurveStyle();
Sets/gets curve line style.
void SetCurveWidth(int nWidth);
int GetCurveWidth();
Sets/gets curve line width.
float Distance(const CPoint& pt1, const CPoint& pt2);
Gets distance between two points.
BOOL IsPointNearCurve(const CPoint& point, int& iIndex);
Whether the point is near the curve.
CCurveCtrl
BOOL Create(const RECT& rect, CWnd* parent, UINT nID,DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE);
Creates control, where
rect
is the dimensions. Refer to MSDN.int AddCurve(const CString& strName, COLORREF color = RGB(0, 0, 0), int iStyle = PS_SOLID, int nWidth = 1);
Adds one curve to control.
BOOL AddData(const CString& strName, float fHori, float fVert);
BOOL AddData(CCurve* pCurve, float fHori, float fVert);
Adds data to a curve by index or object pointer.
BOOL AddCurveData(const CString& strName, const CArray< float, float >& ArrHori, const CArray< float, float >& ArrVert);
Adds one curve and data at the same time.
CCurve* GetCurve(int iIndex);
CCurve* GetCurve(const CString& strName);
Gets a curve object’s pointer by its index in
CCurveCtrl
or its name.int GetIndex(const CCurve* pCurve);
Gets a curve’s index in
CCurveCtrl
by pointer.BOOL Remove(int index);
BOOL Remove(const CString& strName);
void RemoveAll();
Removes a curve or all of the curves in
CCurveCtrl
.int GetCurveCount();
Gets total count of curves.
int GetSelectedCount();
Gets count of selected curves.
void Move(BOOL bLeft);
void MovePage(BOOL bLeft);
Moves all curves and coordinate scales left or right (will not modify data).
void CurveLeft(CCurve* pCurve, float fLen); void CurveRight(CCurve* pCurve, float fLen);
Shifts a curve left or right (will modify data of the curve).
void MirrorHori(CCurve* pCurve, float fMid);
Mirrors a curve in horizontal.
void MirrorVert(CCurve* pCurve, float fMid);
Mirrors a curve in vertical.
void Restore();
Shows all points of all curves.
BOOL Zoom(BOOL bIn);
Zooms in (
bIn
:TRUE
) or zooms out (bIn
:FALSE
).void SetHoriLabel(CString& str);
CString GetHoriLabel();
Sets/gets horizontal label.
void SetVertLabel(CString& str);
CString GetVertLabel();
Sets/gets vertical label.
void ShowCross(BOOL bShow);
BOOL IsShowCross();
Whether to show cross lines.
void SetMargin(const CRect& rect);
CRect GetMargin();
Sets/gets margin left to show title, etc.
void EnableEdit(BOOL bEdit);
BOOL CanEditCurve();
Whether can edit curve data by using mouse.
void SetGridLineStyle(int iStyle);
int GetGridLineStyle();
Sets/gets style of grid line in background.
Notifications
Following notify messages will be sent to control’s owner window (parent or not) if curve selected/ deselected or data modified by mouse operation:
CVN_MVALUE_ADD
- a point added to curve.CVN_MVALUE_CHANG
- Y value of a point changing.CVN_MVALUE_DELETE
- a point deleted.CVN_CURVE_SELECTED
- a curve is selected.CVN_CURVE_CANCELSELECT
- a curve is deselected.CVN_CURVE_SELECTNONE
- deselected all curves.
Struct
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;
Note the iIndex
member: it is the index of the point in the curve if the message sent to owner is CVN_MVALUE_ADD
, CVN_MVALUE_CHANGE
or CVN_MVALUE_DELETE
; it is the index of the curve in CCurveCtrl
if the message sent to owner is CVN_CURVE_SELECTED
, CVN_CURVE_CANCELSELECT
or CVN_CURVE_SELECTNONE
.
Usage
Following steps demonstrate how to use CCurveCtrl
in a dialog-based application:
- Add curvectrl.h and curvectrl.cpp into your project;
- Add a
CCurveCtrl
pointer member to yourCDialog
class:CCurveCtrl* m_pCurveCtrl;
And also add
include
statement:#include “CurveCtrl.h”
- Set
m_pCurveCtrl
asNULL
in your dialog construction functions:m_pCurveCtrl = NULL;
Add control’s resource ID to your resource.h file, such as:
#define ID_CURVE_CONTROL 9999
In your
CDialog::OnInitDialog()
, add statements as following: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)); }
- Add one curve and data as following:
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();
If you want to add/delete or edit points with mouse operation, you must call:
m_pCurveCtrl->EnableEdit(TRUE);
Control’s owner will receive notify message, and if the return values of the messages is not 0 (>0 or <0), the edit or selection /deselection attempts will be rejected.
For example, to handle the message of
CVN_MVALUE_CHANG
, add a handler in your dialog source file: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; }
Refer to sample application TestCurve if you want more information.
History
- V1.0, 19 September 2004
CCurve
,CCurveCtrl
first released.