📄 curvectrl.cpp
字号:
// 参数:
//-------------------------------------------------------------------------------------------------
void CCurveCtrl::ShowCross(BOOL bShow)
{
m_bShowCross = bShow;
}
//-------------------------------------------------------------------------------------------------
// 功能:
// 参数:
//-------------------------------------------------------------------------------------------------
BOOL CCurveCtrl::IsShowCross()
{
return m_bShowCross;
}
// description : set margin, leave a blank in each direction outside of drawing area
// to show title, label, and so on
void CCurveCtrl::SetMargin(const CRect& rect)
{
m_Margin = rect;
}
CRect CCurveCtrl::GetMargin()
{
return m_Margin;
}
// enable/disable edit by using mouse key operation
void CCurveCtrl::EnableEdit(BOOL bEdit)
{
if (GetSelectedCount() > 0)
m_bEdit = bEdit;
else
m_bEdit = FALSE;
}
BOOL CCurveCtrl::CanEditCurve()
{
return m_bEdit;
}
void CCurveCtrl::SetGridLineStyle(int iStyle)
{
m_iGridLineStyle = iStyle;
}
int CCurveCtrl::GetGridLineStyle()
{
return m_iGridLineStyle;
}
// description : non-edit mode: select/deselect one or more(by Shift or Ctrl key pressed) curves
// by clicking left button of mouse;
// edit mode: if parameter "point" is near key point of a curve, select key point and ready to move;
// if parameter "point" is not near key point but near to line between two key points, add key point.
// note that the edited curve must be selected before editing.
//
void CCurveCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
//鼠标拖动图形:记录起点
m_pPoint=point; //保存鼠标按下的点
//disable tooltip
if (m_Tooltip.m_hWnd)
m_Tooltip.Activate(FALSE); //tooltip无效
int iPt = -1;
CCurve* pCurentCur = NULL; //绘图的指针
//has any curve near point
for (int iIndex = 0; iIndex < m_ArrCurve.GetSize(); iIndex++) //查找所有的曲线
{
if (m_ArrCurve[iIndex]->IsPointNearCurve(point, iPt)) //鼠标位置在曲线的边缘?
{
pCurentCur = m_ArrCurve[iIndex]; //是:获得绘制曲线的指针
break;
}
}
// calculate value by point in pixel
float fHori = 0.0f, fVert = 0.0f; //临时变量
if (pCurentCur) //有效的绘图指针?
{
if (iPt > -1) //???在在曲线范围外
{
fHori = pCurentCur->m_fArrHoriValue[iPt];
fVert = pCurentCur->m_fArrVertValue[iPt];
}
else //???在曲线范围内
{
CalculateValue(point, fHori, fVert);
}
}
// non-edit mode
if (!m_bEdit)
{
// multi-select if Ctrl or Shift key are pressed
if ((nFlags & MK_CONTROL) == MK_CONTROL || (nFlags & MK_SHIFT) == MK_SHIFT)
{
if (pCurentCur)
{
// save previous status(selected or not)
BOOL bOldSel = pCurentCur->m_bSelected;
// change status of the curve (deselected or not)
pCurentCur->m_bSelected = !pCurentCur->m_bSelected;
// send message to owner
int nMsg = pCurentCur->m_bSelected ? CVN_CURVE_SELECTED : CVN_CURVE_CANCELSELECT;
BOOL bKeepOld = SendMessageToParent(nMsg,
pCurentCur,
iIndex, // curve index in this CCurveCtrl
fHori,
fVert
);
// restore previous status if owner does not permit to change
if (bKeepOld)
{
pCurentCur->m_bSelected = bOldSel;
}
}
}
else // single-select
{
// deselect all curve
for (int iQ = 0; iQ < m_ArrCurve.GetSize(); iQ++)
{
m_ArrCurve[iQ]->m_bSelected = FALSE;
}
if (pCurentCur != NULL)
{
// save previous status(selected or not)
BOOL bOldSel = pCurentCur->m_bSelected;
// change status of the curve (deselected or not)
pCurentCur->m_bSelected = !pCurentCur->m_bSelected;
// send message to owner
int nMsg = pCurentCur->m_bSelected ? CVN_CURVE_SELECTED : CVN_CURVE_CANCELSELECT;
BOOL bKeepOld = SendMessageToParent(nMsg,
pCurentCur,
iIndex, // curve index in this CCurveCtrl
fHori,
fVert
);
// restore previous status if owner does not permit to change
if (bKeepOld)
{
pCurentCur->m_bSelected = bOldSel;
}
}
else // send message to owner if no curve is selected
{
SendMessageToParent(CVN_CURVE_SELECTNONE,
pCurentCur,
-1, // no curve selected
fHori,
fVert
);
// disable edit mode if no curve selected
m_bEdit = FALSE;
}
}
}
else if(pCurentCur && pCurentCur->IsSelected())// under edit mode, the edited curve must be selected already
{
// if index of key point of the curve is valid, move point when mouse move
if (iPt >= 0)
{
m_iCurPoint = iPt;
m_pCurveEdit = pCurentCur;
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
SetCapture();
// save value before moving
m_fOldHori = pCurentCur->m_fArrHoriValue[iPt];
m_fOldVert = pCurentCur->m_fArrVertValue[iPt];
}
else // if index invalidate, then add key point to the curve
{
// calculate value by point
float fHori, fVert;
CalculateValue(point, fHori, fVert);
// insert values to sorted data arrays, and get the index of the new key point
int iH = InsertDataToCurve(pCurentCur, fHori, fVert, point);
// to notify owner that new key point is added
int bDontAdd = SendMessageToParent(CVN_MVALUE_ADD,
pCurentCur,
iH,
fHori,
fVert
);
// whether to add the new point is determined by owner
if (bDontAdd)
{
pCurentCur->m_fArrHoriValue.RemoveAt(iH);
pCurentCur->m_fArrVertValue.RemoveAt(iH);
pCurentCur->m_ArrPoint.RemoveAt(iH);
}
m_iCurPoint = -1;
m_pCurveEdit = NULL;
}
}
Invalidate();
CWnd::OnLButtonDown(nFlags, point);
}
//-------------------------------------------------------------------------------------------------
// 功能:non-edit mode: refresh to draw cross(if shown) and tooltip
// edit mode: change cursor and move the selected key point
// 参数:nFlags:
// point:mouse坐标点
//-------------------------------------------------------------------------------------------------
void CCurveCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
// change point if has any key point selected
return;
if (m_bEdit && m_pCurveEdit && m_iCurPoint >= 0)
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
float fHori, fVert;
if (CalculateValue(point, fHori, fVert))
{
// change vertical value only
m_pCurveEdit->m_ArrPoint[m_iCurPoint].y = point.y;
m_pCurveEdit->m_fArrVertValue[m_iCurPoint] = fVert;
}
}
else
{
// if there is any key point nearby
int iPoint = -1;
CCurve* pCurentCur = NULL;
for (int iIndex = 0; iIndex < m_ArrCurve.GetSize(); iIndex++)
{
if (m_ArrCurve[iIndex]->IsPointNearCurve(point, iPoint))
{
pCurentCur = m_ArrCurve[iIndex];
break;
}
}
// if parameter point is near one key point of a selected curve
if (pCurentCur && iPoint >= 0 && pCurentCur->IsSelected())
{
// change cursor
if (m_bEdit)
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
// use tooltip to show the values of key point nearby
CString strTip;
strTip.Format(_T("%s[%d]: %d,%.4f"), pCurentCur->GetCurveName(), iPoint, int(pCurentCur->m_fArrHoriValue[iPoint]), pCurentCur->m_fArrVertValue[iPoint]);
if(m_Tooltip.m_hWnd)
{
m_Tooltip.Activate(TRUE);
m_Tooltip.UpdateTipText(strTip, this);
MSG msg;
msg.hwnd= m_hWnd;
msg.message= WM_MOUSEMOVE;
msg.wParam= nFlags;
msg.lParam= MAKELPARAM(LOWORD(point.x), LOWORD(point.y));
msg.time= 0;
msg.pt.x= point.x;
msg.pt.y= point.y;
m_Tooltip.RelayEvent(&msg);
}
}
}
Invalidate();
CWnd::OnMouseMove(nFlags, point);
}
// description : handle left mouse button up, notify owner if data changed
void CCurveCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bEdit && m_pCurveEdit && m_iCurPoint >=0)
{
BOOL bKeepOld = SendMessageToParent(CVN_MVALUE_CHANG,
m_pCurveEdit,
m_iCurPoint,
m_pCurveEdit->m_fArrHoriValue[m_iCurPoint],
m_pCurveEdit->m_fArrVertValue[m_iCurPoint]
);
if (bKeepOld) // owner does not permit to change data, restore previous values
{
m_pCurveEdit->m_fArrHoriValue[m_iCurPoint] = m_fOldHori;
m_pCurveEdit->m_fArrVertValue[m_iCurPoint] = m_fOldVert;
}
else
{
CalculateVertRange(m_pCurveEdit->m_fArrVertValue[m_iCurPoint], TRUE);
CalculateVertRange(m_pCurveEdit->m_fArrVertValue[m_iCurPoint], FALSE);
}
// cursor style
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
m_pCurveEdit = NULL;
m_iCurPoint = -1;
ReleaseCapture();
Invalidate();
}
//拖动鼠标移动图形:依据为鼠标按下的点与鼠标抬起的点的差,再换算成采集的点数;
float fHori, fVert,fHori1;
if(CalculateValue(m_pPoint, fHori1, fVert)) //计算鼠标按下的点
{
if(CalculateValue(point, fHori, fVert)) //计算鼠标抬起的点
{
if(fHori1!=fHori) //相同点?
{
int v_iNum=int(fHori1-fHori); //差值
m_fHoriBegin+=v_iNum; //移动起点
m_fHoriEnd+=v_iNum; //移动终点
Invalidate(); //绘图
}
}
}
CWnd::OnLButtonUp(nFlags, point);
}
// description : delete key point after right mouse button clicked when enable edit
void CCurveCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
if (m_bEdit)
{
// get the nearby curve
int iPt = -1;
CCurve* pCurentCur = NULL;
for (int iIndex = 0; iIndex < m_ArrCurve.GetSize(); iIndex++)
{
if (m_ArrCurve[iIndex]->IsPointNearCurve(point, iPt))
{
pCurentCur = m_ArrCurve[iIndex];
break;
}
}
// if there is one and be selected and near point
if (pCurentCur && pCurentCur->IsSelected() && iPt >= 0)
{
int bKeep = SendMessageToParent(CVN_MVALUE_DELETE,
pCurentCur,
iPt,
pCurentCur->m_fArrHoriValue[iPt],
pCurentCur->m_fArrVertValue[iPt]
);
// whether delete the point determined by message handle function
if (!bKeep)
{
pCurentCur->m_ArrPoint.RemoveAt(iPt);
pCurentCur->m_fArrHoriValue.RemoveAt(iPt);
pCurentCur->m_fArrVertValue.RemoveAt(iPt);
// remove the curve object if there is no point in it
if (pCurentCur->m_fArrHoriValue.GetSize() == 0)
{
ASSERT(m_ArrCurve[iIndex] == pCurentCur);
delete pCurentCur;
m_ArrCurve.RemoveAt(iIndex);
}
}
Invalidate();
}
}
CWnd::OnRButtonDown(nFlags, point);
}
// description : notify owner that curve mode or data changed
// in parameter: nMessage -- message id
// pCurve -- curve object
// iIndex -- index of curve or key point
// fHori -- horizontal value
// fVert -- vertical value
// return : 0:permit to change; else: do not change
LRESULT CCurveCtrl::SendMessageToParent(int nMessage, CCurve* pCurve, int iIndex, float fHori, float fVert) const
{
if (!IsWindow(m_hWnd))
return 0;
// struct to save parameter
NM_CURVECTRL nmcurve;
nmcurve.pCurve = (void*)pCurve;
nmcurve.iIndex = iIndex;
nmcurve.fHori = fHori;
nmcurve.fVert = fVert;
nmcurve.hdr.hwndFrom = m_hWnd;
nmcurve.hdr.idFrom = GetDlgCtrlID();
nmcurve.hdr.code = nMessage;
// send message to owner, owner is parent or not
CWnd *pOwner = GetOwner();
if (pOwner && IsWindow(pOwner->m_hWnd))
return pOwner->SendMessage(WM_NOTIFY, nmcurve.hdr.idFrom, (LPARAM)&nmcurve);
else
return 0;
}
//-------------------------------------------------------------------------------------------------
// 功能:鼠标滚轮消息响应
// 参数:zDelta=120向前(放大);zDelta=120向后(缩小);
//-------------------------------------------------------------------------------------------------
BOOL CCurveCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// TODO: Add your message handler code here and/or call default
m_fHoriBegin+=10;
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -