拖放选中对象

来源:互联网 发布:网络招商是怎么回事 编辑:程序博客网 时间:2024/04/27 20:47
简单就是:在图形范围内判断鼠标点击,捕获鼠标,随着鼠标的移动,不断地擦除原有位置上的图形,在新位置上绘图。
要保存好:图形位置(左上角坐标)、图形尺寸、鼠标点于图形位置的偏移、是否选中图形的标记。
注意:逻辑坐标和设备坐标的转换。
保存的图形坐标、尺寸为逻辑坐标;
DC来画图用的是逻辑坐标;
创建的可选中区域和判断鼠标点再区域内用设备坐标;
得到鼠标点相对图形的偏移是设备坐标;
擦除矩形用设备坐标。
 
新建一个单文档应用程序,View类继承自CScrollView带滚动条。
一、在工程View类中添加数据成员:
protected:
      const CSize m_sizeEllipse; // 所绘制图形的尺寸
      CPoint m_pointTopLeft; // 所绘制图形左上角点的坐标
    CSize m_sizeOffset; // 鼠标的位置相对于图形左上角的偏移
    BOOL m_bCaptured; // 图形是否被选中的标记
 
二、在工程View类的构造函数中初始化这些数据成员:
CMoveSelObView:: CMoveSelObView () : m_sizeEllipse(100, -100),
                                                    m_pointTopLeft(0, 0),
                                                    m_sizeOffset(0, 0)
{
      m_bCaptured = FALSE;
}
 
三、在View类的OnInitialUpdate函数中设置滚动条的属性:(如果不用带滚动条的窗口,这些不是必需的,但必需设定映射模式)
void CMoveSelObView::OnInitialUpdate()
{
      CScrollView::OnInitialUpdate();
 
      //设置滚动范围
      CSize sizeTotal(800, 1050); // 8-by-10.5 inches
    CSize sizePage(sizeTotal.cx / 2, sizeTotal.cy / 2);
    CSize sizeLine(sizeTotal.cx / 50, sizeTotal.cy / 50);
    SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);
}
 
四、在ViewOnDraw函数中绘制一个用于拖动的图形:
void CMoveSelObView::OnDraw(CDC* pDC)
{
      CMoveSelObDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
 
      //创建红色画刷
      CBrush brushHatch(HS_DIAGCROSS , RGB(255, 0, 0));
    CPoint point(0, 0);
 
      //转换逻辑坐标到设备坐标
    pDC->LPtoDP(&point);
    pDC->SetBrushOrg(point); // 以设备坐标为参数
    CBrush* pOldBrush = pDC->SelectObject(&brushHatch);
      //画红色圆圈
    pDC->Ellipse(CRect(m_pointTopLeft, m_sizeEllipse));
      pDC->SelectObject(pOldBrush);
}
 
五、在View类中添加WM_LBUTTONDOWN的消息响应,在其中创建可选中区域、启动鼠标捕捉、更新选中图形标记、计算鼠标相对图形的偏移、改变光标形状:
void CMoveSelObView::OnLButtonDown(UINT nFlags, CPoint point)
{
      CRect rectEllipse(m_pointTopLeft, m_sizeEllipse);
    CRgn circle;
 
    CClientDC dc(this);
    OnPrepareDC(&dc); // 准备好设备上下文,通知设备的映射模式(由SetScrollSizes指定)
    dc.LPtoDP(rectEllipse); // 逻辑坐标转换为设备坐标
    circle.CreateEllipticRgnIndirect(rectEllipse); // 创建用于选中的区域(参数要求逻辑坐标)
    if (circle.PtInRegion(point))  // 点在区域内
      {
        //捕捉鼠标
        SetCapture(); //将鼠标捕获设置到窗口
        m_bCaptured = TRUE;
        CPoint pointTopLeft(m_pointTopLeft);
        dc.LPtoDP(&pointTopLeft);
        m_sizeOffset = point - pointTopLeft; // 得到鼠标位置相对于图形左上角的偏移,设备坐标
 
        //设置光标形状为十字状
        ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
    }
 
      CScrollView::OnLButtonDown(nFlags, point);
}
 
六、在View中添加WM_MOUSEMOVE消息的响应函数。如果图形被选中,在鼠标移动时调用2InvalidateRect函数,前一个用来擦除旧图形,后一个用来显示新图形。
void CMoveSelObView::OnMouseMove(UINT nFlags, CPoint point)
{   
    if (m_bCaptured)
      {//如果有图形被选中,并且鼠标被捕捉则更新图形位置
        CClientDC dc(this);
        OnPrepareDC(&dc);
        CRect rectOld(m_pointTopLeft, m_sizeEllipse);
        dc.LPtoDP(rectOld);
           //擦除老位置的图形
        InvalidateRect(rectOld, TRUE);
        m_pointTopLeft = point - m_sizeOffset; // 更新图形左上角位置
        dc.DPtoLP(&m_pointTopLeft);
           //在新位置画图形
        CRect rectNew(m_pointTopLeft, m_sizeEllipse);
        dc.LPtoDP(rectNew);
        InvalidateRect(rectNew, TRUE);
    }
 
      CScrollView::OnMouseMove(nFlags, point);
}
 
七、在View中添加WM_LBUTTONUP消息的响应函数。释放鼠标左键,释放鼠标捕捉,清除图形选中标记:
void CMoveSelObView::OnLButtonUp(UINT nFlags, CPoint point)
{
      if (m_bCaptured) {
           //释放鼠标捕捉
        ::ReleaseCapture();
        m_bCaptured = FALSE;
    }
 
      CScrollView::OnLButtonUp(nFlags, point);
}
 
完成!
原创粉丝点击