Winform闪烁问题

时间:2012-05-03 01:04:33

标签: c# winforms paint flicker drawimage

我有一个Winform用户控件闪烁非常糟糕。控件的功能非常完美。它只是闪烁非常糟糕。我正在绘制一个位图,然后使用DrawImage将位图复制到屏幕上,所以我很惊讶发生了多少闪烁。这是我所拥有的摘录:

    private void ScrollPanel_Paint(object sender, PaintEventArgs e)
    {
        var c = (Calendar)Parent;

        Bitmap bmp = c.RequestImage();
        if (bmp == null)
            return;

        e.Graphics.DrawImage(bmp, new Rectangle(0, 0, ClientSize.Width, ClientSize.Height),
                             new Rectangle(0, _scrollOffset, ClientSize.Width, ClientSize.Height),
                             GraphicsUnit.Pixel);
        _bmpSize = bmp.Height;
        e.Graphics.Dispose();
        bmp.Dispose();
    }

    private void ScrollPanel_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            _mouseDown = true;
            _oldMouseCoords = e.Location;
        }
    }

    private void ScrollPanel_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
            _mouseDown = false;
    }

    private void ScrollPanel_MouseMove(object sender, MouseEventArgs e)
    {
        if (_mouseDown && e.Location.Y < _oldMouseCoords.Y && _scrollOffset < _bmpSize - _scrollOffset - ClientSize.Height)
        {
            int offset = _oldMouseCoords.Y - e.Location.Y;
            _scrollOffset += offset;
            Refresh();
        }
        if (_mouseDown && e.Location.Y > _oldMouseCoords.Y && _scrollOffset > 0)
        {
            int offset = e.Location.Y - _oldMouseCoords.Y;
            _scrollOffset -= offset;
            Refresh();
        }
        _oldMouseCoords = e.Location;
    }

它应该做的是,当我用鼠标拖动时,它应该滚动位图,它就是这样。就像我说的那样,功能完全正常。正如您从Paint事件中看到的那样,我正在做的就是获取我的位图,然后将其直接复制到屏幕上。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

看看有关双缓冲的其他问题,以确保正确设置... Enabling Double Buffering

根据我的经验,一旦设置了双缓冲,即使你选择自己绘画,也会因为控件的背景被绘制而引起闪烁。我通过从正在绘制的控件类派生我自己的控件类,重写OnPaintBackground方法,而不是在该方法中调用基类实现来避免这种情况。

所以在你的情况下,我假设ScrollPanel是一个Panel。我将从Panel派生一个类,并使用它而不是Panel。然后我会覆盖OnPaintBackground,并将该方法的主体留空。

完成所有这些后,我得到的滚动就像WinForms可以实现的那样顺畅。