Delphi - Internet Explorer kiegészítése Delphi-s alkalmazással

forráskód letöltése
Ha elindítjuk az Internet Explorer-t, akkor abban számos eszköztárat (TToolBar) találunk. Az IE 5-ös verziójától kezdve arra is lehetőségünk nyílik, hogy saját eszköztárat készítsünk, akár Delphi-vel is és ezt beépítsük az Explorer-be. Ennek az eszköztárnak természetesen teljesen egyedi funkciói lehetnek, egyedül csak igényeink szabnak korlátot. Természetesen arra is lehetőségünk nyílik, hogy az aktuálisan futó böngészőt elérjük, annak működését egyedileg befolyásoljuk, például úgy hogy egy általunk megadott web lapot töltünk be.

Mellékelt példában egy olyan eszköztárat hozunk létre, melynek segítségével egyszerűen kiválaszthatjuk, hogy újságunk melyik száma jelenjen meg a böngészőben. Mellékelt példa kipróbálásához a következő lépésekre van szükség:
  • ha fut, zárja be az Internet Explorer-t
  • nyissa meg a mellékelt GotoDSO.dpr-t Delphi-ben
  • fordítsa le, így létrejön a GotoDSO.dll
  • válassza a Delphi-ben a Run - Register ActiveX Server menüpontot
  • indítsa el az Internet Explorer-t
  • válassza a Nézet - Eszköztárak - Goto Delphi Software Online elemet, hogy láthatóvá tegye az új eszköztárat
Az új eszköztárban, ha kiválasztja, hogy melyik évet és ezen belül melyik számot szeretné látni, akkor már csak az Ok gombra kell kattintania. Ha van élő internet kapcsolat, akkor a böngésző betölti a kért oldalt. Felhívnánk viszont a figyelmet arra, hogy ez a funkció jelenleg ugyan működik, de elképzelhető, hogy a szerverünkön található rendszer továbbfejlesztése esetén a most közreadott eszköztár használhatatlanná válik. Történhet ez akkor, ha az eszköztár által előállított URL címet a rendszerünk nem tudja értelmezni az esetleges továbbfejlesztés, vagy egyéb változtatás után.

Az eszköztár eltávolításához zárja be az IE-t, majd nyissa meg a mellékelt GotoDSO.dpr-t és válassza a Run - Unregister ActiveX Server menüpontot.

A megvalósításhoz egy COM objektumot kell létrehoznunk, melyet megfelelően regisztrálva az IE fel tudja használni a létrehozott új eszköztárat. Ebben a COM objektumban az IDeskBand, IPersistStreamInit és az IObjectWithSite interfészeket kell felhasználnunk.

Új COM objektumhoz először is szükségünk lesz egy ActiveX DLL-re. Ehhez válasszuk a File - New menüpontot, majd az ActiveX lapról, az ActiveX Library elemet. Rögtön adjuk is hozzá a COM objektumot, melyet szintén ezen a lapon tehetünk meg a COM Object elem választásával. A mellékelt példában a COM objektumunkat GotoDSOObject-nek neveztük el.
Implementálnunk kell a fent említett három interfész metódusait is, ezek segítségével tudjuk majd megvalósítani feladatunkat.
  TGotoDSOObject = class(TComObject, IDeskBand, 
     IPersistStreamInit, IObjectWithSite)
  private
    FParentWnd: HWND;
    FSite: IInputObjectSite;
    
  public
    {Declare IDeskBand methods here}
    function GetBandInfo(dwBandID, dwViewMode: DWORD; 
        var pdbi: TDeskBandInfo): HResult; stdcall;
    function ShowDW(fShow: BOOL): HResult; stdcall;
    function CloseDW(dwReserved: DWORD): HResult; stdcall;
    function ResizeBorderDW(var prcBorder: TRect; 
       punkToolbarSite: IUnknown;  fReserved: BOOL): 
       HResult; stdcall;
    function GetWindow(out wnd: HWnd): HResult; stdcall;
    function ContextSensitiveHelp(fEnterMode: BOOL):
       HResult; stdcall;

    {Declare IPersistStreamInit methods here}
    function InitNew: HResult; stdcall;
    function GetClassID(out classID: TCLSID): HResult; stdcall;
    function IsDirty: HResult; stdcall;
    function Load(const stm: IStream): HResult; stdcall;
    function Save(const stm: IStream; fClearDirty: BOOL): 
       HResult; stdcall;
    function GetSizeMax(out cbSize: Largeint): HResult; stdcall;

    {Declare IObjectWithSite methods here}
    function SetSite(const pUnkSite: IUnknown): 
        HResult; stdcall;
    function GetSite(const riid: TIID; out site: IUnknown):
        HResult; stdcall;

  end;

Amikor az IDeskBand interfész GetBandInfo függvénye kerül meghívásra, akkor hozzuk létre a saját eszköztárunkat, melyet a Unit2.pas-ban helyeztünk el egy Form-on. A GetBandInfo eljárásban ezt hozzuk létre, abban az esetben, ha még nem tettük meg egyszer sem.
  if not Assigned(GotoDSOForm) then begin
    GotoDSOForm:=TGotoDSOForm.CreateParented(FParentWnd);
  end;
Ezek után a paraméterként kapott TDeskBandInfo struktúra dwMask értékét felhasználva ellenőriznünk kell, hogy miért is került meghívásra a GetBandInfo. DBIM_MINSIZE érték jelenléte esetén az eszköztárunk minimális méretét kell megadnunk. Ez lesz az a méret, melynél kisebbre nem fogja tudni beállítani a felhasználó az IE-ben az eszköztárunkat.
  if (pdbi.dwMask or DBIM_MINSIZE)<>0 then begin
    with pdbi.ptMinSize do begin
      y:=GotoDSOForm.Height;
      x:=0;
    end;
  end;
Ehhez hasonlóan DBIM_MAXSIZE értéknél a maximális méretet kell megadnunk, míg a DBIM_TITLE értéknél az eszköztár fejléc szövegét.

Amikor az IObjectWithSite interfész SetSite függvénye kerül meghívásra, akkor hozzuk létre a kapcsolatot az adott böngészővel ennek objektumát el is tároljuk az FIE változóba későbbi felhasználás céljából.
function TGotoDSOObject.SetSite(const pUnkSite: IUnknown): HResult;
var
  ow: IOleWindow;
  oct: IOleCommandTarget;
  sp: IServiceProvider;
begin
  if Assigned(pUnkSite) then begin
    FSite:=pUnkSite as IInputObjectSite;
    ow:=PunkSIte as IOleWindow;
    ow.GetWindow(FParentWnd);
    oct:=pUnkSite as IOleCommandTarget;
    sp:=oct as IServiceProvider;
    sp.QueryService(IWebbrowserApp, IWebbrowser2, FIE);
  end;
  result:=S_OK;
end;
A Unit2.pas-ban amikor az Ok gombra kattint a felhasználó, akkor használjuk fel az imént eltárolt web böngésző objektumot és a Navigate2 függvényének hívásával a kívánt web lapra ugrunk.
procedure TGotoDSOForm.Button1Click(Sender: TObject);
var
  url, unused: OleVariant;
begin  
  url:='http://www.animare.hu/scripts/i.exe?process=gotoarchive
        &pathinfo=/sw/dso/&year='+ComboBox1.Text+'&num='
        +ComboBox2.Text;
  FIE.Navigate2(url, unused, unused, unused, unused);
end;
Az elkészített DLL-t regisztrálnunk kell a Windows regisztrációs adatbázisába ahhoz, hogy az IE rátaláljon induláskor.

Ehhez azt használjuk fel, hogy amikor a DLL-ünk regisztrálásra kerül, mint ActiveX szerver, akkor a TComObjectFactory objektum UpdateRegistry eljárása meghívásra kerül.

Így ha létrehozunk egy saját objektumot ebből az osztályból és felülírjuk az UpdateRegistry eljárását, akkor itt rögtön elvégezhetjük a szükséges módosítást a Windows regisztrációs adatbázisában.
  TGotoDSOFactory = class(TComObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;
A létrehozott TGotoDSOFactory osztályt felhasználni a forrásunk initialization részében kell, ahol ebből az objektumból kell egy példányt létrehoznunk.
initialization
  TGotoDSOFactory.Create(ComServer, TGotoDSOObject, 
     CLSID_GotoDSOBand, '', 'DSO', ciMultiInstance);
Így az UpdateRegistry eljárásban már csak meg kell adnunk a szükséges kódot attól függően, hogy regisztrálásról, vagy törlésről van-e szó. Ezt a paraméterként kapott Register nevű változó értékéből dönthetjük el.

Az adatbázisba a következő értékeket kell elhelyeznünk:
[HKEY_CLASSES_ROOT\CLSID\objektum GUID-ja\InProcServer32]
'ThreadingModel', 'Apartment'

[HKEY_CLASSES_ROOT\CLSID\objektum GUID-ja\Implemented
     Categories\{00021492-0000-0000-C000-000000000046}]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Toolbar]
'objektum GUID-ja', ''