1.首先新建一个基于对话框的MFC程序
2.点击Class View Dlg类鼠标右键的属性,重写消息里面的鼠标移动、鼠标右键按下、抬起,三个消息。
我们在Dialog中添加一个静态文本框,然后在鼠标移动事件函数中添加以下代码就会发现随着鼠标移动,界面上就会显示当前鼠标的坐标信息。
void CMFCDrawLineAndMouseMoveDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format(_T("x=%d y=%d"),point.x,point.y);
GetDlgItem(IDC_STATIC)->SetWindowTextW(str);
}
3.然后我们就可以利用上面的原理实现对框的移动和拉伸,首先我们需要绘制出一个矩形方框。
void CMFCDrawLineAndMouseMoveDlg::myDraw()//绘制方框函数
{
CPen *pOldPen = m_pDc->SelectObject(&/*pen*/m_objPen);
int nOldDrawMode = m_pDc->SetROP2(R2_NOTXORPEN);
m_pDc->SelectStockObject(NULL_BRUSH);
m_pDc->MoveTo(m_pairCaliper.startPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->LineTo( m_pairCaliper.endPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->MoveTo( m_pairCaliper.startPoint.x ,m_pairCaliper.endPoint.y);
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y);
m_pDc->MoveTo(m_pairCaliper.endPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y );
m_pDc->MoveTo(m_pairCaliper.startPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.startPoint.x,m_pairCaliper.endPoint.y );
m_pDc->SelectObject(pOldPen);
}
m_objPen,m_pairCaliper,m_pDc在.h函数中声明:
PointPair m_pairCaliper;//
CDC *m_pDc;
CPoint m_pStart;
struct PointPair
{
CPoint startPoint;
CPoint endPoint;
};
在构造函数中初始化
m_pairCaliper.startPoint.x = 100;
m_pairCaliper.startPoint.y = 100;
m_pairCaliper.endPoint.x = 200;
m_pairCaliper.endPoint.y = 200;
m_objPen.CreatePen(PS_SOLID, 1, RGB(250,0,0));//红色的绘图笔
我们在确定按钮中加入myDraw()函数点击就会发现在界面上会生成一个红色的方框。
void CMFCDrawLineAndMouseMoveDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
myDraw();
}
但是这时我们只是生成了这个方框,所以接下来我们应该要实现鼠标拉伸边和移动整个方框。主要用两个函数实现。MoveBorder(),MoveRect()
void CMFCDrawLineAndMouseMoveDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str;
str.Format(_T("x=%d y=%d"),point.x,point.y);
GetDlgItem(IDC_STATIC)->SetWindowTextW(str);
if (bMoveBorder == true)//移动框的一条边;
{
MoveBorder(point);
}
else if (bMoveRect == true)//移动整个框
{
SetCursor(LoadCursor(NULL, IDC_SIZEALL));//设置鼠标形状为十字箭头型
MoveRect(point);
}
CDialogEx::OnMouseMove(nFlags, point);
}
由于代码过长,这里就只放实现拉伸左右边框的代码,具体原理就是如果拉伸右边框,那么做边框就不需要动,然后重新根据获得的鼠标坐标绘制右、上、下、三条边。首先将原本的三条边按原来的位置重新画一遍(在原本的位置重新画一遍该线会消失)。然后将鼠标的值赋给保存变量的值,再画一遍,也就是鼠标拉伸后所在的位置。MoveTo LineTo和相关绘制函数不懂的可以自行CSDN。
void CMFCDrawLineAndMouseMoveDlg::MoveBorder(CPoint &point)
{
CPen *pOldPen = m_pDc->SelectObject(&/*pen*/m_objPen);
int nOldDrawMode = m_pDc->SetROP2(R2_NOTXORPEN);
m_pDc->SelectStockObject(NULL_BRUSH);
if (bLeftBorder == true)//如果鼠标按在左边框
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));//将鼠标形状变成左右箭头
m_pDc->MoveTo(m_pairCaliper.startPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->LineTo( m_pairCaliper.endPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->MoveTo( m_pairCaliper.startPoint.x ,m_pairCaliper.endPoint.y);
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y);
m_pDc->MoveTo(m_pairCaliper.startPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.startPoint.x,m_pairCaliper.endPoint.y );
if (point.x > m_pairCaliper.endPoint.x - 5)//防止拉伸时左边框拉伸到右边,设置距离最小值
{
m_pairCaliper.startPoint.x = m_pairCaliper.endPoint.x - 5;
}
else
{
m_pairCaliper.startPoint.x = point.x;
}
m_pDc->MoveTo(m_pairCaliper.startPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->LineTo( m_pairCaliper.endPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->MoveTo( m_pairCaliper.startPoint.x ,m_pairCaliper.endPoint.y);
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y);
m_pDc->MoveTo(m_pairCaliper.startPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.startPoint.x,m_pairCaliper.endPoint.y );
}
else if (bRightBorder == true)//如果鼠标按在右边框
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
m_pDc->MoveTo(m_pairCaliper.startPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->LineTo( m_pairCaliper.endPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->MoveTo( m_pairCaliper.startPoint.x ,m_pairCaliper.endPoint.y);
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y);
m_pDc->MoveTo(m_pairCaliper.endPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y );
m_pDc->MoveTo(m_pairCaliper.startPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.startPoint.x,m_pairCaliper.endPoint.y );
if (point.x < m_pairCaliper.startPoint.x + 5)
{
m_pairCaliper.endPoint.x = m_pairCaliper.startPoint.x + 5;
}
else
{
m_pairCaliper.endPoint.x = point.x;
}
m_pDc->MoveTo(m_pairCaliper.startPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->LineTo( m_pairCaliper.endPoint.x ,m_pairCaliper.startPoint.y);
m_pDc->MoveTo( m_pairCaliper.startPoint.x ,m_pairCaliper.endPoint.y);
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y);
m_pDc->MoveTo(m_pairCaliper.endPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.endPoint.x,m_pairCaliper.endPoint.y );
m_pDc->MoveTo(m_pairCaliper.startPoint.x,m_pairCaliper.startPoint.y );
m_pDc->LineTo(m_pairCaliper.startPoint.x,m_pairCaliper.endPoint.y );
}
}
4.这个时候我们发现需要获得鼠标左键按下是到底是在哪条边框,或者是在方框内部从而判断到底是移动方框还是拉伸边。
在.h文件中声明下面的布尔类型,然后再构造函数中全都初始化为false
bool bMoveBorder;//ture是拉伸边
bool bMoveRect;//true是移动方框
bool bLeftButtonDown;//判断鼠标左键是否按下
bool bTopBorder;//上边框
bool bBottomBorder;//下边框
bool bLeftBorder;//左边框
bool bRightBorder;//右边框
CPoint m_classOriginPoint;
bMoveBorder = false;
bMoveRect = false;
bLeftButtonDown = false;
bTopBorder = false;
bBottomBorder = false;
bLeftBorder = false;
bRightBorder = false;
鼠标左键事件中加入以下代码判断鼠标按下时是按在哪条边上或者是方框内部
void CMFCDrawLineAndMouseMoveDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect LeftRect = GetLeftRect(m_pairCaliper);
CRect TopRect = GetTopRect(m_pairCaliper);
CRect RightRect = GetRightRect(m_pairCaliper);
CRect BottomRect = GetBottomRect(m_pairCaliper);
CRect rect(/*m_classStartPoint*/m_pairCaliper.startPoint, /*m_classEndPoint*/m_pairCaliper.endPoint);
bLeftButtonDown = true;
if(LeftRect.PtInRect(point))//按在左边框上
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));//鼠标形状变成左右箭头
bMoveBorder = true;
bLeftBorder = true;
}
else if(TopRect.PtInRect(point))//按在上边框上
{
SetCursor(LoadCursor(NULL, IDC_SIZENS));//鼠标形状变成上下箭头
bMoveBorder = true;
bTopBorder = true;
}
else if(RightRect.PtInRect(point))//按在右边框上
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
bMoveBorder = true;
bRightBorder = true;
}
else if(BottomRect.PtInRect(point))//按在下边框上
{
SetCursor(LoadCursor(NULL, IDC_SIZENS));
bMoveBorder = true;
bBottomBorder = true;
}
else if(rect.PtInRect(point))//按在方框内部,移动方框
{
// 移动测量框
bMoveRect = true;
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
}
m_classOriginPoint.x = point.x;//CPoint类型,保存按下时鼠标的位置,在移动方框时需要用到
m_classOriginPoint.y = point.y;
CDialogEx::OnLButtonDown(nFlags, point);
}
GetLeftRect(),GetTopRect(),GetTopRect(),GetBottomRect()函数如下
CRect CMFCDrawLineAndMouseMoveDlg::GetLeftRect( const PointPair &pointPair ) const
{
CRect LeatRect(pointPair.startPoint.x - 3, pointPair.startPoint.y, pointPair.startPoint.x + 3, pointPair.endPoint.y);
return LeatRect;
}
CRect CMFCDrawLineAndMouseMoveDlg::GetTopRect( const PointPair &pointPair ) const
{
CRect TopRect(pointPair.startPoint.x, pointPair.startPoint.y - 3, pointPair.endPoint.x, pointPair.startPoint.y + 3);
return TopRect;
}
CRect CMFCDrawLineAndMouseMoveDlg::GetRightRect( const PointPair &pointPair ) const
{
CRect RightRect(pointPair.endPoint.x - 3, pointPair.startPoint.y, pointPair.endPoint.x + 3, pointPair.endPoint.y);
return RightRect;
}
CRect CMFCDrawLineAndMouseMoveDlg::GetBottomRect( const PointPair &pointPair ) const
{
CRect BottomRect(pointPair.startPoint.x, pointPair.endPoint.y - 3, pointPair.endPoint.x, pointPair.endPoint.y + 3);
return BottomRect;
}
在鼠标左键抬起时我们需要将相关的bool类型重新变成false
void CMFCDrawLineAndMouseMoveDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
bLeftButtonDown = false;
bTopBorder = false;
bBottomBorder = false;
bLeftBorder = false;
bRightBorder = false;
bMoveRect = false;
CDialogEx::OnLButtonUp(nFlags, point);
}
移动方框的函数MoveRect()的实现,具体也就是先将原本的方框画一遍删除,然后获得新的坐标重新画一遍方框就是移动后的方框。
void CMFCDrawLineAndMouseMoveDlg::MoveRect(CPoint &point)
{
if(m_pDc)
{
CString strMeasureResult;
int nMoveWidth = point.x - m_classOriginPoint.x;
int nMoveHeight = point.y - m_classOriginPoint.y;
myDraw();//将原来的方框画一遍删除
m_pairCaliper.startPoint.x += nMoveWidth;
m_pairCaliper.startPoint.y += nMoveHeight;
m_pairCaliper.endPoint.x += nMoveWidth;
m_pairCaliper.endPoint.y += nMoveHeight;
m_classOriginPoint = point;
myDraw();
//pen.DeleteObject();
}
}
由于作者是20届刚刚毕业的新手,在写作和代码方面许多地方都有不好的地方,如果大家有不明白的地方可以讨论,有指点的地方我也一定会修正。本文更多的像是写给自己的一个笔记,如果能帮到大家我也十分开心。-。-