MFC 对话框图片上,鼠标拖动画矩形框
参考
https://blog.csdn.net/chenjie863/article/details/17531339 未实验
https://blog.csdn.net/bsnry/article/details/8484047
https://blog.csdn.net/Yuer_Arya/article/details/82052451
在我们在使用微软的绘图程序时。当要画一条直线,先用鼠标确定起始位置,然后鼠标在屏幕上来回移动时,我们会发现,这条直线就像橡皮筋一样,随着鼠标在屏幕中的位置,长短和终点都随之变化。我们在编制自己的程序时,有时也需实现类似的功能,本文将通过简单的编程实例,并说明实现原理。
一。实现原理:
利用了WINDOWS绘图模式中的“异或”的绘图特性。即在屏幕上用异或的模式画图形,然后再用异或的模式,在相同的位置重新画一次此图形,则就会在屏幕上擦出掉上一次所绘制的内容。
具体在程序中,
1。当按下鼠标左键时,用异或的绘图模式在屏幕上画图形。
2。当鼠标移动后,先用异或的绘图模式擦掉上次绘制的图形。然后在新的位置绘制图形。
3。当鼠标左键被抬起时。在最终的位置用正常的颜色重新绘制图形。结束。
要解决这个问题,需要先了解SetROP2函数的两个参数R2_NOT与R2_NOTXORPEN的使用效果,以下为该两种绘画模式举例:
- R2_NOTXORPEN绘画模式
你用红色画笔在黑色背景上画一条直线,显示红色,但你再用这只笔在刚画的直线上重画一遍,就相当于把开始画的红线擦除掉了,划线的地方显示为背景色。 - R2_NOT绘画模式
同样有在同一个地方画两次相当于什么都没画的功能,不过R2_NOT绘画模式第一次画的时候显示颜色并不是你选定的画笔颜色,而是默认的颜色。
当了解以上两种绘画模式后,我们就可以实现拖动鼠标时平滑绘制出动态的矩形框,假设在鼠标移动过程中经过点A, 以点A为末点绘制一个矩形框,接着鼠标移动到下一个点B时,在点B绘制矩形前,再次以点A绘制一次矩形,利用R2_NOT的模式特定,再次绘画末点A后,原来的矩形会被擦除(在同一个地方画两次相当于什么都没画的功能),最后在以点B作为末点,绘制矩形
CPoint m_chRegionLeftTopPoint;//开始点
CPoint m_chRegionRightBottomPoint;//结束点
BOOL m_fLButtonDownNotUp = FALSE;//鼠标是否按下
void CmfcimageDlg::OnLButtonDown(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//获得屏幕坐标 ScreenToClient(&m_picRect);//转到客户区相对坐标 //记录起始点坐标 m_fLButtonDownNotUp = true; if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { m_chRegionLeftTopPoint = point; m_chRegionRightBottomPoint = point; } CDialogEx::OnLButtonDown(nFlags, point); } void CmfcimageDlg::OnMouseMove(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//获得屏幕坐标 ScreenToClient(&m_picRect);//转到客户区相对坐标 if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { if (m_fLButtonDownNotUp) { /* 当了解以上两种绘画模式后,我们就可以实现拖动鼠标时平滑绘制出动态的矩形框, 1 假设在鼠标移动过程中经过点A, 以点A为末点绘制一个矩形框, 2 接着鼠标移动到下一个点B时,在点B绘制矩形前,再次以点A绘制一次矩形, 3 利用R2_NOT的模式特定,再次绘画末点A后,原来的矩形会被擦除(在同一个地方画两次相当于什么都没画的功能), 4 最后在以点B作为末点,绘制矩形! */ CDC* pDC = GetDlgItem(IDC_PIC_SHOW)->GetDC(); CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH); CPen* pen = new CPen(PS_SOLID, 1, RGB(0, 255, 0)); CPen* oldPen = pDC->SelectObject(pen); pDC->SelectObject(pOldBrush); pDC->SetROP2(R2_NOTXORPEN); pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint));//第二次画出A点,那么上次画的框会消失 m_chRegionRightBottomPoint = point; pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint));//画出B点 pDC->SelectObject(oldPen); delete pen; } } CDialogEx::OnMouseMove(nFlags, point); } void CmfcimageDlg::OnLButtonUp(UINT nFlags, CPoint point) { CRect m_picRect; GetDlgItem(IDC_PIC_SHOW)->GetWindowRect(m_picRect);//获得屏幕坐标 ScreenToClient(&m_picRect);//转到客户区相对坐标 // if ((point.x < m_picRect.right) && (point.x > m_picRect.left) && (point.y < m_picRect.bottom) && (point.y > m_picRect.top)) { if (m_fLButtonDownNotUp) { m_chRegionRightBottomPoint = point; //绘制矩形 CDC* pDC = GetDlgItem(IDC_PIC_SHOW)->GetDC(); CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH); CPen* pen = new CPen(PS_SOLID, 1, RGB(0, 255, 0)); CPen* oldPen = pDC->SelectObject(pen); pDC->Rectangle(CRect(m_chRegionLeftTopPoint, m_chRegionRightBottomPoint)); pDC->SelectObject(pOldBrush); pDC->SelectObject(oldPen); delete pen;
} } m_fLButtonDownNotUp = false; CDialogEx::OnLButtonUp(nFlags, point); }