拖拽图形

原理:Visual C++空间图形可视化算法原理与实践

图形拖拽思路

拖拽常用于在图形的定位和组合是需要交互式移动的情况。其思路就是确定图形的新旧定位点,以此来绘制拖拽路径(类似于橡皮筋的实现),鼠标移动过程中不断擦除旧图形显示新图形。

图形拖拽步骤

1、拖拽的前提是b_select为真,即图形被选中。确定图形的定位点newpt1,并根据鼠标移动的距离计算新的定位点newpt2,以便于绘制拖拽路径.
2、计算拖拽过程中外接矩形的左上角点和右下角点,存储在TopLeftNew、BottomRightNew中。
3、用拖动后的新坐标绘制图形。

添加鼠标消息
这里写图片描述

draftView.h

class CDraftView : public CView
{
protected: // create from serialization only
    CDraftView();
    DECLARE_DYNCREATE(CDraftView)

// Attributes
public:
    CDraftDoc* GetDocument();

    //圆所在的矩形区域,圆心旧坐标,新坐标
    CPoint TopLeft, BottomRight, newpt1, newpt2;
    CPoint TopLeftNew, BottomRightNew;   //新的圆所在矩形区域
    CPoint start, end;   
    BOOL b_select;   //是否选中了圆
    void translate(CPoint &to, CPoint &from, CPoint &start, CPoint &end);  //移动一定距离
    void translate(CPoint &pt, CPoint &start, CPoint &end);   //移动一定距离
// Operations
public:
    BOOL select(CPoint &pt, CPoint &topLeft, CPoint &rightBottom);  //选圆

drawView.cpp

CDraftView::CDraftView()
{
    // TODO: add construction code here

    TopLeftNew = TopLeft = CPoint(50, 50);  //左上角点
    BottomRightNew = BottomRight = CPoint(150, 150);  //右下角点
    newpt1 = CPoint(100, 100);  //圆心
    b_select = FALSE;
}

void CDraftView::OnDraw(CDC* pDC)
{
    CDraftDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here

    if(b_select)  //如果选中,加粗显示
    {
        CPen newPen(PS_SOLID, 2, RGB(0, 0, 0)), *oldPen;
        oldPen = pDC->SelectObject(&newPen);
        pDC->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);  //绘制对象圆
        pDC->SelectObject(oldPen);
    }
    else
    {
        CPen newPen(PS_SOLID, 1, RGB(0, 0, 0)), *oldPen;
        oldPen = pDC->SelectObject(&newPen);
        pDC->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);  //绘制对象圆
        pDC->SelectObject(oldPen);
    }
}

//如果鼠标点距圆的外界举行各边的距离小于10,就可以认为被选中
BOOL CDraftView::select(CPoint &pt, CPoint &topLeft, CPoint &bottomRight)
{
    int x1 = topLeft.x;
    int x2 = bottomRight.x;
    int y1 = topLeft.y;
    int y2 = bottomRight.y;

    if( ( abs(pt.x - x1) < 10 && pt.y > y1 && pt.y < y2 ) || 
        ( abs(pt.x - x2) < 100 && pt.y > y1 && pt.y < y2 ) ||
        ( abs(pt.y - y1) < 10 && pt.x > x1 && pt.x < x2 ) ||
        ( abs(pt.y - y2) < 100 && pt.x > x1 && pt.x < x2 ) )
        return TRUE;
    else
        return FALSE;
}

//将点平移一定距离
void CDraftView::translate(CPoint &to, CPoint &from, CPoint &start, CPoint &end)
{
    to.x = from.x + end.x - start.x;
    to.y = from.y + end.y - start.y;
}

//将点平移一定距离
void CDraftView::translate(CPoint &pt, CPoint &start, CPoint &end)
{
    pt.x += end.x - start.x;
    pt.y += end.y - start.y;
}

void CDraftView::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    b_select = select(point, TopLeftNew, BottomRightNew);  //拾取计算判断
    start = end = point;
    Invalidate();

    CView::OnLButtonDown(nFlags, point);
}

void CDraftView::OnMouseMove(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    CDC *pdc = GetDC();  //获取设备环境

    if(nFlags == MK_LBUTTON && b_select)  //如果在鼠标按下和选中的情况下
    {
        pdc->SetROP2(R2_NOT);  //拖拽图形的橡皮筋的实现
        pdc->SelectStockObject(NULL_BRUSH);  //空画刷不填充

        //平移
        CPoint pt1, pt2;
        translate(pt1, TopLeft, start, end);
        translate(pt2, BottomRight, start, end);
        pdc->Ellipse(pt1.x, pt1.y, pt2.x, pt2.y);  

        translate(TopLeftNew, TopLeft, start, point);
        translate(BottomRightNew, BottomRight, start, point);
        pdc->Ellipse(TopLeftNew.x, TopLeftNew.y, BottomRightNew.x, BottomRightNew.y);  

        //拖拽线橡皮筋的实现
        pdc->SetROP2(R2_NOT);

        translate(pt1, newpt1, start, end);
        pdc->MoveTo(newpt1);  
        pdc->LineTo(pt1);

        translate(newpt2, newpt1, start, point);
        pdc->MoveTo(newpt1);
        pdc->LineTo(newpt2);

        end = point;
    }

    CView::OnMouseMove(nFlags, point);
}

void CDraftView::OnLButtonUp(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    translate(newpt1, start, point);       //圆心移到新的坐标
    translate(TopLeft, start, point);      //平移外接矩形顶点
    translate(BottomRight, start, point);
    Invalidate();

    CView::OnLButtonUp(nFlags, point);
}

选中:
这里写图片描述

拖拽:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值