拖放选中对象

简单就是:在图形范围内判断鼠标点击,捕获鼠标,随着鼠标的移动,不断地擦除原有位置上的图形,在新位置上绘图。
要保存好:图形位置 ( 左上角坐标 ) 、图形尺寸、鼠标点于图形位置的偏移、是否选中图形的标记。
注意:逻辑坐标和设备坐标的转换。
保存的图形坐标、尺寸为逻辑坐标;
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);
}
 
四、在 View OnDraw 函数中绘制一个用于拖动的图形:
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 消息的响应函数。如果图形被选中,在鼠标移动时调用 2 InvalidateRect 函数,前一个用来擦除旧图形,后一个用来显示新图形。
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);
}
 
完成!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值