TWebBrowser в Thread
//хмм. хотя вроде у меня заработал...
а что конкретно не получается?
//хмм. хотя вроде у меня заработал...
а что конкретно не получается?
после первого NavigateWait(URL) READYSTATE_COMPLETE не дождешься, а если пропустить дальше, после второго вызова NavigateWait ввобще что то странное твориться начинает, страничка вроде загружается, но толи не полностью, толи не правильно, потому что теги нужные не находятся, хотя эта процедура отлажена в основной программе и работает. При уничтожении Thread вылезает Access violetion в модуле mshtml.dll
А окно как правильно создать и подцепить к нему webbrowser?
Спасибо за ответ
А куда деваться, я бы с радостью IdHTTP юзал, но мне javascript нужно чтобы выполнялись
А подробней пожалуйста, желательно кусочек кода?
Для теста нажимаете кнопку Create и затем Test
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, где ошибся?
мы же блокируем поток, надо чтобы сообщения отрабатывались, иначе загрузка в WebBrowser не пойдет и ReadyState никогда не изменится. лучше только наверное заменить на while PeekMessage do DispatchMessage
o_serg
TThread я вообще не вкуриваю чем хорош и в чем его смысл, когда есть WinAPI. И всегда если очень надо то можно написать свою класс-обертку.
попробую понять что тут не так.
только что проверил, работает так:
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;
и большую часть кода наверное лучше вынести в конструктор
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 onload="alert(''blabla'')"></body></html>');
HtmlDoc.write(PSafeArray(TVarData(HtmlText).VArray));
HtmlDoc.close();
// делаем что хотим с HtmlDoc
// ...
MessageBoxW(Handle, PWideChar(HtmlDoc.title), '', MB_OK);
// ...
// CoUninitialize();
end;
Можно последний вопросик? Может подскажешь как flash удалить, я еще когда TWebBrowser использовал мучался с этим вопросом :( Чего только не пробовал, и вручную вырезал тэги <object> на OnDocumentComplete - не помогает. Это вообще реально сделать? Еще я думал что flash это ActiveX ?, но DLCTL_NO_RUNACTIVEXCTLS не помогает отключить...
P.S. я еще подумал, flash ведь как плагин в ИЕ работает, если есть возможность выключать программно плагины? может получиться его отключить
При загрузке страницы иногда вылезают сообщения типа "Ошибка скрипта .... Продолжить выполнение?" с кнопками Да, Нет. Если включить режим SILENT браузера, то сообщения эти не вылезают, но скрипты перестают выполняться вообще, даже если перейти на другую страницу! Как побороть это безобразие? или кнопку "Да" нажимать программно?
P.S. Еще есть совсем непонятные глюки, например http://www.ps3newz.ru/, вылетает access violetion в модуле mshtml.dll и после этого ни одна страница больше грузиться. В ИЕ сайт открывается, но вылезает ошибка "Ошибка на данной странице может привести к нестабильной работе", может что то подскажете, что с этим делать?