Не всех устраивает стандартный движок IE в Винде. Но, к счастью, есть много альтернативных движков для C#, Gecko входит в их число и в этом посте я опишу, как использовать GeckoFx в своих проектах.
Исходники можно найти в конце статьи.
На момент написания статьи последняя версия GeckoFx для C# это 22. Давненько не было обновлений и, возможно, проект умер, но даже 22 версия лучше IE. Так что начнем 🙂
Напишем приложение, которое будет заходить на главную станицу гугла, вводить какой-то запрос и переходить по случайному сайту в выдаче.
Создаем новый проект (Приложение Windows Forms), называем его «GeckoExample«, переименовываем главную форму в «FrmMain«, размеры главной формы = 514; 399.
Для работы нам понадобиться:
- Скачать библиотеки здесь. Распаковать;
- Скачать сам движок с офф. фтп Мозиллы. Распаковать;
- Установить Async Targeting Pack для .NET 4.0 в проект.
Теперь в созданном проекте добавляем ссылки на Geckofx-Core.dll и Geckofx-Winforms.dll.
Бросаем на форму Panel (Name = pnl1, Location = 0;0, Size = 495; 25), на эту панель добавляем Button (Name = «btnStart», Location = 0;0, Size = 75; 23, Text = Начнем), рядом с кнопкой бросаем TextBox (Name = «tbUrl», Location = 84; 2, Size = 244; 20).
В свойствах проекта переключаем конечную платформу на x86.
Теперь приступим к написанию кода.
В using класса главной формы подключаем:
1 |
using Gecko; |
Добавляем приватное поле _webBrowser типа GeckoWebBrowser:
1 |
private readonly GeckoWebBrowser _webBrowser; |
В конструкторе класса главной формы пишем следующее:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public FrmMain() { // инициализация Xulrunner Xpcom.Initialize( Application.StartupPath + "\\xulrunner\\" ); this.InitializeComponent(); this._webBrowser = new GeckoWebBrowser { Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom, Width = this.Width, Height = this.Height - this.pnl1.Height - 5, Top = this.pnl1.Bottom + 5 }; // после загрузки страницы будем менять значение tbUrl, в котором находится текущий урл this._webBrowser.DocumentCompleted += this._webBrowser_DocumentCompleted; // устанавливаем UserAgent браузера в Firefox 22 GeckoPreferences.User[ "general.useragent.override" ] = "Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20130405 Firefox/22.0"; // добавляем контрол браузера на форму this.Controls.Add( this._webBrowser ); } |
Т.е. мы инициализируем движок, указывая путь к движку (у меня он находится в папке с программой). Далее создаем экземпляр класса GeckoWebBrowser (т.е. наш браузер), создаем обработчик события DocumentCompleted (который будет изменять текущий адрес страницы в tbUrl), меняем наш юа и добавляем контрол браузера на форму.
Кстати, вот реализация метода _webBrowser_DocumentCompleted:
1 2 3 4 |
private void _webBrowser_DocumentCompleted( object sender, EventArgs e ) { this.tbUrl.Text = this._webBrowser.Url.ToString(); } |
Настало время написать класс, который будет иметь следующие методы:
- загрузка главной страницы гугла;
- написание произвольного поискового запроса в текстовое поле;
- клик по случайному сайту на странице выдачи.
Добавляем новый класс GoogleExample и следующие поля:
1 2 3 |
private readonly GeckoWebBrowser _webBrowser; // ссылка на браузер private readonly Timer _loadingTimer; // таймер загрузки private bool _loading; // указывает на статус загрузки |
Поле _webBrowser — это ссылка на наш браузер, _loadingTimer через 2000 (т.е. две секунды) миллисекунд будет изменять состояние загрузки страницы и _loading — статус загрузки (этому полю наш таймер будет присваивать значение false).
Незабываем в using подключить следующее:
1 2 3 |
using System.Threading.Tasks; using System.Windows.Forms; using Gecko; |
Теперь напишем конструктор класса GoogleExample:
1 2 3 4 5 6 7 |
public GoogleExample( GeckoWebBrowser webBrowser ) { this._webBrowser = webBrowser; this._webBrowser.CreateWindow2 += this._webBrowser_CreateWindow2; this._loadingTimer = new Timer { Interval = 2000 }; this._loadingTimer.Tick += this._loadingTimer_Tick; } |
Конструктор принимает ссылку на браузер, инициализирует таймер. Также создается обработчик события CreateWindow2. Это событие вызывается перед созданием окна. Нужно нам это событие для того, чтобы «глушить» открытие новых окон при нажатии на ссылку результата на странице выдачи гугла.
1 2 3 4 5 |
private async void _webBrowser_CreateWindow2( object sender, GeckoCreateWindow2EventArgs e ) { e.Cancel = true; await this.Navigate( e.Uri ); } |
В этом событии мы отменяем открытие нового окна и заставляем главное окно перейти на ссылку, которую хотело открыть новое окно.
Реализация события Tick для _loadingTimer:
1 2 3 4 5 |
private void _loadingTimer_Tick( object sender, EventArgs e ) { this._loadingTimer.Stop(); this._loading = false; } |
Все просто: останавливаем таймер и изменяем значение переменной _loading, это значение указывает на статус загрузки страницы.
Реализация метода WaitForLoading:
1 2 3 4 5 6 7 8 9 10 |
/// <summary> /// Ожидает загрузки страницы /// </summary> private async Task WaitForLoading() { while ( this._loading ) { await TaskEx.Delay( 200 ); } } |
Обычный цикл, каждые 200 миллисекунд проверяется статус загрузки страницы.
Реализация метода Navigate:
1 2 3 4 5 6 7 8 9 10 11 |
/// <summary> /// Загружает указанную страницу и ждет завершения загрузки /// </summary> /// <param name="url">Url страницы</param> private async Task Navigate( string url ) { this._loading = true; this._webBrowser.Navigate( url ); this._loadingTimer.Start(); await this.WaitForLoading(); } |
Открываем браузером страницу, запускаем таймер и асинхронно ждем загрузки страницы.
Основные методы готовы. Начнем открывать гугл 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/// <summary> /// Загружает страницу гугла и ждет загрузки /// </summary> public async Task OpenGoogle() { await this.Navigate( "http://www.google.ru/" ); // если гугл выдает нам страницу не на русском и предлагает включить русский, то включаем var aElements = this._webBrowser.Document.GetElementsByTagName( "a" ); this._loading = true; this._loadingTimer.Start(); foreach ( var element in aElements ) { if ( element.InnerHtml.IndexOf( "русском", StringComparison.Ordinal ) >= 0 ) { this._loading = true; element.Click(); this._loadingTimer.Start(); await this.WaitForLoading(); break; } } } |
Метод OpenGoogle загружает главную страницу гугла. Но есть один момент: гугл может быть на английском, потому цикл foreach нужен для того, чтобы пройтись по всем ссылкам на главной странице и найти ту ссылку (если она есть), при нажатии на которую можно переключить язык на русский.
Следующий в очереди метод ввода поискового запроса — WriteQuery.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/// <summary> /// Пишет поисковый запрос /// </summary> /// <param name="query">Поисковый запрос</param> public async Task WriteQuery( string query ) { // получаем все элементы с тегом input var inputsElements = this._webBrowser.Document.GetElementsByTagName( "input" ); // получаем первый input, имя (атрибут "name") которого равно q var queryElement = inputsElements.First( i => i.GetAttribute( "name" ) == "q" ); // "плавный" набор поискового запроса Random random = new Random(); for ( int i = 0; i < query.Length; i++ ) { queryElement.SetAttribute( "value", query.Substring( 0, i + 1 ) ); await TaskEx.Delay( random.Next( 100, 350 ) ); } // получаем все элементы с тегом button var buttonsElements = this._webBrowser.Document.GetElementsByTagName( "button" ); // указываем, что началась загрузка, кликаем по первой кнопке с именем "btnG, запускаем таймер и ждем загрузки страницы this._loading = true; buttonsElements.First( i => i.GetAttribute( "name" ) == "btnG" ).Click(); this._loadingTimer.Start(); await this.WaitForLoading(); } |
Этот метод получает все input‘ы, далее выбирает первый input, который имеет имя «q». Далее запускается цикл, с помощью которого поисковый запрос вводиться побуквенно (типа, реальный пользователь набирает текст :D). После цикла выбираем все button‘ы и кликаем по первому, у которого имя равно «btnG» (это синяя кнопка для поиска) и ждем загрузки страницы.
Ну и последний метод в нашем классе — ClickRandomLink.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/// <summary> /// Эмулирует нажатие на случайной ссылке /// </summary> public async Task ClickRandomLink() { // получаем все элементы с тегом input var aElements = this._webBrowser.Document.GetElementsByTagName( "a" ).ToList(); // получаем все ссылки, у которых значение атрибута "onmousedown" начинается с "return rwt(" List<GeckoHtmlElement> needleLinks = new List<GeckoHtmlElement>(); foreach ( var element in aElements ) { try { if ( element.GetAttribute( "onmousedown" ).StartsWith( "return rwt(" ) && element.GetAttribute( "href" ) .IndexOf( "webcache.googleusercontent.com", StringComparison.Ordinal ) < 0 ) { needleLinks.Add( element ); } } catch { continue; } } Random random = new Random(); this._loading = true; // нажимаем по случайной ссылке needleLinks[ random.Next( needleLinks.Count ) ].Click(); this._loadingTimer.Start(); await this.WaitForLoading(); } |
Собственно, получаем все ссылки, инициализируем список «нужных ссылок» и запускаем цикл по списку всех ссылок, в котором ищем ссылки, атрибут «onmousedown» которых начинается с «return rwt(» и сама ссылка не содержит «webcache.googleusercontent.com» (иначе получим ссылку на сохраненную копию). дофига ща раз было слово «ссылка». Конструкцию try..catch нужно использовать обязательно, т.к. если попытаться получить доступ к несуществующему атрибуту элемента, то движок выбросит исключение. Например, в том же HtmlAgilityPack все по-другому (и, как мне кажется, удобнее): в методе получения атрибута элемента мы заранее указываем, что нам возвращать, если у элемента нет такого атрибута. Ну да ладно 🙂
Возвращаемся к классу формы. Создаем обработчик события Click кнопки btnStart, добавляем к этому методу модификатор async и пишем следующее:
1 2 3 4 5 6 7 |
private async void btnStart_Click( object sender, EventArgs e ) { var testClass = new GoogleExample( this._webBrowser ); await testClass.OpenGoogle(); await testClass.WriteQuery( "создание приложений с поддержкой плагинов c#" ); await testClass.ClickRandomLink(); } |
Ну вот и всё. Можно компилить, тыкать на кнопку и наблюдать результат 🙂
Кстати, исходники можно скачать на GitHub.
Исходники на гитхабе, не рабочие, замените, пожалуйста
Чего в них не рабочего?
Уже разобрался, не было в сборке xullrunnera.
Остался вопрос про контрол. Добавляется он на форму кодом this.Controls.Add( this._webBrowser ); как я понял. Но это очень не гибко. Как можно сделать, чтобы строго определенное место было для него выделено? Есть ли возможность масштабирования содержимого под эти размеры?
Так же интересно, как быть с тегом select. Как выбрать нужный элемент?
Можно попробовать так:
https://gist.github.com/dredei/69af2f47b6c36a48fc70
Код, который выше, должен работать и для тех select‘ов, у которых нет атрибута value в option.
Это пример, так что ожидать от него какой-то гибкости (чтобы сразу скопировал и работало, как нужно), не стоит 😉
На счет размеров, то я, думаю, не сложно поставить точку после this._webBrowser и глянуть, какие у этого объекта есть поля и методы.
Среди них есть такие поля, как Height (высота) и Width (ширина), с помощью которых можно настроить размеры контролла. Также следует установить свойство Anchor в AnchorStyles.Left | AnchorStyles.Top , т.к. в примере с помощью якорей (AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom) контролл «цепляется» ко всем краям формы.
Точно. Спасибо!
Документации, как я понял, нет на него, даже на английском?
Документации нет. Когда-то находил примеры (для 16 версии, вроде) на англ.
Так что метод научного тыка рулит 🙂
Я вижу что Вы очень неплохо разобрались с Geckofx. Подскажите если знаете. По свойству geckoWebBrowser1.Document мы получаем доступ к документу, который был уже распарсен движком. Но бывают случаи когда оригинал исходника веб страницы с сервера, не соответствует OuterHtml. Хотя движок и верно отображает страницу, свойство geckoWebBrowser1.Document уже потеряло некоторые данные и к ним не получить доступ. если сделать geckoWebBrowser1.Navigate («view-source:» + url); то код без потерь, но во первых он отображается на странице, что не всегда нужно, во вторых запрашивается с сервера ещё раз, а в третьих он только выглядит верно, а получить доступ к html документу как? OuterHtml это будет уже не оригинал, туда добавится разметка оформления для вывода кода. Надеюсь вы поняли, что я хочу узнать. Заранее спасибо.
Я не в курсе, как получить оригинал кода, который отдает сервак, с помощью GeckoFx. Т.к. какой смысл таскать за собой такое двигло, если нужно получить просто код (без рендеринга и т.д.), который отдает сервак? Для таких целей есть WebClient 🙂
Спасибо за ответ. Таскать двигло имеет смысл в определенных ситуациях. Цель его использования в конкретной проблеме была не в получении исходного кода, движок используется по назначению. Просто параллельно и такой вопрос возник, чтоб программно обработать данные со страницы. К сожалению в связи со скудным документированием сам ответа не нашел. Согласитесь, раз движок все же используется, то глупо городить костыли и обращаться через WebClient, когда эту конкретную страницу уже получил и отобразил движок. Ладно, будем искать, возможно не все потерянно.
Городить костыли в программировании нужно чуть ли не постоянно 😉 Т.к. не все либы имеют нужный функционал/работают так, как нужно.
Ну, либо портировать (допиливать) этот движок самому с преферансом и поэтессами. Но на это уйдет намного больше времени, чем соорудить костыль.
Также можно попробовать задать вопрос тем, кто портировал двигло здесь.
П.С. На счет view-source. Можно схитрить и получить доступ к коду так:
_webBrowser.Navigate( "view-source: someurl" );
string html = _webBrowser.Document.GetElementsByTagName( "html" )[ 0 ].TextContent;
В теории, должно сработать 🙂
Здравствуйте, не подскажете как в gecko 29 версии изменить дерикторию куки?
Xpcom.ProfileDirectory — меняет только папку кеша а куки остаются стандартно C:\Users\Админ\AppData\Local\Geckofx\DefaultProfile
Спасибо…
Здравствуйте! У меня отлично все меняет. Пишет все данные (кеш, куки и т.д.) профиля туда, куда я и указал.
У версии geckoFX 29,0,6 и выше — куки остаются в стандартной папке!
И еще прошу помощи с авторизацией Proxy по паролю..
Буду ждать ваших коментариев по этому поводу. Спасибо..
Специально только что проверил на 29.0.11 — все данные профиля сохраняются там, где я и указал.
На счет прокси — смотрите пример здесь.
А можно примерчик на почту или ссылку на пример? только без браузера! что не делаю всеравно куки сохраняет в стандартную папку!
сижу уже пару дней, ничего толком не выходит(
Спасибо за быстрые, супер быстрие отзывы…
Спасибо..
В общем, ничего особенного. Делаю так, как вы и писали 🙂
Пример отправил на почту (указываю профиль в конструкторе главной формы).
Низкий поклон вам, все, разобрался)
так работает
Xpcom.ProfileDirectory = Application.StartupPath + «\\bin\\cookie»;
Xpcom.Initialize(Application.StartupPath + «\\xulruner\\»);
так неработало у меня
Xpcom.Initialize(Application.StartupPath + «\\xulruner\\»);
Xpcom.ProfileDirectory = Application.StartupPath + «\\bin\\cookie»;
в чем разница такого события? раньше все работало до обновления версии.
Сасибо, ваш пример решил мою проблему…
Фиг знает, почему раньше работало. Может, те, кто портировали новую версию что-то изменили или это изменения в самом движке.
В принципе, логично, что сначала указывает профиль, а потом инициализируем движок (так как раз Лиса и работает: сначала выбираем профиль, а потом уже запускается браузер).
Хорошо что хорошо все решилось. Для этого буду знать куда вертеть))
Спасибо за ответы. буду внимательно читать ваш блог.
с автоматической авторизацией прокси по паролю разобрался. если нужно будет кому-то пример то через админа будет можно взять пример.
Спасибо еще раз..
Не за что, удачного кодинга 😉
Здравствуйте, столкнулся с проблемой. Открытия окон в новой вкладки, неработает с некоторыми сайтами, в основном с многими. Вот навожу пример с одним из сайтов — http://123.sovetam.ru Во время подписки выскакивает новая вкладка, но сайт сообщает об ошибке. Если не блокировать окно то подписка проходит нормально! Пробовал подставлять реферер но толку мало, хоча на некоторых из кликовых спонсоров, клики по ссылкам, открытие в новом окне, реферер помог! Без реферера клики тоже непроходили!!!
Прошу помощи, так как это является большой проблемой с использованием геско вкладки. Спасибо.. Буду ждать ответа.
Просто происходит не просто открытие окна, а еще и отправка post-запроса, потому и сообщает об ошибке.
Здесь уже нужно сидеть и копать (и гуглить :)), у меня сейчас времени на это нет, занят другим проектом.
У меня такой вопрос странный. Не могу разобраться как работает ваша синхронизация? Как узнать что страница полностью прогрузилась и с ней можно дальше работать?
с обычным компонентом webBrowser я проверял на ReadyState, если он completed то идем дальше.
Но тут как то не могу разобраться, подскажите, а?)
Здесь таймер, который меняет состояние булевой переменной (_loading) по истечению 2 секунд после начала загрузки страницы. Переменные подписаны комментариями, не сложно в студии выбрать нужную переменную и юзануть «Find Usages», чтобы увидеть места, где она используется/изменяется ее состояние.
Ни в одном из компонентов нельзя четко определить полную загрузку страницы, т.к. сейчас сайты напичканы кучей js скриптов, которые после загрузки документа могут много чего изменить на странице и это фиг отловишь. С одними сайтами DocumentCompleted работает идеально, с другими — вечная загрузка, а третьи вообще на одном аяксе. Так что лучше делать всякие «комбо» из таймеров, метода DocumentCompleted и свойства IsBusy.
я просто не нашел зависимости таймера и загрузки. он просто меняет переменную и говорит, что страница загрузилась через 2 секунды? а если она не успела загрузиться за это время?
или я что то упустил?
В данном примере таймер решает: загрузилась страницы или нет 🙂 Это же пример, лень было что-то «мега-крутое» для простого примера делать.
А если она не успела загрузится, то работа продолжиться с не загруженной страницей.
ага, я понял. Спасибо.
а может подскажите еще какие сторонние компоненты, в которых это решается более просто, при мопощи методов и свойств?
проблема стандартного веб-браузера в том, что он почему то не перегружает содержимое документа, вообще никак. (как загрузил после первой навигации, так и все)
я так понял в Gecko с этим все ок, вот только нужно костылить с синхронизацией?
Я ниже описал, что ни в одном компоненте (с которым я сталкивался 🙂 ) нельзя одним методом/событием определить полную загрузку страницы (еще в Делфи 7 и выше с этой фигней сталкивался и перепробовал еще тогда кучу компонент). Даже обычный браузер (Хром, Лиса) не может этого сделать 🙂
А костыль с загрузкой достаточно простой: используем таймер и проверку свойства IsBusy. Таймер «заводим» на, например, 10 секунд, при срабатывании таймера меняется значение переменной _loading в false.
А в методе открытия ссылки, где происходит ожидание загрузки страницы, делаем простой цикл:
while (_wb.IsBusy && _loading)
{
// ждем
}
_loadingTimer.Stop();
// работаем со страницей
Использовать таймер в любом случае нужно, т.к. может какой-то скрипт какого-то нафиг ненужного счетчика, который загружается синхронно, «повешать» страницу (т.е. будет грузиться вечно или очень долго) и в итоге программа будет ждать, как Хатико 🙂
П.С. Считаю GeckoFX самым нормальным двиглом для C#. Сталкивался с портом Хромиума (уже не помню, как называется), но там всё печально. Нужно лепить «обертку» для работы с элементами страницы на JavaScript, а в GeckoFX уже из коробки реализованы классы веб-элементов, сделана удобная работа с ними и т.п.
Хорошо. Спасибо за помощь=)
Доброе утро.
Спасибо за прекрасную статью. Прошу прощения за мои вопросы (так как моих познаний не хватило решить проблему) 1. не подскажите как вывести ScrollBar, а то приходиться активировать приватное поле, потом листать клавишами? 2. Еще не плохо было бы для полного счастья, увидеть код для прокрутки открытой страницы программно.
1. Никаких публичных полей, для активации скролла, я не видел. Возможно, в новых версиях добавили;
2. Знаю несколько возможностей скроллить программно: введите _webBrowser.Window.Scr и выберите нужный метод, который предложит студия; также у класса GeckoHtmlElement есть метод ScrollIntoView.
Спасибо за подсказку, получилось сделать прокрутку страницы программно по Вашему совету. К стати вывод скролла можно решить с помощью Вашей статьи (http://www.softez.pp.ua/2014/02/23/tabs-in-geckofx-c-sharp/#comment-1352) путем добавления TabControl и размещения на него компонента GeckoWebBrowser.
Еще, при переходе с поисковика на сайт в данном Вашем примере, фиксируется прямой заход на сайт, а не переход с поисковика. Так вот как можно с эмитировать нажатие кнопкой мышки или выполнение js «onmousedown=»return rwt(this,…)»
Вот здесь же эмуляция нажатия по ссылке:
needleLinks[ random.Next( needleLinks.Count ) ].Click();
Да совершенно верно вы правильно указали переход по случайной ссылки, даже переходит как требуется на сайт, но вот проблема при проверки перехода на нужный сайт, сам переход в счетчиках ну типа яндекс метрика, не зачитывается как переход с поисковика, а идет как прямой заход на сайт.
Передачу реферера при эмулировании события нажатия на ссылку не проверял (на досуге проверю). Если действительно не передает — тогда писать разработчикам порта 🙂 Возможно, исправят. Или самому разбираться в коде и исправлять.
Здравствуйте, Вот пытаюсь решить проблему с эмуляцией событий от мыши в геско. побродил по форумах но так походящей инфы под новые версии геско ненашел(. Вот собствено вопрос, как эмулировать клик мыши по ссылкам которые генерируются только реальной мышкой? буду благодарен за любые направления в этом.
Вот пример, нужно кликнуть на ссылку прослушать — https://translate.google.com/#ru/ru/Привет%20мир!
Не в курсе, было желание разобраться (или, хотя бы, сделать попытку :)), но так руки и не дошли. Если найду время и разберусь — напишу отдельную статью. Думаю, копать нужно в сторону WinAPI’шных функций типа SendMessage и т.п.
Наткнулся на какой-то исходник на Java, что-то похожее на эмуляцию мыши есть. На досуге посмотрю, самому интересно 🙂
Приветсвую, вот на яве рабочий пример:
function d ()
{
var event = document.createEvent(‘MouseEvents’);
event.initMouseEvent(‘click’, true, true, window, 1, 10, 10, 10, 10, false, false, false, false, 0, null);
document.getElementById(‘idid’).dispatchEvent(event);
}
Вот думаю пробовать вшить в геско. Пробовал слать SendMessage все получилось, правда когда сворачиваю приложение то кликает не на всех сайтах. Причина пока неизвесна, но сделал через нулевую прозрачность формы, так то все работает отлично, кликает без реальной мыши. Правда, скрывать форму не очень правильно. Хочу разобратся в чем собсвенно дело. Если есть время подключайтесь к поиску решения этой проблемы..
JavaScript это, а не Java 🙂
Метрика как реагирует на движение мышью?
Кстати, код, который выше на js, удалось мне «нативно» в GeckoFx реализовать, даже метрика фиксирует, но пока есть еще пару багов.
Чтобы разобраться в чем дело, то нужно, хотя бы, на код посмотреть.
Сообшение было обрезано!!!! код хтмл не отобразился в сообщение!!! ссылки были обрезаны, прошу дать скайп для общения или включите аську!!!
В аське мне постоянно мозги парят по разному поводу, а времени у меня не так много. Потому туда захожу редко.
Для передачи кода есть классная штука: https://gist.github.com/
Еще одно, я когда то спрашивал как правильно перенаправить окно, потому что правильно оно не перенаправляет. Вы говорили что нада еще и пост-запросы! но оказалось все намного проще. Я сделал вот так:
private void webBrowser_CreateWindow2(object sender, GeckoCreateWindow2EventArgs e)
{
if (checkBox1.Checked == false)
{
this.AddTab();
GeckoWebBrowser webBrowser = this.GetWebBrowserByActiveTab();
e.WebBrowser = webBrowser;
}
if (checkBox1.Checked == true)
{
GeckoWebBrowser webBrowser = this.GetWebBrowserByActiveTab();
e.WebBrowser = webBrowser;
}
}
Окно блокировать не нада! его нада просто было перенаправить так — e.WebBrowser = webBrowser
в моем примере я ставлю птичку и страничка отображается в том же окне, если птичка снята то страничка открывается в новой вкладке! Все писано по вашим примерах «вкладки геско».
вот код по SendMessage клика
https://gist.github.com/anonymous/d35b6d7e680cdc9a64f4
Смысл того что оно то кликает, но т а к . р у клик блокирует. значит не все там гладко, нужно разобраться в этом. Буду ждать ответы по этому поводу. Спасибо…
Все, разобрался). нужно добавить еще MOUSEMOVE. все заработало на ура. только осталось решить почему не срабатывает в свернутом состоянии!
Вообще не срабатывает, когда свернуто? Возможно, просто приостанавливается поток браузера, когда приложение свернуто.
Спасибо за направление мыслей с кликом мышки разобрался, даже с перемещением курсора мыши, осталось узнать как найти координаты нужного объекта по которой необходимо кликнуть мышкой.
Ну если вы разобрались, то поделитесь с людьми. Сюда часто захаживают пользователи, которые интересуются работой с геко.
И вопрос: как метрика реагирует на движение мышью, реализованное на WINAPI?
П.С. Возможно, скоро напишу статью, как работать с мышью (только там другой алгоритм), если тесты покажут положительный результат.
Я думаю чужие идеи как за свои не стоит выдавать, всю работу мышкой брал от сюда http://www.cyberforum.ru/csharp-beginners/thread290438.html, движение курсора мышки «mouse_event(MouseFlags.Absolute | MouseFlags.Move, x, y, 0, UIntPtr.Zero);» задал тупо в цикле — изменением координат. Метрику еще не проверил, так как нужно привязаться к нужному объекту(ссылке по координатам монитора). Да еще программная работа мышки ни как не привязана к окну самой программы(браузера), она выполняет действие пользователя компа, т.е. если свернуть окно браузера — мышь продолжает свою работу на активировавшимся новом окне(к примеру если был ранее открыт Ворд, значит в окне Ворда).
Так это же не виртуальная мышь. На такое метрика реагировать будет нормально.
admin
23.04.2015 at 13:45
Так это же не виртуальная мышь. На такое метрика реагировать будет нормально.
Александр
Ага, тут вопрос поднят как кликать мышкой в свернтом состоянии!!!
Кликал по ссылкам, которые четко генерируются жава-скрипт — все работает как часики). В свернутом состоянии не работает! Буду ломать голову дадее.. Видел програмы написанны на геско в которых применяется такая функция как реальный клик мыши в свернутом состоянии, вот и решил покопать. Это нужная вещь, правда не хочется чтобы этим зловредсвували! Админ, Спасибо за ответы!
Вы почитайте, что это за функция и сразу отпадет вопрос, как имитировать события мыши на свернутых окнах.
П.С. В общем, походу, я разобрался, как «нативно» с помощью GeckoFx эмулитовать события мыши (клики, движения). Работает даже здесь https://translate.google.com/#ru/ru/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80 (кнопка «Прослушать»), в свернутом состоянии и даже метрика фиксирует все это. Думаю, напишу статью когда-то 😀
2П.С. Название движка читается, как геко 🙂