GDI+绘制矩形,并且实现可旋转、缩放、移动功能(基于MFC对话框)
1、绘制矩形
创建一个绘制矩形的函数,本次是用绘制多边形的函数定义的,定义绘制四条变的矩形区域。
先进行函数声明:
void DrawRectangle1(Gdiplus::Point rectangle_points[], CPoint oript, CPoint detpt)
然后定义函数(selected_rect_是之前定义了一个矩形框,使画的东西在框的区域内):
void CdrawtestDlg::DrawRectangle1Gdiplus(Gdiplus::Point rectangle_points[], CPoint oript, CPoint detpt){ if (!(oript.x >= selected_rect_.left && oript.x <= selected_rect_.right && oript.y > selected_rect_.top && oript.y < selected_rect_.bottom)) { return; } if (!(detpt.x >= selected_rect_.left && detpt.x <= selected_rect_.right && detpt.y > selected_rect_.top && detpt.y < selected_rect_.bottom)) { return; } if (drawing_mode_ == deawingrectangle) { rectangle_points[0] = Gdiplus::Point(oript.x, oript.y); rectangle_points[1] = Gdiplus::Point(detpt.x, oript.y); rectangle_points[2] = Gdiplus::Point(detpt.x, detpt.y); rectangle_points[3] = Gdiplus::Point(oript.x, detpt.y); InvalidateRect(selected_rect_, false); } }
定义变量:
/*矩形定义*/ BOOL is_selected;//是否选中 BOOL is_select;//是否选中 BOOL is_scale;//是否缩放 BOOL is_move;//是否移动
并初始化为FALSE,在对话框点击绘制按钮那响应为TURE。
在ONPaint函数中添加以下代码:
if (drawing_mode_==deawingrectangle||is_move||is_scale)
{
g.DrawPolygon(&pen3,rectangle_point_,4);
}
添加消息响应函数鼠标左键按下的响应,并添加以下代码:
if (draw_mode_ == rectangle) { drawing_mode_ = deawingrectangle; rectangle_point_[0].X = point.x; rectangle_point_[0].Y = point.y; rectangle_point_[1].X = point.x; rectangle_point_[1].Y = point.y; rectangle_point_[2].X = point.x; rectangle_point_[2].Y = point.y; rectangle_point_[3].X = point.x; rectangle_point_[3].Y = point.y; }
添加鼠标移动的响应函数并编辑:
if (drawing_mode_ == deawingrectangle) { SetCursor(h_cur_); DrawRectangle1Gdiplus(rectangle_point_, CPoint(rectangle_point_[0].X, rectangle_point_[0].Y), point); }
添加鼠标抬起响应函数:
if (drawing_mode_ == deawingrectangle) { Gdiplus::GraphicsPath gpath_rectangle; temp_path.AddPolygon(rectangle_point_, 4); temp_path.AddPath(&gpath_rectangle, FALSE); gpath_rectangle.Reset(); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; }
这样就可以画矩形了,效果如下:
2、添加旋转、缩放并且移动
主要是要跟随鼠标移动进行旋转
首先我们要绘制标志点,当选中标志点的时候矩形旋转
所以在鼠标左键按下的响应函数添加以下代码:
void CdrawtestDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (is_draw) { if (draw_mode_==arrow) { drawing_mode_=drawingarrow; arrow_points_[0].X = point.x; arrow_points_[0].Y = point.y; arrow_points_[1].X = point.x; arrow_points_[1].Y = point.y; arrow_points_[2].X = point.x; arrow_points_[2].Y = point.y; arrow_points_[3].X = point.x; arrow_points_[3].Y = point.y; arrow_points_[4].X = point.x; arrow_points_[4].Y = point.y; arrow_points_[5].X = point.x; arrow_points_[5].Y = point.y; } if (draw_mode_ == line) { start_pt_ = point; drawing_mode_ = drawingline; } if (draw_mode_ == rectangle) { drawing_mode_ = deawingrectangle; rectangle_point_[0].X = point.x; rectangle_point_[0].Y = point.y; rectangle_point_[1].X = point.x; rectangle_point_[1].Y = point.y; rectangle_point_[2].X = point.x; rectangle_point_[2].Y = point.y; rectangle_point_[3].X = point.x; rectangle_point_[3].Y = point.y; } if (draw_mode_ == ellipse) { drawing_mode_ = drawingellipse; start_pt_ = old_pt_ = point; } } if (is_selected) { Graphics graphics(this->m_hWnd); //构造环境变量指针 Point testPoint(point.x,point.y);//鼠标坐标 Point TestPoint((rectangle_point_[0].X+rectangle_point_[1].X)/2-3,(rectangle_point_[0].Y+rectangle_point_[1].Y)/2-53);//选择坐标 SolidBrush solidBrush(Color(0,0,0,0)); SolidBrush brush1(Color(0,0,0)); Pen pen(Color(255,0,0,0)); GraphicsPath path; //定义路径 /***********************此部分为选中为矩形区域***************************************************************************/ //构造矩形区域 path.AddClosedCurve(rectangle_point_,4); //链接区域 Region pathRegion(&path); //区域指向路径 graphics.FillRegion(&solidBrush,&pathRegion); //填充区域 if (pathRegion.IsVisible(testPoint,&graphics))//如果在选择区域是矩形 { INT count=path.GetPointCount(); Point* dataPoints=new Point[count]; for (INT j=0;j<count;j++) { graphics.FillEllipse( &brush1, dataPoints[j].X-3.0f, dataPoints[j].Y-3.0f, 6.0f, 6.0f ); //选中标志 graphics.FillEllipse(&brush1,rectangle_point_[0].X-10,rectangle_point_[0].Y-10,6,6); graphics.FillEllipse(&brush1,rectangle_point_[1].X+10,rectangle_point_[1].Y-10,6,6); graphics.FillEllipse(&brush1,rectangle_point_[2].X+10,rectangle_point_[2].Y+10,6,6); graphics.FillEllipse(&brush1,rectangle_point_[3].X-10,rectangle_point_[3].Y+10,6,6); } //画选中的把把 PointF point1((rectangle_point_[0].X+rectangle_point_[1].X)/2,(rectangle_point_[0].Y+rectangle_point_[1].Y)/2); PointF point2((rectangle_point_[0].X+rectangle_point_[1].X)/2,(rectangle_point_[0].Y+rectangle_point_[1].Y)/2-50); PointF points[2]={point1,point2}; PointF* pPoints=points; graphics.DrawLine(&pen,point1.X,point1.Y,point2.X,point2.Y); graphics.FillEllipse(&brush1,(rectangle_point_[0].X+rectangle_point_[1].X)/2-3,(rectangle_point_[0].Y+rectangle_point_[1].Y)/2-53,6,6); //画选中的中心点 StartPoint.X = rectangle_point_[0].X; StartPoint.Y = rectangle_point_[0].Y; EndPoint.X = point.x; EndPoint.Y = point.y; C.X=(rectangle_point_[0].X+rectangle_point_[1].X)/2; C.Y=(rectangle_point_[0].Y+rectangle_point_[3].Y)/2; graphics.DrawLine(&pen,C.X,C.Y-3,C.X,C.Y+3); graphics.DrawLine(&pen,C.X-3,C.Y,C.X+3,C.Y); //初始化缩放坐标点 rectangle_Spoint_[0].X=rectangle_point_[0].X; rectangle_Spoint_[0].Y=rectangle_point_[0].Y; rectangle_Spoint_[1].X=rectangle_point_[1].X; rectangle_Spoint_[1].Y=rectangle_point_[1].Y; rectangle_Spoint_[2].X=rectangle_point_[2].X; rectangle_Spoint_[2].Y=rectangle_point_[2].Y; rectangle_Spoint_[3].X=rectangle_point_[3].X; rectangle_Spoint_[3].Y=rectangle_point_[3].Y; //选中中心点 if (C.X-5<point.x && point.x<C.X+5) { if (C.Y-5< point.y && point.y<C.Y+5) { graphics.FillEllipse(&brush1,C.X-5,C.Y-5,10,10); is_move = TRUE; } } is_scale=TRUE;//只要在选中去内左键点过,就可以实现缩放功能 } //testPoint为鼠标坐标,TestPoint为测试坐标,是否选中(粑粑)标志点 else if(((rectangle_point_[0].X+rectangle_point_[1].X)/2-13) < point.x && point.x<((rectangle_point_[0].X+rectangle_point_[1].X)/2+7)){ if (((rectangle_point_[0].Y+rectangle_point_[1].Y)/2-63)< point.y && point.y<((rectangle_point_[0].Y+rectangle_point_[1].Y)/2-43)) { graphics.FillEllipse(&brush1,(rectangle_point_[0].X+rectangle_point_[1].X)/2-7,(rectangle_point_[0].Y+rectangle_point_[1].Y)/2-55,15,15); is_select=TRUE; }} else return; } CDialogEx::OnLButtonDown(nFlags, point); }
在鼠标移动添加以下代码:
void CdrawtestDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 GraphicsPath temp_path; if (is_draw) { if (drawing_mode_ == drawingline) { SetCursor(h_cur_); DrawLine(start_pt_, point); start_pt_ = point; } if (drawing_mode_ == drawingarrow) { SetCursor(h_cur_); DrawArrow(arrow_points_, CPoint(arrow_points_[0].X, arrow_points_[0].Y), point); } if (drawing_mode_ == deawingrectangle) { SetCursor(h_cur_); DrawRectangle1Gdiplus(rectangle_point_, CPoint(rectangle_point_[0].X, rectangle_point_[0].Y), point); } if (drawing_mode_ == drawingellipse) { SetCursor(h_cur_); old_pt_ = point; DrawEclipse(start_pt_, point); } } if (is_selected) { if (is_select) { Graphics graphics(this->m_hWnd); Pen pen(Color(255,0,0,0)); SetCursor(h_move_); DrawRectangle1Gdiplus(rectangle_point_, CPoint(rectangle_point_[0].X, rectangle_point_[0].Y), point); StartPoint.X = rectangle_point_[0].X; StartPoint.Y = rectangle_point_[0].Y; EndPoint.X = point.x; EndPoint.Y = point.y; C.X=(rectangle_point_[0].X+rectangle_point_[1].X)/2; C.Y=(rectangle_point_[0].Y+rectangle_point_[3].Y)/2; float theta =atan2f(EndPoint.X-C.X,EndPoint.Y-C.Y); double R,B; R=sqrt((double)(C.Y-rectangle_point_[0].Y)*(C.Y-rectangle_point_[0].Y)+(double)(C.X-rectangle_point_[0].X)*(C.X-rectangle_point_[0].X)); B=sin(theta/2)*2*R; //绘制中间选中标志点 graphics.DrawLine(&pen,C.X,C.Y-3,C.X,C.Y+3); graphics.DrawLine(&pen,C.X-3,C.Y,C.X+3,C.Y); ////旋转变换成菱形了~~~T-T~~~~ rectangle_points_[0].X=(rectangle_point_[0].X-C.X)*cos(theta)-(rectangle_point_[0].Y-C.Y)*sin(theta)+C.X; rectangle_points_[0].Y=(rectangle_point_[0].X-C.X)*sin(theta)-(rectangle_point_[0].Y-C.Y)*cos(theta)+C.Y; rectangle_points_[1].X=(rectangle_point_[1].X-C.X)*cos(theta)-(rectangle_point_[1].Y-C.Y)*sin(theta)+C.X; rectangle_points_[1].Y=(rectangle_point_[1].X-C.X)*sin(theta)-(rectangle_point_[1].Y-C.Y)*cos(theta)+C.Y; rectangle_points_[2].X=(rectangle_point_[2].X-C.X)*cos(theta)-(rectangle_point_[2].Y-C.Y)*sin(theta)+C.X; rectangle_points_[2].Y=(rectangle_point_[2].X-C.X)*sin(theta)-(rectangle_point_[2].Y-C.Y)*cos(theta)+C.Y; rectangle_points_[3].X=(rectangle_point_[3].X-C.X)*cos(theta)-(rectangle_point_[3].Y-C.Y)*sin(theta)+C.X; rectangle_points_[3].Y=(rectangle_point_[3].X-C.X)*sin(theta)-(rectangle_point_[3].Y-C.Y)*cos(theta)+C.Y; graphics.DrawLine(&pen,rectangle_points_[0].X,rectangle_points_[0].Y,rectangle_points_[2].X,rectangle_points_[2].Y); graphics.DrawLine(&pen,rectangle_points_[1].X,rectangle_points_[1].Y,rectangle_points_[3].X,rectangle_points_[3].Y); Gdiplus::GraphicsPath gpath_rectangle1; temp_path.AddPolygon(rectangle_points_, 4); temp_path.AddPath(&gpath_rectangle1, FALSE); gpath_rectangle1.Reset(); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; } if (is_move)//移动代码 { SetCursor(h_move_); DrawRectangle1Gdiplus(rectangle_point_, CPoint(rectangle_point_[0].X, rectangle_point_[0].Y), point); StartPoint.X = rectangle_point_[0].X; StartPoint.Y = rectangle_point_[0].Y; EndPoint.X = point.x; EndPoint.Y = point.y; double dx,dy; dx=EndPoint.X-StartPoint.X; dy=EndPoint.Y-StartPoint.Y; rectangle_point_[0].X=rectangle_point_[0].X+dx; rectangle_point_[0].Y=rectangle_point_[0].Y+dy; rectangle_point_[1].X=rectangle_point_[1].X+dx; rectangle_point_[1].Y=rectangle_point_[1].Y+dy; rectangle_point_[2].X=rectangle_point_[2].X+dx; rectangle_point_[2].Y=rectangle_point_[2].Y+dy; rectangle_point_[3].X=rectangle_point_[3].X+dx; rectangle_point_[3].Y=rectangle_point_[3].Y+dy; Gdiplus::GraphicsPath gpath_rectangle; temp_path.AddPolygon(rectangle_point_, 4); temp_path.AddPath(&gpath_rectangle, FALSE); gpath_rectangle.Reset(); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; } }
在鼠标抬起添加以下代码:
void CdrawtestDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 GraphicsPath temp_path; if (is_draw) { if (drawing_mode_==drawingline) { drawing_mode_=invalid; temp_path.AddPath(gpath_line_,FALSE); gpath_line_->Reset(); } if (drawing_mode_ == drawingarrow) { GraphicsPath temp_arrow_path; temp_arrow_path.AddPolygon(arrow_points_, 6); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; vec_arrow_drawcwlls_.push_back(DrawCell(pen_color_, pen_width_, &temp_arrow_path)); } if (drawing_mode_ == deawingrectangle) { Gdiplus::GraphicsPath gpath_rectangle; temp_path.AddPolygon(rectangle_point_, 4); temp_path.AddPath(&gpath_rectangle, FALSE); gpath_rectangle.Reset(); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; } if (drawing_mode_ == drawingellipse) { temp_path.AddEllipse(Rect(start_pt_.x, start_pt_.y, old_pt_.x - start_pt_.x, old_pt_.y - start_pt_.y)); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; } vec_drawcells_.push_back(DrawCell(pen_color_, pen_width_, &temp_path)); } if (is_selected) { if (is_move||is_scale||is_select) { Gdiplus::GraphicsPath gpath_rectangle; temp_path.AddPolygon(rectangle_point_, 4); temp_path.AddPath(&gpath_rectangle, FALSE); gpath_rectangle.Reset(); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid; } if (is_Emove) { /*temp_path.AddEllipse(Rect(start_pt_.x, start_pt_.y, old_pt_.x - start_pt_.x, old_pt_.y - start_pt_.y)); InvalidateRect(selected_rect_, false); drawing_mode_ = invalid;*/ } } CDialogEx::OnLButtonUp(nFlags, point); }
并添加滚轮响应实现鼠标控制缩放:
BOOL CdrawtestDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { // TODO: 在此添加消息处理程序代码和/或调用默认值 GraphicsPath temp_path; if (is_scale) { if (zDelta>0)//向上滚 { rectangle_point_[0].X=rectangle_point_[0].X-5; rectangle_point_[0].Y=rectangle_point_[0].Y-5; rectangle_point_[1].X=rectangle_point_[1].X+5; rectangle_point_[1].Y=rectangle_point_[1].Y-5; rectangle_point_[2].X=rectangle_point_[2].X+5; rectangle_point_[2].Y=rectangle_point_[2].Y+5; rectangle_point_[3].X=rectangle_point_[3].X-5; rectangle_point_[3].Y=rectangle_point_[3].Y+5; } if (zDelta<0)//向下滚 { //测试代码 rectangle_point_[0].X=rectangle_point_[0].X+5; rectangle_point_[0].Y=rectangle_point_[0].Y+5; rectangle_point_[1].X=rectangle_point_[1].X-5; rectangle_point_[1].Y=rectangle_point_[1].Y+5; rectangle_point_[2].X=rectangle_point_[2].X-5; rectangle_point_[2].Y=rectangle_point_[2].Y-5; rectangle_point_[3].X=rectangle_point_[3].X+5; rectangle_point_[3].Y=rectangle_point_[3].Y-5; } } return CDialogEx::OnMouseWheel(nFlags, zDelta, pt); }
好了,这样就可以实现鼠标控制移动,缩放,旋转的功能!
程序下载链接:
http://download.****.net/download/weixin_38002417/10109488