Loucura do Navegador da Web

Editar: A pergunta original era longa, com muitos palpites. Eu cortei de volta para os mistérios restantes ..

Estou lutando e intrigando o dia todo e acho que devo apresentar meu problema à comunidade.

Originou-se do post chamadoO método de captura de tela gera imagens em preto. O pôster original deseja capturar continuamente capturas de tela de seu programa, que inclui um WebBrowser, a cada n segundosmesmo quando o usuário está desconectado.

Quando o usuário está desconectado, ele não tem mais tela. Portanto, qualquer tentativa de ler a tela falhará. Se o uso de um identificador de janela, o resultado for uma caixa preta, ao usar CopyFromScreen, uma exceção de erro de GDI.

Mas a janela do programa ainda está lá e usandoDrawToBitmap funciona bem mesmo quando o usuário está desconectado.

Aqui estão as condições e os problemas restantes:

O usuário não deve tocar / clicar noWebBrowser de qualquer maneira. Se ele fizer isso, digamos, Rolando, Clicando, Navegando no SubterrâneoDrawToBitmap chamadas resultam em uma caixa vazia.

Enquanto oWebBrowser permanece intocado, basta fazer umaRefresh antes da próxima chamada DrawToBitmap.

Depois de tocá-lo, é necessário carregar o URL novamente fazendo umwebBrowser1.Url = new Uri(URLpath);

Ao navegar, o novo URL deve ser armazenado para isso. Eu faço isso no evento Navigated.

Não importa o que,DrawToBitmap falhará (com a caixa vazia) se a página da web contiver um<input type="text" ..> field.

Ao vandalizar oDocumentText com umReplace("<input", "<in_put"); isso pode ser curado, mas sem mais truques, isso perderá as folhas CSS.

Para testá-lo, jogue doisButtons, a Label, a Timer, a Combobox and a WebBrowser on a Form e copie o código; altere o caminho do arquivo para uma pasta adequada à sua configuração e observe ..:

public Form1()
{
    InitializeComponent();
    this.button1.Click += new System.EventHandler(this.button1_Click);
    this.button2.Click += new System.EventHandler(this.button2_Click);
    this.button1.Text = "Start";
    this.button2.Text = "Stop";
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
    this.comboBox1.Items.AddRange(new object[] {
        "https://stackoverflow.com/questions",
        "http://webcam.zirndorf.de/marktplatz/gross.jpg"});
    scapeRect = this.ClientRectangle;
    webBrowser1.Url = new Uri("https://stackoverflow.com/questions");
    this.comboBox1.SelectedIndexChanged += 
                   new System.EventHandler(this.comboBox1_SelectedIndexChanged);

}

Rectangle scapeRect = Rectangle.Empty;
int imgIndex = 0;
int urlIndex = 0;

private void button1_Click(object sender, EventArgs e)
{
    timer1.Interval = 10 * 1000;  // every 10 seconds
    timer1.Start();
}

private void button2_Click(object sender, EventArgs e)
{
    timer1.Stop();
}


private void timer1_Tick(object sender, EventArgs e)
{
    imgIndex ++;
    label1.Text = imgIndex .ToString();
    webBrowser1.Url = new Uri(comboBox1.Text); // this works almost always
    //webBrowser1.Refresh();                   // this works only if the WB is 'untouched'   
    string filename = "d:\\scrape\\AB_sos_Screen" + imgIndex .ToString("000") + ".png";
    Bitmap bmp = new Bitmap(scapeRect.Width, scapeRect.Height);
    this.DrawToBitmap(bmp, scapeRect);
    bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
    bmp.Dispose();
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (comboBox1.Text != "") webBrowser1.Url = new Uri(comboBox1.Text);
}




private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    if (!comboBox1.Items.Contains(e.Url.ToString()))
        urlIndex = comboBox1.Items.Add(e.Url.ToString());
    else
        urlIndex = comboBox1.Items.IndexOf(e.Url.ToString());
    if (urlIndex >= 0) comboBox1.SelectedIndex = urlIndex;
    button1.Focus();
}

Agora posso navegar quase livremente e a raspagem da tela continua funcionando, exceto para páginas com campos de entrada de texto, como por exemplo aComercial ou oTag Páginas.

Gostaria de saber se alguém pode reproduzir ..?

Ou explicar?

Ou eu fui apenas 'caçador de fantasmas' afinal de contas e a coisa é simplesmente não confiável ???

Edição final:

Embora tenha sido bom obter uma explicação, obter uma solução funcional provavelmente deve ser bom o suficiente. O OP encontrou um código que usa umPrintWindow ligar parauser32.dll e resolve todos os problemas. Funciona enquanto está desconectado, funciona comRefreshing mesmo depois de clicar noWebBrowser e raspa todas as páginas, incluindo aquelas com campos de entrada de texto. Aqui está a minha versão:

using System.Runtime.InteropServices;
//...
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);

public Bitmap CaptureControl(Control ctl)
{
    //Bitmap bmp = new Bitmap(ctl.Width, ctl.Height);  // includes borders
    Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height);  // content only
    using (Graphics graphics = Graphics.FromImage(bmp))
    {
        IntPtr hDC = graphics.GetHdc();
        try      { PrintWindow(ctl.Handle, hDC, (uint)0);   }
        finally  { graphics.ReleaseHdc(hDC);                }
    }
    return bmp;
}

Isso pode capturar um formulário ou um controle com ou sem bordas.

questionAnswers(1)

yourAnswerToTheQuestion