VC++捕捉鼠标"移动"并画十字交叉线

来源:互联网 发布:notepad怎么运行python 编辑:程序博客网 时间:2024/06/10 09:06

1.目标功能:

        在MFC中有专门的鼠标事件响应函数,如OnLButtonDown,OnLButtonUp,OnMouseMove等等。这些常规的鼠标事件响应函数对于我们的程序设计有着非常大的作用.。我的系统是一个基于对话框的数据采集并显示程序,采集到的数据在一个PICTURE中进行相关的数据绘制。其中有一个需要实现的功能是这个PICTURE控件要捕捉鼠标的移动并且采集到鼠标的瞬时坐标画十字交叉线来直观地反映采集数据的大小。

 2.最初的失败:

        设计这个功能的一开始,我就想到了让我的控件响应OnMouseMove消息。在OnMouseMove函数中通过鼠标的坐标就可以实现画十字线功能。于是便在自己写的一个基于PICTURE的控件类中添加了OnMouseMove响应函数,同时写入自己想要实现的功能。运行程序,发现程序没有任何反映!觉得这个现象非常的奇怪,于是便开始了大规模的BAIDU,GOOGLE。终于找到了控件不响应鼠标移动事件的原因:我在对话框中添加的PICTURE控件并没有添加“通知”属性。解决这个问题的方法就是在控件上方点击鼠标右键,控件属性对话框中勾选上PICTURE控件的“通知”属性。运行程序,发现控件果然可以响应鼠标的移动事件并根据移动时鼠标所在的点坐标画十字交叉线了。但功能实现了之后,发现了一个严重的问题。那就是当鼠标移动的时候,可以画十字线,可是鼠标停下来的时候...........十字线就消失了!而我预计的目标是不管鼠标移动与否都要画十字线。经过一个上午的思考,决定放弃这个方案。(方案中还没有解决控件重画的问题,由于最终目标实现不了,也就没有去具体解决其中的细节问题)

3.第二方案:

        既然鼠标停止状态下的时候也要画十字交叉线,(最开始的时候就没想到这个问题,把最开始的功能实现了之后才发现这个问题的,说明我的准备工作做的还不够,目的性还不够充分的明确,有待改进)那就必须放弃鼠标的OnMouseMove响应函数。这个时候我把思路放到了鼠标位置检测函数GetCursorPos(&m_dcursorPos)上面。这个函数捕捉到的是鼠标的屏幕坐标,因此要用ScreenToClient(&m_dcursorPos)将屏幕坐标转化为客户区坐标。但我要得到的是客户区中控件的坐标。于是还要通过DPtoLP(&m_dcursorPos)将设备坐标转换成逻辑坐标。其中涉及到很多关于GDI坐标相关的知识,在这里就不介绍了。由于程序要求运行画图和停止画图的时候都能通过鼠标来画十字线,因此我在对话框中通过判断画图是否运行来控制是否响应OnMouseMove。

4.关键代码:

void CWaveStatic::DrawWave(void)
{
 
 ASSERT(m_nScaleX>1);
 // 生成在屏幕上要画的点数组
 CRect rect;
 GetClientRect(rect);

 CPoint m_dcursorPos;
 GetCursorPos(&m_dcursorPos);
 ScreenToClient(&m_dcursorPos);
 

 CPoint* arrPoints = new CPoint[m_nScaleX];
 int nDis = 1000/(m_nScaleX-1);
 for(int i=0; i<m_nScaleX; ++i)
 {
  arrPoints[i].x = i* nDis;
  arrPoints[i].y = m_arrData[i];
 }
 CDC* pDC = GetDC();
 CDC dcMem;
 dcMem.CreateCompatibleDC(pDC);
 //pDC->DPtoLP(&m_dcursorPos);
 pDC->SetMapMode(MM_ANISOTROPIC);
 pDC->SetWindowExt(1000,508);
 pDC->SetWindowOrg(0,508);
 pDC->SetViewportExt(rect.Width(),-rect.Height());
 pDC->DPtoLP(&m_dcursorPos);
 //pDC->SetBkMode(TRANSPARENT);
 CBitmap bmp,  *pOldBmp;
 bmp.CreateCompatibleBitmap(pDC, 1000, 508);
 pOldBmp = dcMem.SelectObject(&bmp);
 dcMem.SetBkMode(TRANSPARENT);
 // 设置背景色
 dcMem.FillSolidRect(0,0,1000,508,RGB(255,255,255));
 //dcMem.DPtoLP(&m_dcursorPos);
 //DrawScale(&dcMem);
 dcMem.MoveTo(0,m_dcursorPos.y);
    dcMem.LineTo(1000,m_dcursorPos.y);
    dcMem.MoveTo(m_dcursorPos.x,0);
    dcMem.LineTo(m_dcursorPos.x,508);
 // 绘制刻度
 CPen pen(PS_SOLID, 1, RGB(0,0,0)), *pOldPen;
 pOldPen = dcMem.SelectObject(&pen);
 dcMem.Polyline(arrPoints, m_nScaleX);
 dcMem.SelectObject(pOldPen);
 pDC->BitBlt(0,0,1000, 508, &dcMem,0,0, SRCCOPY);
 dcMem.SelectObject(pOldBmp);
 delete[] arrPoints;
 arrPoints = NULL;
}
void CWaveShowDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 if (RunOn)
 {
  return;
 }
 m_wndPic.DrawWave();
 m_wndSmallPic2.DrawWave();
 CDialog::OnMouseMove(nFlags, point);
}   

原创粉丝点击