Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

TWebBrowser в Thread

578
09 марта 2010 года
o_serg
93 / / 08.09.2003
Добрый день, подскажите пожалуйста можно ли в потоке (Thread) запустить TWebBrowser ? В инете подобных вопросов море, но ответа я так и не нашел.
8.2K
09 марта 2010 года
bagie2
299 / / 26.10.2008
можно попробовать создать немодальное (и если надо то невидимое) окно и на нам WebBrowser. он как как то привязывается к очереди сообщений потока и окну, поэтому просто так его не удается создать.

//хмм. хотя вроде у меня заработал...
а что конкретно не получается?
578
09 марта 2010 года
o_serg
93 / / 08.09.2003
Цитата: bagie2
можно попробовать создать немодальное (и если надо то невидимое) окно и на нам WebBrowser. он как как то привязывается к очереди сообщений потока и окну, поэтому просто так его не удается создать.

//хмм. хотя вроде у меня заработал...
а что конкретно не получается?



после первого NavigateWait(URL) READYSTATE_COMPLETE не дождешься, а если пропустить дальше, после второго вызова NavigateWait ввобще что то странное твориться начинает, страничка вроде загружается, но толи не полностью, толи не правильно, потому что теги нужные не находятся, хотя эта процедура отлажена в основной программе и работает. При уничтожении Thread вылезает Access violetion в модуле mshtml.dll
А окно как правильно создать и подцепить к нему webbrowser?
Спасибо за ответ

303
09 марта 2010 года
makbeth
1.0K / / 25.11.2004
VCL - однопоточная библиотека. Как не извращайся, без глобального перепиливания не обойтись. Проще забить ;)
14
09 марта 2010 года
Phodopus
3.3K / / 19.06.2008
Или создавать окно с браузером на чистом WinAPI...
578
09 марта 2010 года
o_serg
93 / / 08.09.2003
Цитата:
VCL - однопоточная библиотека. Как не извращайся, без глобального перепиливания не обойтись. Проще забить


А куда деваться, я бы с радостью IdHTTP юзал, но мне javascript нужно чтобы выполнялись

Цитата: Phodopus
Или создавать окно с браузером на чистом WinAPI...



А подробней пожалуйста, желательно кусочек кода?

8.2K
09 марта 2010 года
bagie2
299 / / 26.10.2008
погодите. я уже почти написал пример. я так понял вам надо невидимый WebBrowser?
578
09 марта 2010 года
o_serg
93 / / 08.09.2003
Мне нужно в потоке WebBrowser, для того чтобы параллельно несколько URL загрузить и обработать
8.2K
09 марта 2010 года
bagie2
299 / / 26.10.2008
http://sources.codenet.ru/download/3561/WebBrowserInThread.html

Для теста нажимаете кнопку Create и затем Test
303
09 марта 2010 года
makbeth
1.0K / / 25.11.2004
А нафига Application.ProcessMessages в потоке???
578
09 марта 2010 года
o_serg
93 / / 08.09.2003
Спасибо, думаю то что нужно. Пытаюсь это прикрутить к TThread:
Код:
TWPThread = class(TThread)
  private
    FURLString: string;
    wb: IWebBrowser2; // бразуер
    wHandle: HWND; // handle созданного окна
  protected
    procedure Execute; override;
  end;

----

function MsgOnlyWindowProc(hwnd: HWND; uMsg: UINT;
  wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Result := DefWindowProc(hwnd, uMsg, wParam, lParam);
end;

procedure ProcessMessage( wHandle: HWND );
var
  Msg: TMsg;
begin
  while PeekMessage(Msg, wHandle, 0, 0, PM_REMOVE) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;                    
end;

procedure TWPThread.Execute;
var
  WndClass: TWndClassEx;
  ForegroundWindow: HWND;
  k: Integer;
begin
  ForegroundWindow := GetForegroundWindow();

  FillChar(WndClass, SizeOf(WndClass), 0);
  with WndClass do
  begin
    cbSize := SizeOf(WndClass);
    lpszClassName := 'MESSAGE_ONLY_WINDOW';
    lpfnWndProc := @MsgOnlyWindowProc;
  end;
  RegisterClassEx(WndClass);

  wHandle := CreateWindowEx(0, WndClass.lpszClassName, nil,
    0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, nil);
  if (wHandle = 0) then
    raise Exception.Create('CreateWindowEx');

  SetForegroundWindow(ForegroundWindow);

  try

    CoInitializeEx(nil, COINIT_APARTMENTTHREADED);

    if (CoCreateInstance(CLSID_InternetExplorer, nil, CLSCTX_INPROC_SERVER,
      IID_IWebBrowser2, wb) <> S_OK) then
      raise Exception.Create('CoCreateInstance');
    try

      AtlAxAttachControl(wb, wHandle, nil);

      wb.Navigate( PAnsiChar( 'http://ya.ru' ), EmptyParam, EmptyParam, EmptyParam, EmptyParam ) ;

      while ( wb.ReadyState < READYSTATE_COMPLETE ) do
      begin
        k := wb.ReadyState;
        ProcessMessage( wHandle ); sleep( 2 );
      end;

      res :=  ( wb.Document as IHTMLDocument2 ).body.innerHTML;

    finally
      wb := nil;
    end;

  finally
    DestroyWindow(wHandle);
  end;
end;


Readystate всегда loading, где ошибся?
8.2K
09 марта 2010 года
bagie2
299 / / 26.10.2008
Цитата:
А нафига Application.ProcessMessages в потоке???


мы же блокируем поток, надо чтобы сообщения отрабатывались, иначе загрузка в WebBrowser не пойдет и ReadyState никогда не изменится. лучше только наверное заменить на while PeekMessage do DispatchMessage

o_serg
TThread я вообще не вкуриваю чем хорош и в чем его смысл, когда есть WinAPI. И всегда если очень надо то можно написать свою класс-обертку.

попробую понять что тут не так.

только что проверил, работает так:

Код:
procedure TWPThread.Execute;
var
  WndClass: TWndClassEx;
begin
  FillChar(WndClass, SizeOf(WndClass), 0);
  with WndClass do
  begin
    cbSize := SizeOf(WndClass);
    lpszClassName := 'MESSAGE_ONLY_WINDOW';
    lpfnWndProc := @DefWindowProc;
  end;
  RegisterClassEx(WndClass);

  wHandle := CreateWindowEx(0, WndClass.lpszClassName, nil,
    0, 0, 0, 0, 0, DWORD(HWND_MESSAGE), 0, 0, nil);
  if (wHandle = 0) then
    raise Exception.Create('CreateWindowEx');

  try

    CoInitializeEx(nil, COINIT_APARTMENTTHREADED);

    if (CoCreateInstance(CLSID_InternetExplorer, nil, CLSCTX_INPROC_SERVER,
      IID_IWebBrowser2, wb) <> S_OK) then
      raise Exception.Create('CoCreateInstance');
    try

      AtlAxAttachControl(wb, wHandle, nil);

      wb.Navigate('http://ya.ru', EmptyParam, EmptyParam, EmptyParam, EmptyParam) ;

      while (wb.ReadyState <> READYSTATE_COMPLETE) do
      begin
        while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do DispatchMessage(Msg);
        Sleep(1);
      end;

      MessageBoxW(0, PWideChar((wb.Document as IHTMLDocument2).title), '', 0);

    finally
      wb := nil;
    end;

  finally
    DestroyWindow(wHandle);
  end;
end;


и большую часть кода наверное лучше вынести в конструктор
578
10 марта 2010 года
o_serg
93 / / 08.09.2003
bagie2, спасибо огромное, буду пробовать :)
8.2K
10 марта 2010 года
bagie2
299 / / 26.10.2008
вот еще проще метод нашел. HTML код загружаем сами и потом выполняем это. JavaScript работает.

Код:
uses
  ActiveX, MSHTML, Variants;

const
  CLSID_HTMLDocument: TCLSID = '{25336920-03F9-11CF-8FD0-00AA00686F13}';
  CLSID_MHTMLDocument: TCLSID = '{3050F3D9-98B5-11CF-BB82-00AA00BDCE0B}';

procedure TForm1.Button1Click(Sender: TObject);
var
  HtmlDoc: IHTMLDocument2;
  HtmlText: Variant;
begin
  // надо расскомментировать, если код будет выполняться в отдельном потоке
  // CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
   
  if (CoCreateInstance(CLSID_HTMLDocument, nil, CLSCTX_INPROC_SERVER,
    IID_IHTMLDocument2, HtmlDoc) <> S_OK) then
    raise Exception.Create('Cannot initialize HTMLDocument.');
         
  HtmlText := VarArrayCreate([0, 0], varVariant);
  HtmlText[0] := WideString('<html><head><title>Vasya</title></head><body &#111;&#110;load="alert(''blabla'')"></body></html>');
  HtmlDoc.write(PSafeArray(TVarData(HtmlText).VArray));
  HtmlDoc.close();
 
  // делаем что хотим с HtmlDoc
  // ...
  MessageBoxW(Handle, PWideChar(HtmlDoc.title), '', MB_OK);
  // ...

  // CoUninitialize();
end;
8.2K
10 марта 2010 года
bagie2
299 / / 26.10.2008
Кстати эта идея мне понравилась. Сделал калькулятор, который использует JavaScript =)

http://sources.codenet.ru/download/3566/JavaScriptCalc.html
578
14 марта 2010 года
o_serg
93 / / 08.09.2003
bagie2, спасибо огромное все получилось. Только теперь не понимаю как выключить загрузку картинок, звуков и т.п. В инете полно примеров как это сделать для TWebBrowser, а что делать с IWebBrowser2 ?
578
15 марта 2010 года
o_serg
93 / / 08.09.2003
Супер, спасибо!
Можно последний вопросик? Может подскажешь как flash удалить, я еще когда TWebBrowser использовал мучался с этим вопросом :( Чего только не пробовал, и вручную вырезал тэги <object> на OnDocumentComplete - не помогает. Это вообще реально сделать? Еще я думал что flash это ActiveX ?, но DLCTL_NO_RUNACTIVEXCTLS не помогает отключить...
8.2K
15 марта 2010 года
bagie2
299 / / 26.10.2008
Если честно то сходу не скажу. Но оба флага DLCTL_NO_RUNACTIVEXCTLS + DLCTL_NO_DLACTIVEXCTLS установлены?

И вот ссылка по флагам. Вообще пригодится. http://www.bsalsa.com/ewb_down_opt.html
578
15 марта 2010 года
o_serg
93 / / 08.09.2003
Да флаги оба установлены, ссылку посмотрю. Проблема в том что видимо нет события которое вызывается до начала загрузки всех объектов на странице (картинок, flash, ... ), чтобы можно было вырезать тэг, до того как эксплорер начнет его загружать. Я нашел исходники плагина для ИЕ на С++, для выключения flash, но там тоже находятся тэги <object> и устанавливается свойство hidden=true, как я понял flash все равно загружается. Очень хочется что то придумать, т.к. это лишний трафик и иногда вылезают ошибки которые выдает flash player, несмотря на то что стоит wb.Silent:=true и DLCTL_SILENT.
P.S. я еще подумал, flash ведь как плагин в ИЕ работает, если есть возможность выключать программно плагины? может получиться его отключить
578
22 марта 2010 года
o_serg
93 / / 08.09.2003
Снова ищу совета, т.к. ИЕ просто выносит мозг!
При загрузке страницы иногда вылезают сообщения типа "Ошибка скрипта .... Продолжить выполнение?" с кнопками Да, Нет. Если включить режим SILENT браузера, то сообщения эти не вылезают, но скрипты перестают выполняться вообще, даже если перейти на другую страницу! Как побороть это безобразие? или кнопку "Да" нажимать программно?
8.2K
22 марта 2010 года
bagie2
299 / / 26.10.2008
я уже давал ссылку там надо повесить свой обратчик ошибок ICustomDoc.SetUIHandler (сам класс в модуле HTMLDocCustomUI) и отладка скриптов должна быть выключена в настойках IE
578
22 марта 2010 года
o_serg
93 / / 08.09.2003
Спасибо, работает. Только когда грузишь поочереди несколько сайтов функцией Navigate оно вроде перестает работать. SetUIHandler после каждого navigate нужно делать, или я где-то ошибся?

P.S. Еще есть совсем непонятные глюки, например http://www.ps3newz.ru/, вылетает access violetion в модуле mshtml.dll и после этого ни одна страница больше грузиться. В ИЕ сайт открывается, но вылезает ошибка "Ошибка на данной странице может привести к нестабильной работе", может что то подскажете, что с этим делать?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог