<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • x
    x

    Ole控件的事件輔助類

    發布時間:2011-3-29 20:24    發布者:1770309616
    關鍵詞: Ole控件 , 事件輔助類
    概述
           Delphi對Ole控件作了很好的封裝,使用起來要比C++的方便地多,比如想用IE控件,只需要將TWebBrowser拖到窗體上,設置相關屬性,處理相關事件,一切和其他控件沒有什么區別。
           但是使用過程中,我們會發現一個問題,拿TWebBrowser來說,它沒有OnNavigateError事件,如果我們想在連接錯誤的時候做一些事情,比如要用一個更漂亮的網頁來代替IE預定義的錯誤頁面,那么似乎是沒有辦法的了。
           出現這個問題的原因是IE控件的版本,越高版本功能越多,比如錯誤事件是在IE 6才有的,而TWebBrowser顯然是用更低版本的IE類型庫生成的。解決辦法之一是通過更新的類型庫生成更新的控件,但這仍然不大方便,如果下一版本的IE提供了更多的事件,你就必須重新生成控件了。
    我這里提供了一個更好的辦法,無需要生成類型庫就可以接收所有的事件。下面就是代碼:
    代碼
    (**
    * OLE控件的事件輔助類
    *
    * by linzhenqun 2008-12-6
    *)
    unit OleCtrlEventHelper;
    {
      用法:
      1、開始時:創建TOleCtrlEventHelper,建立連接點,添加想處理的事件:
         FOleCtrlEventHelper := TOleCtrlEventHelper.Create(DIID_DWebBrowserEvents2);
         FOleCtrlEventHelper.EventConnect(Webbrowser.DefaultInterface);
         FOleCtrlEventHelper.AddEvent($10F, Method(Self, @TMyClass.OnNavigateError));
      2、結束時:斷開連接點,消毀TOleCtrlEventHelper
         FOleCtrlEventHelper.EventDisconnect(Webbrowser.DefaultInterface);
         FOleCtrlEventHelper.Free;
                                                            --- linzhenqun
    }
    interface
    uses
      SysUtils, ActiveX, Classes;
    type
      PEventRec = ^TEventRec;
      TEventRec = record
        DispID: TDispID;
        Method: TMethod;
      end;
      TOleCtrlEventHelper = class(TObject, IUnknown, IDispatch)
      private
        FEventIID: TGUID;
        FEventList: TList;
        FEventsConnection: LongInt;
      private
        procedure ClearEvent;
        procedure InvokeEvent(DispID: TDispID; var Params: TDispParams);
      protected
        { IUnknown }
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
        { IDispatch }
        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;
      public
        constructor Create(const EventIID: TGUID);
        destructor Destroy; override;
        function AddEvent(DispID: TDispID; const Method: TMethod): Boolean;
        function RemoveEvent(DispID: TDispID): Boolean;
        function GetEvent(DispID: TDispID; var Method: TMethod): Boolean;
        procedure EventConnect(Source: IInterface);
        procedure EventDisconnect(Source: IInterface);
      end;
    function Method(Data, Code: Pointer): TMethod;
    implementation
    uses
      ComObj;
    function Method(Data, Code: Pointer): TMethod;
    begin
      Result.Code := Code;
      Result.Data := Data;
    end;
    { TOleCtrlEventHelper }
    function TOleCtrlEventHelper.AddEvent(DispID: TDispID; const Method: TMethod): Boolean;
    var
      M: TMethod;
      EventRec: PEventRec;
    begin
      Result := False;
      if not GetEvent(DispID, M) then
      begin
        New(EventRec);
        EventRec^.DispID := DispID;
        EventRec^.Method := Method;
        FEventList.Add(EventRec);
        Result := True;
      end;  
    end;
    procedure TOleCtrlEventHelper.ClearEvent;
    var
      i: Integer;
    begin
      for i := 0 to FEventList.Count - 1 do
        Dispose(FEventList.Items);
      FEventList.Clear;
    end;
    constructor TOleCtrlEventHelper.Create(const EventIID: TGUID);
    begin
      FEventIID := EventIID;
      FEventList := TList.Create;
    end;
    destructor TOleCtrlEventHelper.Destroy;
    begin
      ClearEvent;
      FEventList.Free;
      inherited;
    end;
    procedure TOleCtrlEventHelper.EventConnect(Source: IInterface);
    begin
      InterfaceConnect(Source, FEventIID, Self, FEventsConnection);
    end;
    procedure TOleCtrlEventHelper.EventDisconnect(Source: IInterface);
    begin
      InterfaceDisconnect(Source, FEventIID, FEventsConnection);
    end;
    function TOleCtrlEventHelper.GetEvent(DispID: TDispID; var Method: TMethod): Boolean;
    var
      i: Integer;
      EventRec: PEventRec;
    begin
      Result := False;
      for i := FEventList.Count - 1 downto 0 do
      begin
        EventRec := PEventRec(FEventList);
        if EventRec^.DispID = DispID then
        begin
          Method := EventRec^.Method;
          Result := True;
          Break;
        end;
      end;
    end;
    function TOleCtrlEventHelper.GetIDsOfNames(const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
    begin
      Result := E_NOTIMPL;
    end;
    function TOleCtrlEventHelper.GetTypeInfo(Index, LocaleID: Integer;
      out TypeInfo): HResult;
    begin
      Pointer(TypeInfo) := nil;
      Result := E_NOTIMPL;
    end;
    function TOleCtrlEventHelper.GetTypeInfoCount(out Count: Integer): HResult;
    begin
      Count := 0;
      Result := S_OK;
    end;
    function TOleCtrlEventHelper.Invoke(DispID: Integer; const IID: TGUID;
      LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
      ArgErr: Pointer): HResult;
    begin
      if not ((DispID >= DISPID_MOUSEUP) and (DispID <= DISPID_CLICK)) then
        InvokeEvent(DispID, TDispParams(Params));
      Result := S_OK;
    end;
    procedure TOleCtrlEventHelper.InvokeEvent(DispID: TDispID;
      var Params: TDispParams);
    var
      EventMethod: TMethod;
    begin
      if not GetEvent(DispID, EventMethod) or
        (Integer(EventMethod.Code) < $10000) then Exit;
      // copy from olectrls.pas: TOleControl.InvokeEvent
      try
        asm
                  PUSH    EBX
                  PUSH    ESI
                  MOV     ESI, Params
                  MOV     EBX, [ESI].TDispParams.cArgs
                  TEST    EBX, EBX
                  JZ      @@7
                  MOV     ESI, [ESI].TDispParams.rgvarg
                  MOV     EAX, EBX
                  SHL     EAX, 4                         // count * sizeof(TVarArg)
                  XOR     EDX, EDX
                  ADD     ESI, EAX                       // EDI = Params.rgvarg^[ArgCount]
          @@1:    SUB     ESI, 16                        // Sizeof(TVarArg)
                  MOV     EAX, dword ptr [ESI]
                  CMP     AX, varSingle                  // 4 bytes to push
                  JA      @@3
                  JE      @@5
          @@2:    TEST    DL,DL
                  JNE     @@2a
                  MOV     ECX, ESI
                  INC     DL
                  TEST    EAX, varArray
                  JNZ     @@6
                  MOV     ECX, dword ptr [ESI+8]
                  JMP     @@6
          @@2a:   TEST    EAX, varArray
                  JZ      @@5
                  PUSH    ESI
                  JMP     @@6
          @@3:    CMP     AX, varDate                    // 8 bytes to push
                  JA      @@2
          @@4:    PUSH    dword ptr [ESI+12]
          @@5:    PUSH    dword ptr [ESI+8]
          @@6:    DEC     EBX
                  JNE     @@1
          @@7:    MOV     EDX, Self
                  MOV     EAX, EventMethod.Data
                  CALL    EventMethod.Code
                  POP     ESI
                  POP     EBX
        end;
      except
      end;
    end;
    function TOleCtrlEventHelper.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      if GetInterface(IID, Obj) then
      begin
        Result := S_OK;
        Exit;
      end;
      if IsEqualIID(IID, FEventIID) then
      begin
        GetInterface(IDispatch, Obj);
        Result := S_OK;
        Exit;
      end;
      Result := E_NOINTERFACE;
    end;
    function TOleCtrlEventHelper.RemoveEvent(DispID: TDispID): Boolean;
    var
      i: Integer;
      EventRec: PEventRec;
    begin
      Result := False;
      for i := FEventList.Count - 1 downto 0 do
      begin
        EventRec := PEventRec(FEventList);
        if EventRec^.DispID = DispID then
        begin
          FEventList.Remove(EventRec);
          Dispose(EventRec);
          Result := True;
          Break;
        end;
      end;
    end;
    function TOleCtrlEventHelper._AddRef: Integer;
    begin
      Result := -1;
    end;
    function TOleCtrlEventHelper._Release: Integer;
    begin
      Result := -1;
    end;
    end.

    用法
           使用方法非常簡單,我寫了一個Demo傳上來,可以從下面連接下載:
    http://download.csdn.net/source/843895
           TOleCtrlEventHelper是一個比較輕量級的類,使用時需要手工創建和消毀,如果要更方便一點,可以寫成一個組件,這樣就不必關心它的生命周期了,當然代價就是多了一些體積。
    本文地址:http://www.portaltwn.com/thread-60398-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • EtherCAT®和Microchip LAN925x從站控制器介紹培訓教程
    • MPLAB®模擬設計器——在線電源解決方案,加速設計
    • 讓您的模擬設計靈感,化為觸手可及的現實
    • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
    • 貿澤電子(Mouser)專區
    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷