|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
I am catching event when new window are created and starting working with new created WebView. But problem when I am trying to Capture() image of the WebView it returns null. GetContentAreaSize() and GetScrollOffset() are always (0,0); Tested with http://www.popuptest.com/
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
I tried to make test project and found it works correctly. Proably something with configuration in my app. I am investigation it. Intersting that Handle of created window is 0, when page is loaded correctly, I use URL and can get HTML of the document: http://prntscr.com/d38zwvMaybe you can give me advice what is wrong?
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
Wehn I capture image with parameters Capture(new Rectangle(0, 0, Width, Height)) it returns image instead of null.
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
I found why it happens. If I created webview with specific Width and Height: WebView view = runner.CreateWebView(1000, 1000);
then issue that I described above will appear. If I created WebView without width and height it works good.
If you need, I can make a test project.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Sure. Please create a test project and send it to us.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
I have sent you a test project, please check it.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
We have looked into the test project you sent to us. The root of the problem you are accessing the WebView in two different threads and created a race condition in your code. Specifically, NewWindow event is fired does not mean the new WebView is ready. In fact the flow is like this:
1. User or code tries to open a new window in an existing WebView; 2. A new WebView is created but not initialized; 3. NewWindow is fired and user accept the new WebView (or user can choose not to accept it and the flow ends here); 4. The new WebView is initialized;
The key here is the WebView is initialized after NewWindow is fired. If you access the new WebView in another thread between step 3 and step 4 it will fail.
Generally, you should not access the same WebView from multiple threads because the WebView is thread specific. In your case, you can try to enclose the call inside ThreadRunner.Send, that will marshal the call to the ThreadRunner's thread and it will only be called after step 4. That should resolve the issue for you.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
Hi,
probably you didn't understand the issue. I changed the code, make all requests via ThreadRunner.Send(), wait till WebView is created and loaded. It still doesn't help. And I think it won't help as if I create view in other way it works.
WebView view = runner.CreateWebView(); // It works WebView view = runner.CreateWebView(1000, 1000); // It doesn't work
In any case I fixed the issue by myself, I create WebView without specifying the size of it and later I just resize it.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
I don't think you understand what we tried to tell you. The issue does not have anything to do with the WebView size. It's a racing condition in two different threads in your code that is triggered by certain timing sequence. When you create the WebView in a different size, it changes the amount of time certain steps takes (for example, a larger WebView takes more time to do the initial rendering). That timing change triggers the racing conditions that you run into. Without fixing the racing condition itself, it can still manifest in all sorts of different scenarios --- for example, you might run into the same problem when you run the code on a slower or faster machine, or when somehow the computer "choke" for a second due to a background task while you are creating the WebView. All these can change the timing sequence of your code and trigger the same problem that you thought you "fixed" by creating a WebView without specifying size.
Unless you are extremely familiar with such multi-thread problems, a good start for you is to put everything inside ThreadRunner.Send so that they all run inside a single thread. If you still run into problems, we can then look into that and help you further.
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
Thank you for the explaining. Probably I described the issue not correctly. If you checked my code, you can see that I create WebView and access it methods from a single thread. Moreover I tried to wrap everything in ThreadRunner.Send() and I still receive the same issue.
If you can change my code and send me back the correct version, probably I can understand better what's wrong. For now tried everything (sleeping after WebView created, waiting while WebView created, using ThreadRunner, using single thread etc.) and it doesn't work for me.
In any case I fixed the issue for myself and it works, I tested it in multi threads with different sizes of WebViews and websites, will do more tests as you advised.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
The root of the problem is when you call WebView.Capture, the WebView is not ready yet. We will look into this and see if we can provide an easy way to make sure/check whether the WebView is ready.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
Hi,
bu if WebView is not ready why it allows me to load url? Moreover I can execute JavaScript code and receive HTML of the document, for example.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
The first WebView (the "view" variable in your code) is ready. The second WebView (the "_newWebView" variable in your code) is NOT ready when you call _newWebView.Capture(). That's why image2 is null and this is what caused the NullReferenceException.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
If WebView is not ready, can I still execute JavaScript or other methods?
Before calling Capture() I called var html = _newWebView.GetHtml(); and received the HTML of the WebView.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
It's possible. In order for the WebView to be ready for capture, the DOM/JavaScript engine has to be ready first, then the internal window is initialized and the actual layout/rendering/buffer is built/updated. Because the browser engine is optimized for speed, it often delay rendering when its still busy with other things. That means the browser engine is ready to run JavaScript before it can ever "display" anything at all. If you call capture in this state, then you will receive null.
Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
Thank you, now it's totally clear for me.
The question is how to know if WebView is ready for capturing the image? As I understood you don't have a solution for that now?
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi, For your particular case you can use LoadCompleted:
Code: C#
void view_NewWindow(object sender, NewWindowEventArgs e)
{
_newWebView = e.WebView;
e.Accepted = true;
_newWebView.LoadCompleted += (sender2, e2) =>
{
System.Drawing.Image image = _newWebView.Capture();
...save the image....
};
}
In our next build you will be able to use:
Code: C#
void view_NewWindow(object sender, NewWindowEventArgs e)
{
_newWebView = e.WebView;
e.Accepted = true;
_newWebView.QueueScriptCall(() =>
{
System.Drawing.Image image = _newWebView.Capture();
...save the image....
});
}
The difference between these two is usually QueueScriptCall will be done much sooner than LoadCompleted. So you will be able to use this method if you want to capture screen shot as soon as possible. Thanks!
|
|
Rank: Advanced Member Groups: Member
Joined: 8/29/2016 Posts: 64
|
I tried the first code and it still returns null when I try to Capture. Have you tried to change my test project and it works for you?
I really like the idea of the second code, I can use it in many variations. Looking forward to try it.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,229
|
Hi,
We have posted a new build. We tested this build with your test app for both cases (LoadCompleted and QueueScriptCall) and they work fine. If you still have problems, please send us an updated test app and we will investigate further.
Thanks!
|
|