IE控制问题,请各位DX帮忙 ( 积分: 200 )

  • 主题发起人 主题发起人 liuziwei_china
  • 开始时间 开始时间
L

liuziwei_china

Unregistered / Unconfirmed
GUEST, unregistred user!
我要开发一个IE的插件,现在遇到一个问题, 如何才能获取到页面上的CLICK事件
例如: 有个页面上面有一个BUTTON,我的插件怎么才能获取用户点击按钮的事件?
注意: 不能去更改页面文件. 还请各位大侠多多指教
 
我要开发一个IE的插件,现在遇到一个问题, 如何才能获取到页面上的CLICK事件
例如: 有个页面上面有一个BUTTON,我的插件怎么才能获取用户点击按钮的事件?
注意: 不能去更改页面文件. 还请各位大侠多多指教
 
连接到
DWebBrowserEvents2就有了
 
http://www.codeproject.com/internet/detecting_the_ie_refresh.asp
 
to satanmonkey:
DWebBrowserEvents2这个是用VC写的吧,我是用DELPHI写的插件,该怎么调用啊,能说的详细点么?
 
DWebBrowserEvents2是IE的连接点.所有支持COM的语言都适用,给你哪个例子是给你参考的.
 
哪个网站我注册不上,我看下他的代码,和DELPHI的Advise方法的参数不一样,我不清楚该怎么调用,你有MSN么, 我的MSN:liuziwei_china@hotmail.com,请教一下,谢谢先
 
利用 Delphi 编写 IE 扩展
TechnoFantasy 原作

就是如何使 ie 扩展组件可以响应事件。

在自己的程序中使用过 webbrowser 控件的朋友都知道 ,webbrowser 控件定义了诸如 beforenavigate 、 downloadcomplete 等事件 ,我们可以通过编写事件处理代码实现对 webbrowser 控件的操作。那么如何实现对 ie 的事件响应和处理呢?同建立 ie 面板一样。我们需要建立一个实现 iobjectwithsite 接口的 com 组件 ,不同的是 ,我们还需要实现 idispatch 接口 ,在 iobjectwithsite 接口的 setsite 方法中获得 ie 的 webbrowser 接口并建立自身与 webbrowser 的连接 ,然后如果在 ie 的 webbrowser 对象中发生什么事件的话 ,那么 ie 就会回调连接的 idispatch 接口的 invoke 方法。我们通过在 invoke 方法中编写代码就可以获得 ie 事件了。这个利用的是 com 编程的回调接口原理。

下面我们首先来实现代码。点击 delphi 菜单 file | new 。在 activex 页面中选择 active library ,然后点击 ok 按钮。然后用同样的方法建立一个 com object 。在 com object wizard 窗口中 ,将复选框 included type library 去掉。然后在 class name 中输入 iehelper,在 implemented interface 中输入 :idispatch;iobjectwithsite 。然后点击 ok 按钮建立一个 com 组件。

保存工程 ,将工程保存为 iehelper.dpr,将 unit1 保存为 iehelperunit.pas 。下面是 iehelperunit.pas 的具体代码 :


unit iehelperunit;


interface


uses

windows, comobj, activex, shdocvw, mshtml,dialogs;



type


tiehelperfactory = class(tcomobjectfactory)

private

procedure addkeys;

procedure removekeys;

public

procedure updateregistry(register: boolean); override;

end;



tiehelper = class(tcomobject, idispatch, iobjectwithsite)

public

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;

function setsite(const punksite: iunknown): hresult; stdcall;

function getsite(const riid: tiid; out site: iunknown): hresult; stdcall;

private

ie: iwebbrowser2;

cookie: integer;

end;


const

class_iehelper: tguid = '{3d898c55-74cc-4b7c-b5f1-45913f368388}';



implementation


uses comserv, registry, sysutils;



procedure dostatustextchange(const text: widestring);

begin


end;


procedure doprogresschange(progress: integer; progressmax: integer);

begin


end;


procedure docommandstatechange(command: integer; enable: wordbool);

begin


end;


procedure dodownloadbegin;

begin


end;


procedure dodownloadcomplete;

begin


end;


procedure dotitlechange(const text: widestring);

begin


end;


procedure dopropertychange(const szproperty: widestring);

begin


end;


procedure dobeforenavigate2(const pdisp: idispatch; var url: olevariant; var flags: olevariant; var targetframename: olevariant; var postdata: olevariant; var headers: olevariant; var cancel: wordbool);

begin

if url<>'http://www.applevb.com/'then begin

showmessage(' 你不可以浏览其它站点 ');

cancel:=true;

url:='http://www.applevb.com';

(pdisp as iwebbrowser2).navigate2(url,flags,targetframename,postdata,headers);

end;

end;


procedure donewwindow2(var ppdisp: idispatch; var cancel: wordbool);

begin


end;


procedure donavigatecomplete2(const pdisp: idispatch; var url: olevariant);

begin


end;


procedure dodocumentcomplete(const pdisp: idispatch; var url: olevariant);

begin


end;


procedure doonquit;

begin


end;


procedure doonvisible(visible: wordbool);

begin


end;


procedure doontoolbar(toolbar: wordbool);

begin


end;


procedure doonmenubar(menubar: wordbool);

begin


end;


procedure doonstatusbar(statusbar: wordbool);

begin


end;


procedure doonfullscreen(fullscreen: wordbool);

begin


end;


procedure doontheatermode(theatermode: wordbool);

begin


end;



procedure buildpositionaldispids(pdispids: pdispidlist; const dps: tdispparams);

var

i: integer;

begin

assert(pdispids <> nil);

for i := 0 to dps.cargs - 1 do

pdispids^ := dps.cargs - 1 - i;

if (dps.cnamedargs <= 0) then exit;

for i := 0 to dps.cnamedargs - 1 do

pdispids^[dps.rgdispidnamedargs^] := i;

end;


function tiehelper.invoke(dispid: integer; const iid: tguid; localeid: integer;

flags: word; var params; varresult, excepinfo, argerr: pointer): hresult;

type

polevariant = ^olevariant;

var

dps: tdispparams absolute params;

bhasparams: boolean;

pdispids: pdispidlist;

idispidssize: integer;

begin

result := disp_e_membernotfound;

pdispids := nil;

idispidssize := 0;

bhasparams := (dps.cargs > 0);

if (bhasparams) then

begin

idispidssize := dps.cargs * sizeof(tdispid);

getmem(pdispids, idispidssize);

end;

try

if (bhasparams) then buildpositionaldispids(pdispids, dps);

case dispid of

102:

begin

dostatustextchange(dps.rgvarg^[pdispids^[0]].bstrval);

result := s_ok;

end;

108:

begin

doprogresschange(dps.rgvarg^[pdispids^[0]].lval, dps.rgvarg^[pdispids^[1]].lval);

result := s_ok;

end;

105:

begin

docommandstatechange(dps.rgvarg^[pdispids^[0]].lval, dps.rgvarg^[pdispids^[1]].vbool);

result := s_ok;

end;

106:

begin

dodownloadbegin();

result := s_ok;

end;

104:

begin

dodownloadcomplete();

result := s_ok;

end;

113:

begin

dotitlechange(dps.rgvarg^[pdispids^[0]].bstrval);

result := s_ok;

end;

112:

begin

dopropertychange(dps.rgvarg^[pdispids^[0]].bstrval);

result := s_ok;

end;

250:

begin

dobeforenavigate2(idispatch(dps.rgvarg^[pdispids^[0]].dispval), polevariant(dps.rgvarg^[pdispids^[1]].pvarval)^, polevariant(dps.rgvarg^[pdispids^[2]].pvarval)^, polevariant(dps.rgvarg^[pdispids^[3]].pvarval)^, polevariant(dps.rgvarg^[pdispids^[4]].pvarval)^, polevariant(dps.rgvarg^[pdispids^[5]].pvarval)^, dps.rgvarg^[pdispids^[6]].pbool^);

result := s_ok;

end;

251:

begin

donewwindow2(idispatch(dps.rgvarg^[pdispids^[0]].pdispval^), dps.rgvarg^[pdispids^[1]].pbool^);

result := s_ok;

end;

252:

begin

donavigatecomplete2(idispatch(dps.rgvarg^[pdispids^[0]].dispval), polevariant(dps.rgvarg^[pdispids^[1]].pvarval)^);

result := s_ok;

end;

259:

begin

dodocumentcomplete(idispatch(dps.rgvarg^[pdispids^[0]].dispval), polevariant(dps.rgvarg^[pdispids^[1]].pvarval)^);

result := s_ok;

end;

253:

begin

doonquit();

result := s_ok;

end;

254:

begin

doonvisible(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

255:

begin

doontoolbar(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

256:

begin

doonmenubar(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

257:

begin

doonstatusbar(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

258:

begin

doonfullscreen(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

260:

begin

doontheatermode(dps.rgvarg^[pdispids^[0]].vbool);

result := s_ok;

end;

end;

finally

if (bhasparams) then freemem(pdispids, idispidssize);

end;

end;



function tiehelper.getidsofnames(const iid: tguid; names: pointer;

namecount, localeid: integer; dispids: pointer): hresult;

begin

result := e_notimpl;

end;


function tiehelper.gettypeinfo(index, localeid: integer;

out typeinfo): hresult;

begin

result := e_notimpl;

pointer(typeinfo) := nil;

end;


function tiehelper.gettypeinfocount(out count: integer): hresult;

begin

result := e_notimpl;

count := 0;

end;



function tiehelper.getsite(const riid: tiid; out site: iunknown): hresult;

begin

// result := s_ok;

if assigned(ie) then result:=ie.queryinterface(riid, site)

else

result:= e_fail;

end;


function tiehelper.setsite(const punksite: iunknown): hresult;

var

cmdtarget: iolecommandtarget;

sp: iserviceprovider;

cpc: iconnectionpointcontainer;

cp: iconnectionpoint;

begin

if assigned(punksite) then begin

cmdtarget := punksite as iolecommandtarget;

sp := cmdtarget as iserviceprovider;


if assigned(sp)then

sp.queryservice(iwebbrowserapp, iwebbrowser2, ie);

if assigned(ie) then begin

ie.queryinterface(iconnectionpointcontainer, cpc);

cpc.findconnectionpoint(dwebbrowserevents2, cp);

cp.advise(self, cookie)

end;

end;

result := s_ok;

end;



procedure tiehelperfactory.addkeys;

var s: string;

begin

s := guidtostring(class_iehelper);

with tregistry.create do

try

rootkey := hkey_local_machine;

if openkey('software/microsoft/windows/currentversion/explorer/browser helper objects/' + s, true)

then closekey;

finally

free;

end;

end;


procedure tiehelperfactory.removekeys;

var s: string;

begin

s := guidtostring(class_iehelper);

with tregistry.create do

try

rootkey := hkey_local_machine;

deletekey('software/microsoft/windows/currentversion/explorer/browser helper objects/' + s);

finally

free;

end;

end;


procedure tiehelperfactory.updateregistry(register: boolean);

begin

inherited updateregistry(register);

if register then addkeys else removekeys;

end;


initialization

tiehelperfactory.create(comserver, tiehelper, class_iehelper,

'iehelper', '', cimultiinstance, tmapartment);

end.


代码很长 ,但是关键的是 tiehelper.setsite 方法以及 tiehelper.invoke 方法。在 tiehelper.setsite 方法中注意以下语句 :

if assigned(sp)then

sp.queryservice(iwebbrowserapp, iwebbrowser2, ie);

if assigned(ie) then begin

ie.queryinterface(iconnectionpointcontainer, cpc);

cpc.findconnectionpoint(dwebbrowserevents2, cp);

cp.advise(self, cookie)


上面的语句作用是 ,首先获得 ie 的 webbrowser 接口 ,然后寻找到连接点。并通过 advise 方法建立 com 自身与连接点的连接。

当连接建立成功后 ,ie 在有事件引发后 ,会调用连接到自身的 idispatch 接口对象的 invoke 方法。不同的事件对应不同的 dispid 编码 ,我们可以在程序中判断 dispid 并做相应的处理。在上面的程序中 ,我们只处理了 beforenavigate2 事件 ,处理函数是 dobeforenavigate2,在该函数中 ,如果浏览的站点不是 'http://www.applevb.com/' 的话 ,程序会提示 :' 你不可以浏览其它站点 ' 并强行转到 http://www.applevb.com 。

很多的软件 ,象 " 护花使者 " 以及 "3721" 一类的中文网址 " 都是利用上面的原理来实现对 ie 浏览器事件响应的 ,例如 3721,当用户输入一个中文词并浏览时 ,com 组件可以在 beforenavigate2 事件中编写代码访问服务器并转到正确的站点上去。

以上程序在 win2k 、 delphi 5 下编写 win98 、 win2k 下编辑通过 ,如果大家需要源程序或者对于 com 编程需要有什么的指教的话 ,欢迎到我的主页 http://www.applevb.com 访问 ,我愿意同大家一起探讨。
 
delphi里一句就搞定了
InterfaceConnect(IE, DWebBrowserEvents2, Self, FConnection);
 
你可以看看
unit SHDocVw;

其实你只要得到 IE 的 IWebBrowser2 接口,可以通过 TInternetExplorer.ConnectTo 得到 IE 这个东西,就可以响应 TInternetExplorer 的所有事件了
 
我看了下DWebBrowserEvents2这个接口,好象还是不能达到我的需求啊,这个接口中只有

procedure StatusTextChange(const Text: WideString); dispid 102;
procedure ProgressChange(Progress: Integer; ProgressMax: Integer); dispid 108;
procedure CommandStateChange(Command: Integer; Enable: WordBool); dispid 105;
procedure DownloadBegin; dispid 106;
procedure DownloadComplete; dispid 104;
procedure TitleChange(const Text: WideString); dispid 113;
procedure PropertyChange(const szProperty: WideString); dispid 112;
procedure BeforeNavigate2(const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant;
var TargetFrameName: OleVariant; var PostData: OleVariant;
var Headers: OleVariant; var Cancel: WordBool); dispid 250;
procedure NewWindow2(var ppDisp: IDispatch; var Cancel: WordBool); dispid 251;
procedure NavigateComplete2(const pDisp: IDispatch; var URL: OleVariant); dispid 252;
procedure DocumentComplete(const pDisp: IDispatch; var URL: OleVariant); dispid 259;
procedure OnQuit; dispid 253;
procedure OnVisible(Visible: WordBool); dispid 254;
procedure OnToolBar(ToolBar: WordBool); dispid 255;
procedure OnMenuBar(MenuBar: WordBool); dispid 256;
procedure OnStatusBar(StatusBar: WordBool); dispid 257;
procedure OnFullScreen(FullScreen: WordBool); dispid 258;
procedure OnTheaterMode(TheaterMode: WordBool); dispid 260;
这些事件可以触发,这些的都是IE本身提供的事件,可是我想得到到的是,一个在IE窗口中打开的网页上的按钮触发事件,例如: 我登陆大富翁网站,写入用户名和密码,然后点"进入论坛"这个按钮, 我想捕获的的就是你点这个按钮的事件,在这个事件中我要加入一些操作,不知道我表达清楚了没有,还请各位大侠帮忙啊
 
哈,记错了,应该是
HTMLDocumentEvents
 
to satanmonkey:
我看了HTMLDocumentEvents 这个接口,看到里面有一个ONCLICK事件
我修改了我的代码:
SetSite事件中:
if(Assigned(frmIE.IEThis))then
begin
frmIE.IEThis.QueryInterface(IConnectionPointContainer,CPC);//寻找连接点
//CPC.FindConnectionPoint(DWEBBrowserEvents2,CP);
CPC.FindConnectionPoint(HTMLDocumentEvents,CP);

CP.Advise(Self,Cookie);//通过Advise方法建立Com自身与连接点的连接

end;

在Invoke事件中做了如下修改:
if Dispid = -600 then
begin
//这个是我要做的事情,
frmIE.Click;

end;

还有一个不明白的地方就是,在Invoke中,我怎么知道,CLICK触发的就是我想要捕捉的那个按钮的事件,如果页面有两个按钮的话,是不是就有问题了?
 
Invoke的Params参数里可以分析出来是点了哪个IHTMLElement

var
dps: TDispParams absolute Params;
然后IHTMLElement(dps.rgvarg^[pDispIds^[0]].dispval)就是点了的html元素
 
刚才做了个测试

如果代码是这样的话,IE就抱错
CPC.FindConnectionPoint(HTMLDocumentEvents,CP);

如果是这样
CPC.FindConnectionPoint(DWEBBrowserEvents2,CP);
就没问题,这是为什么啊?
 
delphi上用InterfaceConnect连接就可以了,不用照C++的抄
 
我修改后的代码
在setsite事件中:
if Assigned(pSP) then
begin
{检索提供的服务}
pSP.QueryService(IWebbrowserApp, IWebbrowser2, frmIE.IEThis);

if(Assigned(frmIE.IEThis))then
begin
//frmIE.IEThis.QueryInterface(IConnectionPointContainer,CPC);//寻找连接点
//CPC.FindConnectionPoint(DWEBBrowserEvents2,CP);
//CPC.FindConnectionPoint(HTMLDocumentEvents2,CP);
InterfaceConnect(frmIE.IEThis, HTMLDocumentEvents2, Self, Cookie);
//CP.Advise(Self,Cookie);//通过Advise方法建立Com自身与连接点的连接

end;
Invoke事件的代码如下:
function TGetMailBand.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;
type
POleVariant=^OleVariant;
PVarDataList = ^TVarDataList;
TVarDataList = array[0..3] of TVarData;

var
Args: PVarDataList;
Shift: TShiftState;
Button: TMouseButton;
X, Y: Integer;

//dps:TDispParams absolute Params;
bHasParams:Boolean;
pDispIDs:PDispIDList;
iDispIDsSize:Integer;

sl: TStringlist;
dps: TDispParams absolute Params;

begin
sl := TStringList.Create;
Args := PVarDataList(TDispParams(Params).rgvarg);
Result:=DISP_E_MEMBERNOTFOUND;
pDispIDs:=nil;
iDispIDsSize:=0;
bHasParams:=(dps.cArgs>0);
if(bHasParams)then
begin
iDispIDsSize:=dps.cArgs*SizeOf(TDispID);
GetMem(pDispIDs,iDispIDsSize);
end;
try
if(bHasParams)then BuildPositionalDispIDs(pDispIDs,dps);
showmessage(inttostr(Dispid));
if Dispid = -600 then
begin
showmessage('ok');
if IHTMLElement(dps.rgvarg^[pDispIds^[0]].dispval).ID = 'button2' then
begin
//frmIE.DocumentComplete(self);
showmessage('ok');
end;
end;
Result:=S_OK;
finally
if(bHasParams)then
FreeMem(pDispIDs,iDispIDsSize);
end;

end;

编译可以过,但是我点击页面却什么也没触发,如果正常应该出现提示框才对,
是哪里还有问题么?
 
你调试看看Invoke被调用了没有
 
查了下我原来的代码
IHTMLElement(dps.rgvarg^[pDispIds^[0]].dispval).ID
应该改成
IHTMLEventObj(dps.rgvarg^[pDispIds^[0]].dispval).srcElement.ID

dps.rgvarg^[pDispIds^[0]].dispval是个IHTMLEventObj不是IHTMLElement
 
没有走那个函数, 奇怪, 有什么地方不对么?
你说的地方也没关系啊,我在之前也有个showmessage啊,怎么都没显示的?
 
后退
顶部