关于超想
本站导航
邮件列表
  首页 | 本站产品 | Delphi资料 | 免费资源 | 程序人生 | 软件工程 | 网站设计 | 推荐网站
你所在的位置 -> 主页 -> 超想软件 -> 编程资料 -> delphi -> 开发技巧 -> 网络通讯 ->详细
相关内容  
 
 
在Delphi程序中应用IE浏览器控件
 
【新品推荐】

  详细内容
 

利用Delphi编写IE扩展
作者: 张泰立 评价: 上站日期: 2001-06-29
内容说明:
来源:

利用Delphi编写IE扩展     就是如何使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^[i] := dps.cargs - 1 - i;
  if (dps.cnamedargs < = 0) then exit;
  for i := 0 to dps.cnamedargs - 1 do
    pdispids^[dps.rgdispidnamedargs^[i]] := 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 事件中编写代码访问服务器并转到正确的站点上去。
    

 
你所在的位置 -> 主页 -> 超想软件 -> 编程资料 -> delphi -> 开发技巧 -> 网络通讯 ->详细
  首页 | 本站产品 | Delphi资料 | 免费资源 | 程序人生 | 软件工程 | 网站设计 | 推荐网站
声明:本站内容除注明原创以外均从网上摘抄,如有侵权请指明。
  如果您对我们的网站有什么意见或者建议,请与我们联系
powered by 建站易上手- V2.0