MFC 菜鸟之问——鼠标移动获取坐标和画线问题

来源:互联网 发布:prism.js 使用 编辑:程序博客网 时间:2024/06/14 06:58

MFC 菜鸟之问??鼠标移动获取坐标和画线问题

2014-01-16-20:44
初学MFC,现做一个鼠标测试软件,希望实现鼠标移动实时获取坐标,在左下角显示X,Y坐标值,并实现按下左键拖动划红线,按下右键画蓝线,按下中键画绿线,主要代码如下:
void CMSDlg::OnPaint() 
{
               CClientDC dc(this);
     //显示X: Y: W:
 COLORREF oldColor = dc.GetTextColor();
  dc.SetBkMode(TRANSPARENT);
       CFont font,fontChannel;
     CFont* pOldFont=(CFont*)dc.SelectObject(&font);
     CString strShowText;
     fontChannel.CreatePointFont(300, _T("宋体"), &dc);
     dc.SelectObject(&fontChannel);
     strShowText.Format(_T("X:%4d Y:%4d W:%3d"),p.x,p.y,gl);
     dc.SetTextColor(RGB(106,86,148));  //文本颜色  
 dc.TextOut(20,860,strShowText); 
     dc.SetTextColor(oldColor); 
     dc.SelectObject(pOldFont);
 // CDialog::OnPaint();

}

void CMSDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 if (LButDon||RButDon||MButDon)
 {
  CDC* pDC;
  CPen   newPen;
  pDC=GetDC();
  if(MButDon)
   newPen.CreatePen(PS_DASHDOTDOT,2,RGB(0,255,0));
  if (RButDon)
   newPen.CreatePen(PS_DASHDOTDOT,2,RGB(0,0,255));
  if (LButDon)
   newPen.CreatePen(PS_DASHDOTDOT,2,RGB(255,0,0));  
  pDC-> SelectObject(newPen);   
  pDC->MoveTo(p);
  pDC->LineTo(point);
  ReleaseDC(pDC);
 }
 p=point;
 RefreshPromptInfo();
 CDialog::OnMouseMove(nFlags, point);
}

void CMSDlg::RefreshPromptInfo()
{
       RECT rect;  //刷新区域
       rect.left=20; //区域最左端
       rect.top=860;//区域最顶端
       rect.right=rect.left+400;//宽
       rect.bottom=rect.top+40;//高
       InvalidateRect(&rect);
       UpdateWindow();
}
以上代码显示坐标正常,但是不能画线; 屏蔽掉RefreshPromptInfo()后画线功能可以了,但是显示X,Y坐标的数字重叠模糊成一片了,这是为什么?小妹才疏学浅 求高手指教!

回复讨论(解决方案)

呵呵,这里很少碰见女孩子啊。

你贴出来的代码不是很全,而且你其中用了一些类成员变量吧,例如LButDon||RButDon||MButDon???

如果是的话,以后最好还是前面加上 m_ ,并且CSDN上的编辑器是支持代码的,这样可读性就强多了。

就说这些代码,不明白RefreshPromptInfo()是干什么用的,而且其中的坐标用的是绝对数字。

麻烦你再补充一下。
OnMouseMove只记录一些数据
OnPaint根据以上数据绘图
不做修改,不会画线。
因为你的mousemove不断响应,也就不断地RefreshPromptInfo(),这个函数中InvalidateRect(&rect);
又会反复的调用OnPaint函数,所以,你的坐标显示是对的,但是你的画图被不断地刷新界面给掩埋了。
如果屏蔽了RefreshPromptInfo(),那你的画图时正常了,因为界面不会刷新,你画的线也会一直存在。看起来是可以画线了。但是因为界面不刷新,你的坐标显示就不正确了。

出现的问题是因为你的坐标显示与画线函数没有在一起响应。
你在p=point;后边加Invalidate();不是你的效果的话InvalidateRect(&rect1);重新定义一下那个区域。

我也是个学生,马上要吃饭了,我没有具体的调试。
今天注册的样哦。欢迎哈
RefreshPromptInfo()函数里面的InvalidateRect(&rect)有问题,其实这个函数的意思是把rect区域加入到cwnd中将要重绘的区域中,然后等待WM_PAINT消息发送后,rect区域和CWND中药重绘的区域一起重绘(我想你可能是把这个函数的意思弄成了只重绘rect区域了)。所以只要你的鼠标移动就会导致这种重绘,就会发现没有画出直线
解决的方法其实很简单,在响应鼠标移动的函数中用刷子把坐标值的区域用背景色刷了就可以了,一定要先刷再输出新的坐标就可以了。。。。。还有做大量频繁的图形绘制用invalidate函数其实很不好,因为会出现闪烁的问题。。。
以上代码显示坐标正常,但是不能画线; 屏蔽掉RefreshPromptInfo()后画线功能可以了,但是显示X,Y坐标的数字重叠模糊成一片了,这是为什么?小妹才疏学浅 求高手指教!
-------------------------------------------------------------
是画上了又被刷掉了,X,Y坐标的数字重叠模糊成一片,那是因为你设置了背景色透明了,你可以先用背景色刷一遍,在你写文字之前

呵呵 是的 我是刚注册的  

刚开始学MFC 看了一些书 但是一点效果都没有 于是想动手做些东西这样边做边学 但是感觉有点吃力 各位大

侠有没有什么好的建议或者给小妹指引个方向。。。。。不介意的话是否能加个好友指导指导~

同时也谢谢各位的指导 我先试着做看看~
女娃子学MFC。。。
俺是学嵌入式的,当然也得又当爹又当娘:硬件自己搭,软件自己写。
旁边的师姐说,女孩子学什么编程硬件啊,多么不雅啊,所以,我一直替人家改程序
理解清楚什么时候会重绘!

是小妹妹一定得指导哦
画图程序一般不是这样设计的,

你应该有个东西记录你画线的数据(线,就是起止点了。矩形可以直接记录。 其它也能找到相应的数据结构)。

鼠标画线时画的是“橡皮线”,搜索下, 要画xor线,在你拖动时,画新线,擦除原来的线。
在controlpaint类中。
最后鼠标弹起时,再设置终点坐标,pait下。

希望对你有所帮助,这个功能实现后,你对gdi+会有进一步的了解。
sorry,当成dotnet贴了。 mfc中,用xor模式画线,很方便的。
思路跟上边的一样。
橡皮线。
RefreshPromptInfo()函数里面的InvalidateRect(&rect)有问题,其实这个函数的意思是把rect区域加入到cwnd中将要重绘的区域中,然后等待WM_PAINT消息发送后,rect区域和CWND中药重绘的区域一起重绘(我想你可能是把这个函数的意思弄成了只重绘rect区域了)。所以只要你的鼠标移动就会导致这种重绘,就会发现没有画出直线
解决的方法其实很简单,在……
呵呵 我真的以为InvalidateRect(&rect)只是重绘rect区域了 受教了 按照你的方法做了 但是坐标显示正常了 画线只有笔触那里显示一点画笔颜色 还有点闪烁 大侠能否给出代码详细给我解释下~
来来来,小妹,哥哥手把手教你画鼠标轨迹 声明一个全局的内存DC, CDC m_memDC;下面就是关键步骤,看看就知道了
void CDrawLineView::OnDraw(CDC* pDC)
{
CDrawLineDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

CRect rc;
GetClientRect(&rc);

CBitmap m_memBmp; //与内存DC相兼容的位图
if (m_memDC.GetSafeHdc() == NULL)
{
m_memDC.CreateCompatibleDC(pDC);
m_memBmp.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
m_memDC.SelectObject(m_memBmp);
m_memDC.FillSolidRect(0, 0, rc.Width(), rc.Height(), RGB(255,255,255));
}
pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &m_memDC, 0, 0, SRCCOPY); //拷贝内存图
}

void CDrawLineView::OnLButtonDown(UINT nFlags, CPoint point) 
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));

m_bElseDraw = TRUE;
m_FirstPoint = point;
m_LastPoint = point;
SetCapture(); //捕捉鼠标
CRect rc;
GetClientRect(&rc);
ClientToScreen(rc);
ClipCursor(rc); //限定鼠标在客户区移动
CView::OnLButtonDown(nFlags, point);
}

void CDrawLineView::OnMouseMove(UINT nFlags, CPoint point) 
{
if (m_bElseDraw)
{
CPen m_pen;
m_pen.CreatePen(m_PenStyle, m_PenWidth, m_PenColor);
m_memDC.SetROP2(R2_COPYPEN);
CPen *pOldPen = m_memDC.SelectObject(&m_pen);

m_memDC.MoveTo(m_FirstPoint);
m_memDC.LineTo(point);
m_FirstPoint = point;
m_memDC.SelectObject(pOldPen);
m_pen.DeleteObject();
Invalidate(FALSE);
}
CView::OnMouseMove(nFlags, point);
}

void CDrawLineView::OnLButtonUp(UINT nFlags, CPoint point) 
{
m_bElseDraw = FALSE;
ReleaseCapture(); //释放鼠标
ClipCursor(NULL); //解除鼠标区域限制
CView::OnLButtonUp(nFlags, point);
}
...


篇2:
GetDlgItem(控件ID)->GetWindowRect(&rect);//获取控件基于全频的位置
ScreenToClient(rect);//转换为对话框上的相对位置

  
 BOOL   GetCursorPos( LPPOINT   lpPoint ); //获取鼠标的X,Y坐标

篇3:

MFC在dialog下怎么获取鼠标在Picture控件中的坐标?求高手解答

转自:http://bbs.csdn.net/topics/390401684
出现的问题:
MFC在dialog下怎么获取鼠标在Picture控件中的坐标:
我的程序如下:
先使用Opencv 读取图像,再用MFC画出:
// TODO: Add your control notification handler code here
IplImage *image=NULL; //原始图像
if(image) cvReleaseImage(&image);
CString fileName;
//打开文件对话窗口
//CFileDialog dlg(TRUE,"jpg","*.jpg",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"JPEG文件(*.jpg)|*.jpg||",NULL);
//从文件对话窗口中打开图像
//CString    strFilter = "Bmp File(*.bmp)|*.bmp|";
CString strFilter;
strFilter += "Jpeg File (*.jpg;*.jpeg)|*.jpg;*.jpeg|";
strFilter += "Tif File (*.tif)|*.tif|";
strFilter += "Gif File (*.gif)|*.gif|";
strFilter += "PGM Files (*.pgm)|*.pgm|";
strFilter += "All Files (*.*)|*.*|";
CFileDialog dlg(TRUE, NULL, NULL, OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
strFilter, this);

if(dlg.DoModal()!=IDOK)
return;
fileName = dlg.GetPathName();
std::string tempName = (LPCSTR)CStringA(fileName);
const char* tempimage = tempName.c_str();
image = cvLoadImage(tempimage,1); //显示图片
IplImage* image2= cvCloneImage(image);
DrawPicToHDC(image2, IDC_STATIC);
然后,使用OnMouseMove()函数获取鼠标在Picture控件中的坐标:
void CTestDialgDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default

CRect rect_ctr;
//获取Picture控件相对屏幕左上角的坐标,/存储到rect_ctr中
(this->GetDlgItem(IDC_STATIC))->GetWindowRect(&rect_ctr);

ScreenToClient(rect_ctr); //获取Picture控件相对对话框客户区左上角的坐标
point.x -=  rect_ctr.left; //point获取的是鼠标相对对话框客户区左上角的坐标,减去rect_ctr.left和
point.y -=  rect_ctr.top; //rect_ctr.top后,即为鼠标相对Picture控件左上角的坐标


//获取状态栏上的文字,并将鼠标的坐标显示在状态栏上
char szString[100]={0};
char szText[512];

HWND hWnd = ::GetActiveWindow();
::GetWindowText(hWnd,(LPWSTR)szText,200);
memset(szText+strlen(szText),' ',20);

//如果鼠标位于Picture控件之外,在对话框状态栏上不显示其坐标
if( point.x>(rect_ctr.right-rect_ctr.left) || point.y>(rect_ctr.bottom-rect_ctr.top )
|| point.x<0 || point.y<0 )
;
else
sprintf(szString,"(%4i,%4i)",point.x,point.y);

//将鼠标坐标显示到对话框状态栏上
// sprintf(szString,"(%4i,%4i)",point.x,point.y);

strcpy(szText+20,szString);
::SetWindowText(hWnd,(LPWSTR)szText);
CDialog::OnMouseMove(nFlags, point);
}

以上是详细代码,为什么运行后,无法获取鼠标拖动点的坐标?
听有的人是是因为不能用opencv直接图取图像,有没有别的办法能够在MFC dialog 下编程实现以上功能?

解决的办法:
首先声明,不是OnMouseMove(UINT nFlags, CPoint point)问题,而是没有触发OnMouseMove的PreTranslateMessage消息映射。
在上面代码CPP里面加上一个触发鼠标响应的代码就可以了,如下:
//将Static控件的鼠标响应转换到父窗口处理
BOOL CTestDialgDlg::PreTranslateMessage(MSG* pMsg)  
{

     if (GetDlgItem(IDC_STATIC)->GetSafeHwnd() == pMsg->hwnd && 
                                                                                                   pMsg->message == WM_MOUSEMOVE)
      {
           OnMouseMove(MK_MBUTTON, pMsg->pt);
            return TRUE;
       }
     return CDialog::PreTranslateMessage(pMsg);
}



原创粉丝点击