【问题标题】:Winforms Wait to draw Until Controls Added [duplicate]Winforms等待绘制,直到添加控件[重复]
【发布时间】:2011-01-05 15:15:38
【问题描述】:

可能重复:
How do I suspend painting for a control and its children?

我在一个表单中添加了几百个控件,并且在添加每个控件时表单会闪烁,直到完成,有没有办法阻止这个?

【问题讨论】:

  • 无论你做什么,一个带有数百个控件的表单都会像廉价汽车旅馆一样闪烁。将它们添加到面板,然后添加面板并不能真正解决任何问题。

标签: c# winforms controls draw


【解决方案1】:

答案与本题答案相同:

How do I suspend painting for a control and its children?

(为方便起见复制答案:最初来自:https://stackoverflow.com/users/36860/ng5000

在我之前的工作中,我们一直在努力让我们丰富的 UI 应用程序能够立即流畅地绘制。我们使用的是标准的 .Net 控件、自定义控件和 devexpress 控件。

经过大量谷歌搜索和反射器使用后,我发现了 WM_SETREDRAW win32 消息。这确实会在您更新控件时停止绘制,并且可以将 IIRC 应用于父/包含面板。

这是一个非常简单的类,演示如何使用此消息:

class DrawingControl
{
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);

    private const int WM_SETREDRAW = 11; 

    public static void SuspendDrawing( Control parent )
    {
        SendMessage(parent.Handle, WM_SETREDRAW, false, 0);
    }

    public static void ResumeDrawing( Control parent )
    {
        SendMessage(parent.Handle, WM_SETREDRAW, true, 0);
        parent.Refresh();
    }
}

对此有更全面的讨论 - google for C# 和 WM_SETREDRAW,例如

C# Jitter

Suspending Layouts

【讨论】:

  • 我不知道我做错了什么,但这对我不起作用。我仍然在动态创建的表单中看到控件一个接一个地绘制...在父表单和一些容器(如 flowLayoutPanel)上尝试过。
【解决方案2】:

可能希望用表单的 SuspendLayout 和 ResumeLayout 属性包围您的代码

this.SuspendLayout();

//创建控件

this.ResumeLayout(true);

【讨论】:

    【解决方案3】:

    以下是ng5000相同的解决方案,但不使用P/Invoke。

    public static class SuspendUpdate
    {
        private const int WM_SETREDRAW = 0x000B;
    
        public static void Suspend(Control control)
        {
            Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
                IntPtr.Zero);
    
            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgSuspendUpdate);
        }
    
        public static void Resume(Control control)
        {
            // Create a C "true" boolean as an IntPtr
            IntPtr wparam = new IntPtr(1);
            Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
                IntPtr.Zero);
    
            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgResumeUpdate);
    
            control.Invalidate();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多