ElementHost的布局问题布局、问题、ElementHost

由网友(毁我现在′废你将来)分享简介:我有一堆ElementHosts说我装上我的形式。发生这种情况时,该元件的主机都出现一个黑色背景。如果我把另一个控制前,然后关闭其他的控制,在ElementHosts通常粉刷一新。一些google搜索后,我发现,如果我子类的ElementHost并为此在构造使用(的createGraphics()){}在Element...

我有一堆ElementHosts说我装上我的形式。发生这种情况时,该元件的主机都出现一个黑色背景。如果我把另一个控制前,然后关闭其他的控制,在ElementHosts通常粉刷一新。一些google搜索后,我发现,如果我子类的ElementHost并为此在构造

 使用(的createGraphics()){}
 

在ElementHosts都绘制好的背景....但是,他们需要约300ms的每个元素主机出现在窗体上......他们相继出现......因此它喜欢看的形式越来越奠定了..我有,当然称为SuspendLayout和ResumeLayout手动,但这并不改变结果

这只是Windows窗体的整合bugginess?或者是有什么我可以做这使控件显示正确,并以合理的速度?

感谢。

更新:我能够用非常简单的code重现该问题:

 公共部分类TestControl2:用户控件
    {
        公共TestControl2()
        {
            的InitializeComponent();
        }

    保护覆盖无效的OnLoad(EventArgs的发送)
    {
        base.OnLoad(E);

        //推迟负荷BackgroundWorker的似乎是这里涉及到的问题...
        VAR体重=新的BackgroundWorker();
        bw.DoWork + =委托{Thread.sleep代码(2000); };
        bw.RunWorkerCompleted + =委托
        {
            INT X = 0;
            INT Y = 0;
            的for(int i = 0;我小于20;我++)
            {
                无功控制=新面板();
                control.Width = 200;
                control.Height = 80;
                control.Controls.Add(新的ElementHost {儿童=新System.Windows.Controls.Label {内容= @你好},码头= DockStyle.Left,大小=新System.Drawing.Size(75,23)});
                control.Controls.Add(新的ElementHost {儿童=新System.Windows.Controls.Button {内容= @按钮},码头= DockStyle.Fill});
                VAR UC2 =新用户控件();
                uc2.Controls.Add(控制);
                control.Dock = DockStyle.Fill;
                uc2.Left = X;
                uc2.Top = Y;
                X + = control.Width + 10;
                //使用(uc2.CreateGraphics()){}解决了这个问题,但是减慢负载,所以它看起来像每个用户控件被添加一次加
                panel1.Controls.Add(UC2);
            }
        };

        bw.RunWorkerAsync();
    }
    }
 

解决方案

圣奔忙,我终于得到了它的工作。我试图从谷歌这个code(有一对夫妇的来源.... How做我暂停画一个控件及其子 ...命名一个):

 私人const int的WM_SETREDRAW = 0x000B;

    公共静态无效挂起(该控制的控制)
    {
        消息msgSuspendUpdate = Message.Create(control.Handle,WM_SETREDRAW,IntPtr.Zero,
            IntPtr.Zero);

        NativeWindow的窗口= NativeWindow.FromHandle(control.Handle);
        window.DefWndProc(REF msgSuspendUpdate);
    }

    公共静态无效简历(该控制的控制)
    {
        VAR WPARAM =新的IntPtr(1);
        消息msgResumeUpdate = Message.Create(control.Handle,WM_SETREDRAW,WPARAM,
            IntPtr.Zero);

        NativeWindow的窗口= NativeWindow.FromHandle(control.Handle);
        window.DefWndProc(REF msgResumeUpdate);

        control.Invalidate();
    }
 
JAVA中GridLayout的布局问题 如图,如何弄成这样的布局,

这并没有解决我的问题,给我留下了黑色搞砸背景......但我想尝试加入以下的恢复方法:

 公共静态无效简历(该控制的控制)
      {
            control.Visible = FALSE;
            //上述现有code ....
            control.Visible =真;
      }
 

和BAM!它的工作原理。

I have a bunch of ElementHosts that I'm loading onto my form. When this happens, the element hosts all appear with a black background. If I bring another control to front, then close the other control, the ElementHosts are repainted normally. After some googling, I found that if I sub-class ElementHost and do this in the constructor

 using (CreateGraphics()) { }

The ElementHosts are all drawn with good backgrounds....BUT, they take about 300ms per element host to appear on the form...and they appear sequentially...so it's like watching the form getting laid out... I have, of course called SuspendLayout and ResumeLayout manually, but this doesn't change the result.

Is this just Windows Forms integration bugginess? Or is there something I can do about this to make the controls appear correctly and at a reasonable rate?

Thanks.

UPDATE: I am able to reproduce the problem with the very simple code:

    public partial class TestControl2 : UserControl
    {
        public TestControl2()
        {
            InitializeComponent();
        }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        // deferring load with the BackgroundWorker seems to be related to the problem here...
        var bw = new BackgroundWorker();
        bw.DoWork += delegate { Thread.Sleep(2000); };
        bw.RunWorkerCompleted += delegate
        {
            int x = 0;
            int y = 0;
            for (int i = 0; i < 20; i++)
            {
                var control = new Panel();
                control.Width = 200;
                control.Height = 80;
                control.Controls.Add(new ElementHost { Child = new System.Windows.Controls.Label { Content = @"Hello" }, Dock = DockStyle.Left, Size = new System.Drawing.Size(75, 23) });
                control.Controls.Add(new ElementHost { Child = new System.Windows.Controls.Button { Content = @"button" }, Dock = DockStyle.Fill });
                var uc2 = new UserControl();
                uc2.Controls.Add(control);
                control.Dock = DockStyle.Fill;
                uc2.Left = x;
                uc2.Top = y;
                x += control.Width + 10;
                // adding using (uc2.CreateGraphics()) {} fixes the problem but slows down the load so it looks like each UserControl is being added one at a time
                panel1.Controls.Add(uc2);
            }
        };

        bw.RunWorkerAsync();
    }
    }

解决方案

Holy sh*t, I finally got it working. I tried this code from Google (there were a couple of sources.... How do I suspend painting for a control and its children? ...to name one):

    private const int WM_SETREDRAW = 0x000B;

    public static void Suspend(this 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(this Control control)
    {
        var 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();
    }

It didn't solve my problem and left me with the black messed up backgrounds...BUT I thought to try adding the following to the Resume method:

      public static void Resume(this Control control)
      {
            control.Visible = false;                
            // existing code above....
            control.Visible = true;
      }

and BAM!!! it works.

阅读全文

相关推荐

最新文章