cefsharp / CefSharp

.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework
http://cefsharp.github.io/
Other
9.86k stars 2.92k forks source link

CefWebBrowser display dependent #33

Closed joaosigma closed 11 years ago

joaosigma commented 13 years ago

I have a UserControl that has an instance of CefWebBrowser (it occupies it's entire area). When my program starts, it creates several instances of my UserControl, but only one is initially shown (the primary one). The others are swapped for the primary UserControl in turn so that only one control is displayed at any given time. When each UserControl is created, it calls CefWebBrowser.Load but I noticed that nothing actually happens until the UserControl, where the CefWebBrowser is attached to, gets displayed. In fact, if I call CefWebBrowser.RunScript after CefWebBrowser.Load (even giving it time to load the page), it freezes completely.

ghost commented 13 years ago

Hi. Can you provide reproduction minimal example?

joaosigma commented 13 years ago

You can download the example from here: https://docs.google.com/leaf?id=0B4kDjseZapByNDRmZjA2ODAtOGFhNy00MjE1LTllMTMtZTRjNzAyNmUxNmUw&hl=en_GB&authkey=CIKE8N0D

ghost commented 13 years ago

Thanks for you feedback. This is happens, 'cause you create hidden panel (UserControl) and browser never becomes visible. .Load method wait until browser created and you got infinite wait. It's related to all winforms controls - it creates actual windows in deffered manner.

Now, you can workaround this with .CreateControl technique:

Method 1: In PanelBrowser.cs in constructor place:

            //create browser
            this.browser = new CefSharp.CefWebBrowser();
            this.browser.Dock = DockStyle.Fill;

After this add: this.browser.CreateControl();

Method 2: Do same before .Load method (any CefWebBrowser method). I.e:

        public void Load(string url)
        {
            this.browser.CreateControl();
            this.browser.Load(url);
        }

Second better, 'cause you have lazy control creation, but in future may be more complex to support this.

ghost commented 13 years ago

Swapping via removing controls from form it is very slow. WinForms Layouting very stupid and while webbrowser it is very heavy control, may be you need do only visible/unvisible for controls. Better do manual layouting. For example swapping of two browser controls in your app:

Main(){
...

            //show first panel
            this.Controls.Add(this.panelBrowser1);
            this.Controls.Add(this.panelBrowser2);
            this.Controls.SetChildIndex(this.panelBrowser1, 0);
            this.Controls.SetChildIndex(this.panelBrowser2, 0);
}

        private void buttonSwap_Click(object sender, EventArgs e)
        {
            // corrected
            var visible2 = panelBrowser2.Visible;
            panelBrowser1.Visible = visible2;
            panelBrowser2.Visible = !visible2;
        }

It is works much faster.

joaosigma commented 13 years ago

HI, thanks for the feeedback. I confirm that your solution works, but (!) I disagree when you say that the behavior happens in all windowsforms controls. It does not happen for the WebBrowser control that ships in the .NET framework. And in some respects I believe that what the control is doing in the background (if it doesn't directly correlate to it's drawing), shouldn't be dependent of it (the drawing). By that logic, if I need to show a CefBrowser to make it process a Load(...) request, then it should stop processing it when I make it invisible. Regarding the layout stuff, I don't use the Visible property because it doesn't remove the child control from the layout processing. In your case, you will be receiving resize messages for both child windows even though only one is visible. In simple controls, it's OK, but if the child's controls are complex, it can become slow. Oh and I usually put everything inside a Suspend/Resume Layout that speeds it up a bit.

ghost commented 13 years ago

Of course, this is a bug and we will fix it. Use CreateControl as temporary workaround.

About winforms and same behaviour - i mean that WinForms controls create actual win32 handles in deffered way. While CefWebBrowser it is Control with native window inside, which initalizes asynchroniously - we have confuses, like this issue.