WebBrowser控件DocumentCompleted IFRAME和功放后,使用Javascript完成功放、控件、WebBrowser、DocumentCompleted

2023-09-04 03:44:58 作者:独孤掌权

我需要捕获生成的HTML的图像。我使用的是亚历克斯Filipovici的优秀的解决方案从这里: HTML字符串转换为图片。它除了当我试图加载一个页面,有一个使用一些JavaScript加载一个iframe的伟大工程。

I need to capture an image of generated HTML. I'm using Alex Filipovici's excellent solution from here: Convert HTML string to image. It works great except when I'm trying to load a page that has an iframe that uses some Javascript to load.


        static int width = 1024;
        static int height = 768;

        public static void Capture()
        {
            var html = @"
<!DOCTYPE html>
<meta http-equiv='X-UA-Compatible' content='IE=Edge'>
<html>
<iframe id='forecast_embed' type='text/html' frameborder='0' height='245' width='100%' src='https://m.xsw88.com/allimgs/daicuo/20230904/7102.png", System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            Application.Exit();
        }

据我所知,有可能是没有明确的办法知道的已经结束了所有的JavaScript和iframe装载的变幻莫测和事实DocumentCompleted得到,因为有帧/内置页框+ 1。我可以用iframe负载处理的称为多次有一个计数器或东西,但我要的是一个合理的延迟,所以JavaScript在它加载,我没有得到的图像与加载是这样的:的 http://imgur.com/FiFMTmm

推荐答案

如果你正在处理与使用框架和AJAX大量动态网页,没有完美的解决方案,以发现,当一个特定的页面完成加载资源。你可以得到附近做以下两件事情:

If you're dealing with dynamic web pages which use frames and AJAX heavily, there is no perfect solution to find when a particular page has finished loading resources. You could get close by doing the following two things:

处理页面的的window.onload 事件; ,然后异步轮询 web浏览器的忙性,具有一定的predefined相当短的时间了。 handle the page's window.onload event; then asynchronously poll WebBrowser Busy property, with some predefined reasonably short time-out.

例如,(检查 http://stackoverflow.com/a/19283143/1768303 以一个完整的例子):

E.g., (check http://stackoverflow.com/a/19283143/1768303 for a complete example):

const int AJAX_DELAY = 2000; // non-deterministic wait for AJAX dynamic code
const int AJAX_DELAY_STEP = 500;

// wait until webBrowser.Busy == false or timed out
async Task<bool> AjaxDelay(CancellationToken ct, int timeout)
{
    using (var cts = CancellationTokenSource.CreateLinkedTokenSource(ct))
    {
        cts.CancelAfter(timeout);
        while (true)
        {
            try
            {
                await Task.Delay(AJAX_DELAY_STEP, cts.Token);
                var busy = (bool)this.webBrowser.ActiveXInstance.GetType().InvokeMember("Busy", System.Reflection.BindingFlags.GetProperty, null, this.webBrowser.ActiveXInstance, new object[] { });
                if (!busy)
                    return true;
            }
            catch (OperationCanceledException)
            {
                if (cts.IsCancellationRequested && !ct.IsCancellationRequested)
                    return false;
                throw;
            }
        }
    }
}

如果你不想使用异步/计谋,您可以使用定时器实现相同的逻辑。

If you don't want to use async/await, you can implement the same logic using a timer.