【问题标题】:Reduce Drag & Drop Flickering减少拖放闪烁
【发布时间】:2014-01-23 12:50:16
【问题描述】:

我的代码有问题。我已经为拖放创建了一个类,但是在拖动对象期间,我看到正在拖动的对象出现烦人的闪烁效果

void CDragDropListBox::DrawDragRect(CPoint point, CDragItem* DragItem,SIZE Size)
{
    CDC* pDC = GetDC();
    ScreenToClient(&point);

    //Rect centered under mouse pointer
    point.x -= Size.cx/2;
    point.y -= Size.cy/2;

    CRect rectFull(point,m_RectSize);

    //Delete previous rect
    ClientToScreen(&m_OldRect);
    _DstWnd->ScreenToClient(&m_OldRect);
    _DstWnd->InvalidateRect(m_OldRect, true);
    _DstWnd->UpdateWindow();

    //Draw new rect based on mouse position
    DrawSelectFrame(pDC,rectFull);
    DrawSingleItem(DragItem,pDC,rectFull);

    m_OldRect = rectFull;
}

在我的代码中,每次我移动鼠标时,我都会删除之前绘制的拖动矩形并绘制一个新的,但是闪烁非常挑剔...... 有什么我可以做的吗?

【问题讨论】:

  • 当然,您的 UpdateWindow() 调用会强制窗口重新绘制而不显示矩形。然后你再次绘制矩形。像廉价汽车旅馆一样闪烁。使 WM_PAINT 处理程序意识到必须绘制矩形是解决方法。使用 InvalidateRect() 与新旧矩形的并集来请求更新。
  • 对不起,我不明白。 InvalidateRect 采用单个 rect 参数,我不明白如何使用它来升级两个 rect。

标签: visual-studio-2010 visual-c++ mfc drag-and-drop flicker


【解决方案1】:

这里的主要问题是,擦除和绘画是分两步完成的。 即使它执行得很快。它看起来像在闪烁。

所以不要使用 WM_ERASEBKGND,而在 WM_PAINT 中使用双缓冲(带内存 DC)。

请参阅 Codeproject 中的 CMemDC,了解一个简单易用的课程。

【讨论】:

  • 我已经看过那个例子,但我不知道我是否可以在我的项目中调整它。在我的代码中,拖放期间的绘图功能由放置在我的对话框中的一个列表框控制,而不是由对话框本身控制
  • 我也在尝试覆盖 OnERASEBKGND 但似乎永远不会调用该函数
【解决方案2】:

我已编辑我的代码以删除对 UpdateWindow() 的使用

   void CDragDropListBox::DrawDragRect(CPoint point, CDragItem* DragItem,SIZE Size)
{
    CDC* pDC = _DstWnd->GetDC();
    CDC dcMemory;

    ScreenToClient(&point);
    dcMemory.CreateCompatibleDC(pDC);

    CDC* olddc= pDC;

    CRect tmprect;
    pDC->GetClipBox(&tmprect);

    CBitmap tmpbmp;
    tmpbmp.CreateCompatibleBitmap(pDC, tmprect.Width(), tmprect.Height());

    CBitmap* OldBmp;
    OldBmp = dcMemory.SelectObject(&tmpbmp);

    point.x -= Size.cx/2;
    point.y -= Size.cy/2;

    CRect rectFull(point,m_RectSize);

    ClientToScreen(&m_OldRect);
    _DstWnd->ScreenToClient(&m_OldRect);
    _DstWnd->InvalidateRect(m_OldRect, TRUE);

    m_OldRect = rectFull;

    ClientToScreen(&rectFull);
    _DstWnd->ScreenToClient(&rectFull);
    DrawSelectFrame(pDC,rectFull);
    DrawSingleItem(DragItem,pDC,rectFull);
    _DstWnd->ValidateRect(rectFull);

    //_DstWnd->UpdateWindow();

    olddc->BitBlt(tmprect.left, tmprect.top, tmprect.Width(), tmprect.Height(), pDC, tmprect.left, tmprect.top, SRCCOPY);

    dcMemory.SelectObject(OldBmp);

}

闪烁较少,但我可以进一步改进吗?

【讨论】:

    猜你喜欢
    • 2011-08-26
    • 2011-03-27
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    相关资源
    最近更新 更多