Форум: "Прочее";
Текущий архив: 2011.02.20;
Скачать: [xml.tar.bz2];
ВнизКак отследить события в Internet Explorer Найти похожие ветки
← →
hattak © (2010-11-09 17:28) [0]Опять, господа, у меня вопрос про IE)))
Проблема - нужно отследить возникновение некоторых событий в Веб-странице, загруженной в IE. Например, в частности onPropertyChange на слое (DIV). Суть в том, что мне из программы нужно узнать, когда обновилось содержимое DIV через свойство innerHTML. Для этого как раз и нужно отследить возникновение onPropertyChange.
Как я сделал ... долго думал и искал и придумал только сделать часть своей программы ActiveX сервером и описать в нём метод, который будет вызывать событие onPropertyChange из Web-страницы, обработчик же onPropertyChange програмно вешать на этот DIV ...
Делаю так: получаю IHTMLDocument2 страницы, ну скажем:
IE.Document.QueryInterface(IHTMLDocument2, iDoc);
далее вешаю обработчик используя скрипт на javascript и метод attachEvent:
iDoc.parentWindow.execScript("function runc() { var coms = new ActiveXObject("MyProg.MyInterface"); coms.doDIVControl(); } document.getElementById("msg").attachEvent("onpropertychange", runc);","javascript");
т.е. я вызываю из своей программы скрипт на JS, который и вешает на DIV с ID"ом msg функцию runc(), при вызове которой, как видно, создаётся элемент ActiveX из моей программы и из него вызывается функция doDIVControl() - таким образом моя программа узнаёт, что в Web-странице возникло событие onpropertychange ... вот)))
а теперь вопрос, можно ли решить мою задачу каким-то иным путём?
например, у нитерфейса IHTMLDocument2 есть куча методов on..... onClick, скажем и т.п. а как ими пользоваться-то? я не понимаю никак, или они там только для "красоты" и через них можно только узнать есть ли обработчик событий вообще или нет ... ?))
Вот, подскажите, может есть у кого-то идеи, а то в моём варианте есть значительные минусы, требуется каждый раз приаттачивать обработчик, при обновлении страницы, требуется смена настроек безопасности, для создания activex элемента и т.п. ...
← →
brand (2010-11-09 17:46) [1]>а как ими пользоваться-то?
Согласно документации, нужно имплементировать IDispatch с методом по умолчанию, который и будет обработчиком события (указатель на инстанс вашей реализации и нужно передать в метод onclick).
А вообще, дичайшей ересью вы, по-моему, занимаетесь.
← →
hattak © (2010-11-09 17:59) [2]ересь ... хммм, хорошо, посоветуйте ... есть копроративный чат, сделан так, что сообщения в него когда приходят обновляются не документы во фрейме, т.е. никаких FrameNavigateComplete и т.п. а именно обновляется документ внутри, через innerHTML. Требуется написать плагин, который будет перехватывать эти сообщения, в лог их складывать, когда приходит новое и оповещать об этом пользователя. Чат сделан именно в вибе веб-страницы, в фрейме (повторяю, фрейм не обновляется), изменить код самого чата никак нельзя, т.е. это разработка зарубежного отделения компании ... как же это ещё решить, если не такой вот "ересью" ?))
я за другие варианты, дайте идею)))
← →
hattak © (2010-11-09 19:59) [3]не, не въезжаю, хоть убейте!)))
вообще, я нашёл в методах IHTMLDocument3 собственно функцию
attachEvent(const event WideString; pdisp:IDispatch):boolean;
т.е. если я получаю интерфейс
IE.Document.QueryInterface(IHTMLDocument3, iDoc);
то по идее
iDoc.attachEvent("onpropertychange",???); - должно делать тоже, что делаю я через JS, но там DISP функции ... я должен как указать, что должна вызываться моя функция doDIVControl; ? я что-то совсем запутался ((
unit MyInt;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses ComObj, ActiveX, AspTlb, MyInterface_TLB, StdVcl, Dialogs;
type
TMyInterface = class(TASPMTSObject, IMyInterface)
protected
procedure doDIVControl; safecall;
end;
implementation
uses ComServ, MainForm_Unit;
procedure TMyInterface.doDIVControl;
begin
..............................
end;
initialization
TAutoObjectFactory.Create(ComServer, THaddanInterface, Class_MyInterface, ciMultiInstance, tmApartment);
end.
unit MyInterface_TLB;
{$TYPEDADDRESS OFF}
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface
uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;
const
MyInterfaceMajorVersion = 1;
MyInterfaceMinorVersion = 0;
LIBID_MyInterface: TGUID = "{CFEA4581-435A-4175-8303-4AEC0D1599CC}";
IID_IMyInterface: TGUID = "{79B819AC-A318-4FD6-9693-229032395110}";
CLASS_MyInterface: TGUID = "{632190B3-ABFA-4B80-AFBA-B8F504680CB1}";
type
IMyInterface = interface;
IMyInterfaceDisp = dispinterface;
MyInterface = IMyInterface;
IMyInterface = interface(IDispatch)
["{79B819AC-A318-4FD6-9693-229032395110}"]
procedure doDIVControl; safecall;
end;
IMyInterfaceDisp = dispinterface
["{79B819AC-A318-4FD6-9693-229032395110}"]
procedure doDIVControl; dispid 201;
end;
CoMyInterface = class
class function Create: IMyInterface;
class function CreateRemote(const MachineName: string): IMyInterface;
end;
implementation
uses ComObj;
class function CoMyInterface.Create: IMyInterface;
begin
Result := CreateComObject(CLASS_MyInterface) as IMyInterface;
end;
class function CoMyInterface.CreateRemote(const MachineName: string): IMyInterface;
begin
Result := CreateRemoteComObject(MachineName, CLASS_MyInterface) as IMyInterface;
end;
end.
← →
DiamondShark © (2010-11-09 20:11) [4]
> hattak © (09.11.10 19:59) [3]
Пишешь класс , реализующий интерфейс IDispatch, в метод attachEvent передаёшь экземпляр этого класса.
Когда срабатывает событие, будет вызван метод Invoke.
← →
hattak © (2010-11-09 20:38) [5]хорошо:
type
TMyN = class(TObject, IUnknown, IDispatch)
private
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
end;
var TN:TMyN;
implementation
function TMyN._AddRef: Integer;
begin
Result := 1;
end;
function TMyN._Release: Integer;
begin
Result := 1;
end;
function TMyN.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
Result := S_OK;
end;
function TMyN.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
begin
Result := E_NOTIMPL;
end;
function TMyN.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
begin
Pointer(TypeInfo) := nil;
Result := E_NOTIMPL;
end;
function TMyN.GetTypeInfoCount(out Count: Integer): HResult;
begin
Count := 0;
Result := S_OK;
end;
function TMyN.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
begin
showmessage("OK");
end;
........................
procedure TMainForm.ToolButton9Click(Sender: TObject);begin
begin
frmDoc3.attachEvent("onmousemove",TN);
end;
..............................
не работает событие, хотя результат attachEvent = true, типа повесилось, а не срабатывает (((( в чём дело может быть?
← →
DiamondShark © (2010-11-09 21:15) [6]
> в чём дело может быть?
Что-то не видно, где создаётся экземпляр TMyN
function TMyN._AddRef: Integer;
begin
Result := 1;
end;
function TMyN._Release: Integer;
begin
Result := 1;
end;
function TMyN.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
Result := S_OK;
end;
Бред.
type
TMyN = class(TIntefacedObject, IDispatch)
private
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
end;
procedure TMainForm.ToolButton9Click(Sender: TObject);begin
begin
frmDoc3.attachEvent("onmousemove",TMyN.Create as IDispatch);
end;
← →
hattak © (2010-11-09 21:35) [7]_AddRef, _Release, QueryInterface относится тут к IUnknown, это как бы не бред, просто не выкинул из кода, но они не на что тут и не влияют как бы
потомок должен быть от TIntefacedObject, а что это за класс, откуда он ? первый раз слышу и инфы не вижу нигде
← →
hattak © (2010-11-09 21:44) [8]так, голова кипит уже TMyN = class(TInteRfacedObject, IDispatch) ))))))))))))))))))
← →
hattak © (2010-11-09 21:48) [9]да, так работает, спасибо!
хотя задача основная так и остаётся не решённой,
слой (DIV) же нельзя получить как IHTMLDocument3, а значит на него нельзя таким образом повесить и обработчик ... или опять же я что-то упустил?)))
← →
brand (2010-11-09 21:57) [10]hattak © (09.11.10 21:48) [9]
GUI эвенты от нодов должны через эвент бабблинг всплывать до документа, и теоретически обработчик документа должен отрабатывать. Но неизвестно, всплывают ли DOM эевенты, нужно экспериментировать.
← →
hattak © (2010-11-09 22:11) [11]у меня вполне заработало вот так
frmDoc3.getElementById("msg").onclick := TMyN.Create as IDispatch;
именно на слой событие, но там нет нужного onpropertychange ... может его назвали как-то иначе, щас все перекопаю))
← →
brand (2010-11-09 22:22) [12]hattak © (09.11.10 22:11) [11]
Можно попробовать прицепить onPropertyChange к самому документу, если DOM эвенты всплывают, то это должно работать.
А по поводу альтернативных идей, если можно изменять javascript (а насколько я понимаю, можно) то в плагине можно устроить локальный сервер на NNNN порту, и сабмитить туда скрытую форму из обработчика javascript, javascript-ом же вставленную в документ (но опять же не ручаюсь насколько это будет работать касательно настроек безопасности).
← →
hattak © (2010-11-09 23:02) [13]не, не всплывает, однако нашёл решение
var e:IHTMLElement2;
e := HaddanFrames[1].frmDoc3.getElementById("msg") as IHTMLElement2;
e.onpropertychange := TMyN.Create as IDispatch;
вот так всё работает!
всем большое спасибо!
← →
hattak © (2010-11-11 00:27) [14]в продолжение темы ... чтоб не открывать нову тему ...
у меня получается странная вещь, сделал я плагин для IE, всё вроде нормально, до тех пор пока открыта одно копия IE, когда открывается вторая или нажимаю на ссылке и она открывается во внешнем окне, то значения всех переменных в главном окне сбрасываются, т.е. такое ощущение, что все окна (ну копии плагина в них т.е.) используют одни и те же переменные оО Разве при создании нового экземпляра переменные не должны также новые создаваться. как сделать так, чтоб при запуске каждого окна IE запускалась как бы новая копия плагина, чтоб переменные в них были "изолированы" друг от друга?
з.ы. пытался при создании плагина - т.е. com сервера, создавать его с ciSingleInstance вместо ciMultiInstance ... всё тоже самое (((
← →
hattak © (2010-11-11 00:43) [15]даже ещё интереснее, есть гланое окно ... в нём ссылка, нажимаю, открывается в новом окне - значения переменных разные в главном и в открывшемся ... в открывшемся ещё ссылка ... открываю в новом окне и опа ... это новое окно имеет все значения переменных из главного и сбрасывает все переменные в главном оО
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2011.02.20;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.004 c