Я должен быть еретиком, если хочу браузер C# с NewWindow2 и GetElementsByTagName

Очевидно, ты не можешь получить свой торт и съесть его.

В настоящее время я использую System.Windows.Forms.WebBrowser в своем приложении. В настоящее время программа зависит от использования функции GetElementsByTagName. Я использую его, чтобы собрать все элементы определенного типа (либо «входные», либо «текстовые области»), чтобы я мог отсортировать их и вернуть значение определенного типа. Это код для этой функции (мой веб-браузер называется web1):

// returns the value from a element.
public String FetchValue(String strTagType, String strName) 
{
    HtmlElementCollection elems;
    HtmlDocument page = web1.Document.Window.Frames[1].Document;
    elems = page.GetElementsByTagName(strTagType);
    foreach (HtmlElement elem in elems)
    {
        if (elem.GetAttribute("name") == strName ||
            elem.GetAttribute("ref") == strName)
        {
            if (elem.GetAttribute("value") != null)
            {
                return elem.GetAttribute("value");
            }
        }
    }

    return null;
}

(указывает на примечание: веб-страница, с которой мне нужно извлечь, находится во фрейме, и, в зависимости от обстоятельств, идентифицирующее имя элемента будет либо в имени, либо в атрибуте ref)

Все это прекрасно работает с System.Windows.Forms.WebBrowser.

Но чего он не может сделать, так это перенаправить открытие нового окна, чтобы остаться в приложении. Все, что открывается в новом окне, попадает в браузер пользователя по умолчанию, что приводит к потере сеанса. Эту функциональность можно легко исправить с помощью события NewWindow2, которого нет в System.Windows.Forms.WebBrowser.

А теперь простите меня за то, что я был ошеломлен его отсутствием. Я только недавно бросил VB6 и перешел на C# (да, VB6, видимо, я работаю под камнем), и в VB6 WebBrowser обладал как функцией GetElementsByTagName, так и событием NewWindow2.

AxSHDocVw.WebBrowser имеет событие NewWindow2. Он был бы более чем счастлив помочь мне направить мои новые окна туда, где они мне нужны. Код для этого в THAT WebBrowser:

private void web1_NewWindow2(
                      object sender, 
                      AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
    frmNewWindow frmNW = new frmNewWindow();
    e.ppDisp = frmNW.web2.Application;
    frmNW.web2.RegisterAsBrowser = true;
    frmNW.Visible = true;
}

Я не могу самостоятельно создать способ воспроизвести эту функцию с помощью обычного события NewWindow, которое не приводит в восторг.

Я также не могу понять, как воспроизвести функцию FetchValue, описанную выше, с помощью файла AxSHDocVw.WebBrowser. Кажется, что все происходит совершенно по-другому, и все мои знания о том, как это делать, бесполезны.

Я знаю, что я больной, испорченный человек для этой причудливой фантазии об использовании этих двух вещей в одном приложении. Но сможете ли вы найти в своем сердце желание помочь этому глупому идеалисту?


person friggle    schedule 21.03.2012    source источник
comment
Можете ли вы показать нам код того, как вы перенаправляете на новую страницу? Вы пытаетесь перезагрузить страницу в текущем элементе управления WebBrowser?   -  person Brad Rem    schedule 21.03.2012
comment
В настоящее время у меня нет кода для перенаправления. В OP второй блок кода — это то, как это работало бы, если бы у меня был NewWindow2. Я хочу перенаправить начальный URL-адрес в новую форму.   -  person friggle    schedule 21.03.2012


Ответы (3)


Я больше не мог полагаться на обходной путь, и мне пришлось отказаться от System.Windows.Forms.WebBrowser. Мне нужен NewWindow2.

В конце концов я понял, как добиться того, что мне нужно, с помощью AxWebBrowser. В моем первоначальном посте запрашивалось либо решение для NewWindow2 в System.Windows.Forms.WebBrowser, либо замена AxWebBrowser для .GetElementsByTagName. Замена требует примерно в 4 раза больше кода, но выполняет свою работу. Я подумал, что было бы разумно опубликовать свое решение для более поздних сотрудников Google, столкнувшихся с тем же затруднением. (также на случай, если есть лучший способ сделать это)

IHTMLDocument2 webpage = (IHTMLDocument2)webbrowser.Document;
IHTMLFramesCollection2 allframes = webpage.frames;
IHTMLWindow2 targetframe = (IHTMLWindow2)allframes.item("name of target frame");
webpage = (IHTMLDocument2)targetframe.document;
IHTMLElementCollection elements = webpage.all.tags("target tagtype");

foreach (IHTMLElement element in elements)
{
  if (elem.getAttribute("name") == strTargetElementName)
   {
     return element.getAttribute("value");
   }
}

Webbrowser.Document приводится в IHTMLDocument2, затем кадры IHTMLDocument2 помещаются в IHTMLFrameCollection2, затем я привожу конкретный нужный кадр в IHTMLWindow2 (вы можете выбрать кадр по индексу # или имени), затем я привожу член кадра .Document в IHTMLDocument2 (первоначально использовавшийся для удобства). Отсюда метод IHTMLDocument2 .all.tags() функционально идентичен старому методу WebBrowser.Document.GetElementsByTagName(), за исключением того, что он требует IHTMLElementCollection, а не HTMLElementCollection. Затем вы можете использовать для каждой коллекции отдельные элементы, которые должны быть IHTMLElement, и использовать .getAttribute для получения атрибутов. Обратите внимание, что g в нижнем регистре.

person friggle    schedule 30.03.2012

Элемент управления WebBrowser может обрабатывать событие NewWindow, чтобы новые всплывающие окна открывались в WebBrowser.

private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
  // navigate current window to the url
  webBrowser1.Navigate(webBrowser1.StatusText);
  // cancel the new window opening
  e.Cancel = true;
}

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/361b6655-3145-4371-b92c-051c223518f2/

person Erik Philips    schedule 21.03.2012
comment
Вздох, мне этого было достаточно. К сожалению, я не имею дело с простой HTML-ссылкой. Я пробовал подобное решение, но поскольку ссылка на самом деле представляет собой какой-то Javascript, e.Cancel = true; выдает ошибку сценария Internet Explorer вида Вы хотите продолжить выполнение сценариев на этой странице? Да/Нет разнообразия. - person friggle; 21.03.2012
comment
о, отлично, я погуглил и почти нашел решение. Поскольку я сам генерирую ошибку, мне было бы удобно временно подавлять ошибки Javascript на время этого события. По-видимому, в AxSHDocVw.WebBrowser есть свойство Silent, которое я мог бы просто установить в true...... но КОНЕЧНО, System.Windows.Forms.WebBrowser не имеет такого свойства горе мне горе мне - person friggle; 21.03.2012
comment
Ах, да, это было бы связано с попыткой сценария перенаправить и кодом, отменяющим его. Вы также можете предотвратить появление ошибок сценария. msdn.microsoft.com/en-us/ library/ не уверен, что это предотвратит их. - person Erik Philips; 21.03.2012
comment
это работает! Я знаю, что не рекомендуется подавлять ошибки скриптов, но я работаю с этой страницей уже почти 2 года и не могу вспомнить ни одного случая, когда было бы важно увидеть эти ошибки. Оооо, это меня заводит! - person friggle; 21.03.2012