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.csdn.net/download/weixin_38002417/10109488

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章