5

我在表单上有一个简单的面板,我正在使用 AutoScrollMinSize 和 AutoScroll 在我的面板上获取一些滚动条,一切正常。

我还有一个 Scroll 事件,我用它来使整个面板区域无效,因为事实上它似乎只使左/右、上/下滚动时需要的位无效。除此之外,我正在使用与面板大小相同的 BufferedGraphics,然后执行 .Render(e.Graphics) 因为我希望它在整个面板上绘制,就好像滚动条不存在一样.

现在,我遇到的问题是滚动和绘制内容时似乎存在视觉延迟,我认为这是因为在滚动事件之前我不熟悉的地方有一个额外的绘制/设置阶段是调用或在调用 Paint 事件之间。

如果我在绘画方法中有一个无效面板,您看不到问题,但这更多与绘画事件被多次调用隐藏问题有关。

所以我想我理解的方式是,当你滚动时,引擎盖下的东西会做一个大矩形 blit 移动已经存在的内容,然后用需要填充的区域的矩形调用无效。

如果是这种情况,是否存在这种情况,例如抑制这个阶段或我缺少的其他设置来摆脱跟上滞后?

PS:我还覆盖了 OnPaintBackground 方法,它是一个空存根。

4

1 回答 1

4

好的,回答我自己的问题,以防它在极少数情况下帮助任何人。从有人提到 LockWindowUpdate 开始,我发现了 WM_SETREDRAW 和这篇文章SuspendDrawing,现在我可以平滑滚动并能够绘制整个面板。只需让 Scroll 事件执行以下操作。YMMV。

    [DllImport("user32.dll")]
    private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
    private const int WM_SETREDRAW = 0xB;

    private void PanelView_Scroll(object sender, ScrollEventArgs e)
    {
        Control control = sender as Control;
        if (control!=null)
        {
            if (e.Type == ScrollEventType.ThumbTrack)
            {
                // Enable drawing
                SendMessage(control.Handle, WM_SETREDRAW, 1, 0);
                // Refresh the control 
                control.Refresh();
                // Disable drawing                            
                SendMessage(control.Handle, WM_SETREDRAW, 0, 0);
            }
            else
            {
                // Enable drawing
                SendMessage(control.Handle, WM_SETREDRAW, 1, 0);
                control.Invalidate();
            }
        }
    }
于 2012-11-16T21:34:29.083 回答