23

我有代码可以在我已经使用了几个月的winforms中拖动无边框表单,效果非常好。

但是当我第一次得到代码时,它们this.Invalidate();在Form的MouseMove事件中使用,并且Form在拖动时有点闪烁并且很慢。因此,我在事件中替换Invalidate()为,令我惊讶的是,表单现在可以非常流畅地拖动并且没有任何闪烁。Update()MouseMove

有人可以向我解释为什么 Update 使代码比 Invalidate 更好地工作,即使 Invalidate 听起来它是正确的使用?

谢谢 :)

PS如果我添加代码可能会有所帮助......现在添加它。

编辑- 这是代码:


private void titlebar_MouseDown(object sender, MouseEventArgs e)
{
    this.IsMouseDown = true;

    this.LastCursorPosition = new Point(e.X, e.Y);

    if (this.BackColor == Color.White)
    {
        this.BackColor = Color.GhostWhite;
        tbox.BackColor = Color.GhostWhite;
        tbox.ForeColor = Color.Black;
    }
    else
    {
        this.BackColor = Color.FromArgb(20, 20, 20);
        tbox.BackColor = Color.FromArgb(20, 20, 20);
        tbox.ForeColor = Color.White;
    }
}

private void titlebar_MouseMove(object sender, MouseEventArgs e)
{
    if (this.IsMouseDown == true)
    {
        //Move the form
        this.Location = new Point(this.Left - (this.LastCursorPosition.X - e.X), this.Top - (this.LastCursorPosition.Y - e.Y));

        // Update works better than Invalidate();.
        Update();
    }
}

private void titlebar_MouseUp(object sender, MouseEventArgs e)
{
    this.IsMouseDown = false;
    this.BackColor = fc;
    tbox.BackColor = fc;
}
4

2 回答 2

41

Invalidate()只需一个区域添加到控件的更新区域。下次收到 WM_PAINT 时,您已失效的区域以及任何其他失效区域都将被标记为进行绘制。当RedrawWindow()被调用时,通常会将 WM_PAINT 消息发布到应用程序队列。该系统可以自由地做它想做的事情,通常是更紧迫的业务,并在可能的情况下进行绘画。

如果您调用Update(),您将获得 GDI+,UpdateWindow()它不会标记要重新绘制的区域,而是WM_PAINT直接将 a 推送到WNDPROC(),绕过应用程序队列。

如果您需要立即刷新控件,请使用Refresh(),这会使区域无效,然后立即调用Update().

于 2010-02-18T06:27:07.563 回答
15

Invalidate 将窗口标记为需要刷新(在某些时候)。更新在那里,然后如果我没记错的话

这是一个比我能够更好地解释差异的链接

于 2010-02-18T06:06:14.337 回答