Перехват сообщений IE
01.01.2007
{ This component allows you to intercept Internet Explorer messages such as "StatusTextChangeEvent", "DocumentCompleteEvent" and so on. } //---- Component Source: Install this component first. unit IEEvents; interface uses Windows, SysUtils, Classes, Graphics, ComObj, ActiveX, SHDocVW; type // Event types exposed from the Internet Explorer interface TIEStatusTextChangeEvent = procedure(Sender: TObject; const Text: WideString) of object; TIEProgressChangeEvent = procedure(Sender: TObject; Progress: Integer; ProgressMax: Integer) of object; TIECommandStateChangeEvent = procedure(Sender: TObject; Command: Integer; Enable: WordBool) of object; TIEDownloadBeginEvent = procedure(Sender: TObject) of object; TIEDownloadCompleteEvent = procedure(Sender: TObject) of object; TIETitleChangeEvent = procedure(Sender: TObject; const Text: WideString) of object; TIEPropertyChangeEvent = procedure(Sender: TObject; const szProperty: WideString) of object; TIEBeforeNavigate2Event = procedure(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant; var TargetFrameName: OleVariant; var PostData: OleVariant; var Headers: OleVariant; var Cancel: WordBool) of object; TIENewWindow2Event = procedure(Sender: TObject; var ppDisp: IDispatch; var Cancel: WordBool) of object; TIENavigateComplete2Event = procedure(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant) of object; TIEDocumentCompleteEvent = procedure(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant) of object; TIEOnQuitEvent = procedure(Sender: TObject) of object; TIEOnVisibleEvent = procedure(Sender: TObject; Visible: WordBool) of object; TIEOnToolBarEvent = procedure(Sender: TObject; ToolBar: WordBool) of object; TIEOnMenuBarEvent = procedure(Sender: TObject; MenuBar: WordBool) of object; TIEOnStatusBarEvent = procedure(Sender: TObject; StatusBar: WordBool) of object; TIEOnFullScreenEvent = procedure(Sender: TObject; FullScreen: WordBool) of object; TIEOnTheaterModeEvent = procedure(Sender: TObject; TheaterMode: WordBool) of object; // Event component for Internet Explorer TIEEvents = class(TComponent, IUnknown, IDispatch) private // Private declarations FConnected: Boolean; FCookie: Integer; FCP: IConnectionPoint; FSinkIID: TGuid; FSource: IWebBrowser2; FStatusTextChange: TIEStatusTextChangeEvent; FProgressChange: TIEProgressChangeEvent; FCommandStateChange: TIECommandStateChangeEvent; FDownloadBegin: TIEDownloadBeginEvent; FDownloadComplete: TIEDownloadCompleteEvent; FTitleChange: TIETitleChangeEvent; FPropertyChange: TIEPropertyChangeEvent; FBeforeNavigate2: TIEBeforeNavigate2Event; FNewWindow2: TIENewWindow2Event; FNavigateComplete2: TIENavigateComplete2Event; FDocumentComplete: TIEDocumentCompleteEvent; FOnQuit: TIEOnQuitEvent; FOnVisible: TIEOnVisibleEvent; FOnToolBar: TIEOnToolBarEvent; FOnMenuBar: TIEOnMenuBarEvent; FOnStatusBar: TIEOnStatusBarEvent; FOnFullScreen: TIEOnFullScreenEvent; FOnTheaterMode: TIEOnTheaterModeEvent; protected // Protected declaratios for IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; override; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; // Protected declaratios for IDispatch function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; virtual; stdcall; function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; virtual; stdcall; function GetTypeInfoCount(out Count: Integer): HResult; virtual; stdcall; function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; virtual; stdcall; // Protected declarations procedure DoStatusTextChange(const Text: WideString); safecall; procedure DoProgressChange(Progress: Integer; ProgressMax: Integer); safecall; procedure DoCommandStateChange(Command: Integer; Enable: WordBool); safecall; procedure DoDownloadBegin; safecall; procedure DoDownloadComplete; safecall; procedure DoTitleChange(const Text: WideString); safecall; procedure DoPropertyChange(const szProperty: WideString); safecall; procedure DoBeforeNavigate2(const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant; var TargetFrameName: OleVariant; var PostData: OleVariant; var Headers: OleVariant; var Cancel: WordBool); safecall; procedure DoNewWindow2(var ppDisp: IDispatch; var Cancel: WordBool); safecall; procedure DoNavigateComplete2(const pDisp: IDispatch; var URL: OleVariant); safecall; procedure DoDocumentComplete(const pDisp: IDispatch; var URL: OleVariant); safecall; procedure DoOnQuit; safecall; procedure DoOnVisible(Visible: WordBool); safecall; procedure DoOnToolBar(ToolBar: WordBool); safecall; procedure DoOnMenuBar(MenuBar: WordBool); safecall; procedure DoOnStatusBar(StatusBar: WordBool); safecall; procedure DoOnFullScreen(FullScreen: WordBool); safecall; procedure DoOnTheaterMode(TheaterMode: WordBool); safecall; public // Public declarations constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ConnectTo(Source: IWebBrowser2); procedure Disconnect; property SinkIID: TGuid read FSinkIID; property Source: IWebBrowser2 read FSource; published // Published declarations property WebObj: IWebBrowser2 read FSource; property Connected: Boolean read FConnected; property StatusTextChange: TIEStatusTextChangeEvent read FStatusTextChange write FStatusTextChange; property ProgressChange: TIEProgressChangeEvent read FProgressChange write FProgressChange; property CommandStateChange: TIECommandStateChangeEvent read FCommandStateChange write FCommandStateChange; property DownloadBegin: TIEDownloadBeginEvent read FDownloadBegin write FDownloadBegin; property DownloadComplete: TIEDownloadCompleteEvent read FDownloadComplete write FDownloadComplete; property TitleChange: TIETitleChangeEvent read FTitleChange write FTitleChange; property PropertyChange: TIEPropertyChangeEvent read FPropertyChange write FPropertyChange; property BeforeNavigate2: TIEBeforeNavigate2Event read FBeforeNavigate2 write FBeforeNavigate2; property NewWindow2: TIENewWindow2Event read FNewWindow2 write FNewWindow2; property NavigateComplete2: TIENavigateComplete2Event read FNavigateComplete2 write FNavigateComplete2; property DocumentComplete: TIEDocumentCompleteEvent read FDocumentComplete write FDocumentComplete; property OnQuit: TIEOnQuitEvent read FOnQuit write FOnQuit; property OnVisible: TIEOnVisibleEvent read FOnVisible write FOnVisible; property OnToolBar: TIEOnToolBarEvent read FOnToolBar write FOnToolBar; property OnMenuBar: TIEOnMenuBarEvent read FOnMenuBar write FOnMenuBar; property OnStatusBar: TIEOnStatusBarEvent read FOnStatusBar write FOnStatusBar; property OnFullScreen: TIEOnFullScreenEvent read FOnFullScreen write FOnFullScreen; property OnTheaterMode: TIEOnTheaterModeEvent read FOnTheaterMode write FOnTheaterMode; end; // Register procedure procedure Register; implementation function TIEEvents._AddRef: Integer; begin // No more than 2 counts result := 2; end; function TIEEvents._Release: Integer; begin // Always maintain 1 ref count (component holds the ref count) result := 1; end; function TIEEvents.QueryInterface(const IID: TGUID; out Obj): HResult; begin // Clear interface pointer Pointer(Obj) := nil; // Attempt to get the requested interface if (GetInterface(IID, Obj)) then // Success result := S_OK // Check to see if the guid requested is for the event else if (IsEqualIID(IID, FSinkIID)) then begin // Event is dispatch based, so get dispatch interface (closest we can come) if (GetInterface(IDispatch, Obj)) then // Success result := S_OK else // Failure result := E_NOINTERFACE; end else // Failure result := E_NOINTERFACE; end; function TIEEvents.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; begin // Not implemented result := E_NOTIMPL; end; function TIEEvents.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; begin // Clear the result interface Pointer(TypeInfo) := nil; // No type info for our interface result := E_NOTIMPL; end; function TIEEvents.GetTypeInfoCount(out Count: Integer): HResult; begin // Zero type info counts Count := 0; // Return success result := S_OK; end; function TIEEvents.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; var pdpParams: PDispParams; lpDispIDs: array[0..63] of TDispID; dwCount: Integer; begin // Get the parameters pdpParams := @Params; // Events can only be called with method dispatch, not property get/set if ((Flags and DISPATCH_METHOD) > 0) then begin // Clear DispID list ZeroMemory(@lpDispIDs, SizeOf(lpDispIDs)); // Build dispatch ID list to handle named args if (pdpParams^.cArgs > 0) then begin // Reverse the order of the params because they are backwards for dwCount := 0 to Pred(pdpParams^.cArgs) do lpDispIDs[dwCount] := Pred(pdpParams^.cArgs) - dwCount; // Handle named arguments if (pdpParams^.cNamedArgs > 0) then begin for dwCount := 0 to Pred(pdpParams^.cNamedArgs) do lpDispIDs[pdpParams^.rgdispidNamedArgs^[dwCount]] := dwCount; end; end; // Unless the event falls into the "else" clause of the case statement the result is S_OK result := S_OK; // Handle the event case DispID of 102: DoStatusTextChange(pdpParams^.rgvarg^[lpDispIds[0]].bstrval); 104: DoDownloadComplete; 105: DoCommandStateChange(pdpParams^.rgvarg^[lpDispIds[0]].lval, pdpParams^.rgvarg^[lpDispIds[1]].vbool); 106: DoDownloadBegin; 108: DoProgressChange(pdpParams^.rgvarg^[lpDispIds[0]].lval, pdpParams^.rgvarg^[lpDispIds[1]].lval); 112: DoPropertyChange(pdpParams^.rgvarg^[lpDispIds[0]].bstrval); 113: DoTitleChange(pdpParams^.rgvarg^[lpDispIds[0]].bstrval); 250: DoBeforeNavigate2(IDispatch(pdpParams^.rgvarg^[lpDispIds[0]].dispval), POleVariant(pdpParams^.rgvarg^[lpDispIds[1]].pvarval)^, POleVariant(pdpParams^.rgvarg^[lpDispIds[2]].pvarval)^, POleVariant(pdpParams^.rgvarg^[lpDispIds[3]].pvarval)^, POleVariant(pdpParams^.rgvarg^[lpDispIds[4]].pvarval)^, POleVariant(pdpParams^.rgvarg^[lpDispIds[5]].pvarval)^, pdpParams^.rgvarg^[lpDispIds[6]].pbool^); 251: DoNewWindow2(IDispatch(pdpParams^.rgvarg^[lpDispIds[0]].pdispval^), pdpParams^.rgvarg^[lpDispIds[1]].pbool^); 252: DoNavigateComplete2(IDispatch(pdpParams^.rgvarg^[lpDispIds[0]].dispval), POleVariant(pdpParams^.rgvarg^[lpDispIds[1]].pvarval)^); 253: begin // Special case handler. When Quit is called, IE is going away so we might // as well unbind from the interface by calling disconnect. DoOnQuit; // Call disconnect Disconnect; end; 254: DoOnVisible(pdpParams^.rgvarg^[lpDispIds[0]].vbool); 255: DoOnToolBar(pdpParams^.rgvarg^[lpDispIds[0]].vbool); 256: DoOnMenuBar(pdpParams^.rgvarg^[lpDispIds[0]].vbool); 257: DoOnStatusBar(pdpParams^.rgvarg^[lpDispIds[0]].vbool); 258: DoOnFullScreen(pdpParams^.rgvarg^[lpDispIds[0]].vbool); 259: DoDocumentComplete(IDispatch(pdpParams^.rgvarg^[lpDispIds[0]].dispval), POleVariant(pdpParams^.rgvarg^[lpDispIds[1]].pvarval)^); 260: DoOnTheaterMode(pdpParams^.rgvarg^[lpDispIds[0]].vbool); else // Have to idea of what event they are calling result := DISP_E_MEMBERNOTFOUND; end; end else // Called with wrong flags result := DISP_E_MEMBERNOTFOUND; end; constructor TIEEvents.Create(AOwner: TComponent); begin // Perform inherited inherited Create(AOwner); // Set the event sink IID FSinkIID := DWebBrowserEvents2; end; destructor TIEEvents.Destroy; begin // Disconnect Disconnect; // Perform inherited inherited Destroy; end; procedure TIEEvents.ConnectTo(Source: IWebBrowser2); var pvCPC: IConnectionPointContainer; begin // Disconnect from any currently connected event sink Disconnect; // Query for the connection point container and desired connection point. // On success, sink the connection point OleCheck(Source.QueryInterface(IConnectionPointContainer, pvCPC)); OleCheck(pvCPC.FindConnectionPoint(FSinkIID, FCP)); OleCheck(FCP.Advise(Self, FCookie)); // Update internal state variables FSource := Source; // We are in a connected state FConnected := True; // Release the temp interface pvCPC := nil; end; procedure TIEEvents.Disconnect; begin // Do we have the IWebBrowser2 interface? if Assigned(FSource) then begin try // Unadvise the connection point OleCheck(FCP.Unadvise(FCookie)); // Release the interfaces FCP := nil; FSource := nil; except Pointer(FCP) := nil; Pointer(FSource) := nil; end; end; // Disconnected state FConnected := False; end; procedure TIEEvents.DoStatusTextChange(const Text: WideString); begin // Call assigned event if Assigned(FStatusTextChange) then FStatusTextChange(Self, Text); end; procedure TIEEvents.DoProgressChange(Progress: Integer; ProgressMax: Integer); begin // Call assigned event if Assigned(FProgressChange) then FProgressChange(Self, Progress, ProgressMax); end; procedure TIEEvents.DoCommandStateChange(Command: Integer; Enable: WordBool); begin // Call assigned event if Assigned(FCommandStateChange) then FCommandStateChange(Self, Command, Enable); end; procedure TIEEvents.DoDownloadBegin; begin // Call assigned event if Assigned(FDownloadBegin) then FDownloadBegin(Self); end; procedure TIEEvents.DoDownloadComplete; begin // Call assigned event if Assigned(FDownloadComplete) then FDownloadComplete(Self); end; procedure TIEEvents.DoTitleChange(const Text: WideString); begin // Call assigned event if Assigned(FTitleChange) then FTitleChange(Self, Text); end; procedure TIEEvents.DoPropertyChange(const szProperty: WideString); begin // Call assigned event if Assigned(FPropertyChange) then FPropertyChange(Self, szProperty); end; procedure TIEEvents.DoBeforeNavigate2(const pDisp: IDispatch; var URL: OleVariant; var Flags: OleVariant; var TargetFrameName: OleVariant; var PostData: OleVariant; var Headers: OleVariant; var Cancel: WordBool); begin // Call assigned event if Assigned(FBeforeNavigate2) then FBeforeNavigate2(Self, pDisp, URL, Flags, TargetFrameName, PostData, Headers, Cancel); end; procedure TIEEvents.DoNewWindow2(var ppDisp: IDispatch; var Cancel: WordBool); var pvDisp: IDispatch; begin // Call assigned event if Assigned(FNewWindow2) then begin if Assigned(ppDisp) then pvDisp := ppDisp else pvDisp := nil; FNewWindow2(Self, pvDisp, Cancel); ppDisp := pvDisp; end; end; procedure TIEEvents.DoNavigateComplete2(const pDisp: IDispatch; var URL: OleVariant); begin // Call assigned event if Assigned(FNavigateComplete2) then FNavigateComplete2(Self, pDisp, URL); end; procedure TIEEvents.DoDocumentComplete(const pDisp: IDispatch; var URL: OleVariant); begin // Call assigned event if Assigned(FDocumentComplete) then FDocumentComplete(Self, pDisp, URL); end; procedure TIEEvents.DoOnQuit; begin // Call assigned event if Assigned(FOnQuit) then FOnQuit(Self); end; procedure TIEEvents.DoOnVisible(Visible: WordBool); begin // Call assigned event if Assigned(FOnVisible) then FOnVisible(Self, Visible); end; procedure TIEEvents.DoOnToolBar(ToolBar: WordBool); begin // Call assigned event if Assigned(FOnToolBar) then FOnToolBar(Self, ToolBar); end; procedure TIEEvents.DoOnMenuBar(MenuBar: WordBool); begin // Call assigned event if Assigned(FOnMenuBar) then FOnMenuBar(Self, MenuBar); end; procedure TIEEvents.DoOnStatusBar(StatusBar: WordBool); begin // Call assigned event if Assigned(FOnStatusBar) then FOnStatusBar(Self, StatusBar); end; procedure TIEEvents.DoOnFullScreen(FullScreen: WordBool); begin // Call assigned event if Assigned(FOnFullScreen) then FOnFullScreen(Self, FullScreen); end; procedure TIEEvents.DoOnTheaterMode(TheaterMode: WordBool); begin // Call assigned event if Assigned(FOnTheaterMode) then FOnTheaterMode(Self, TheaterMode); end; procedure Register; begin // Register the component on the Internet tab of the IDE RegisterComponents('Internet', [TIEEvents]); end; end.
Project source
//Notes: Add a button and the IEEvents component to Form1. The button1 click event // shows how the IE enumeration is achieved, and shows how the binding is done: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IEEvents, StdCtrls, ActiveX, SHDocVw; type TForm1 = class(TForm) IEEvents1: TIEEvents; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure IEEvents1Quit(Sender: TObject); procedure IEEvents1DownloadBegin(Sender: TObject); procedure IEEvents1DownloadComplete(Sender: TObject); procedure Button1Click(Sender: TObject); procedure IEEvents1ProgressChange(Sender: TObject; Progress, ProgressMax: Integer); private { Private declarations } FTimeList: TList; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var pvShell: IShellWindows; pvWeb2: IWebBrowser2; ovIE: OleVariant; dwCount: Integer; begin // Create the shell windows interface pvShell := CoShellWindows.Create; // Walk the internet explorer windows for dwCount := 0 to Pred(pvShell.Count) do begin // Get the interface ovIE := pvShell.Item(dwCount); // At this point you can evaluate the interface (LocationUrl, etc) // to decide if this is the one you want to connect to. For demo purposes, // the code will bind to the first one ShowMessage(ovIE.LocationURL); // QI for the IWebBrowser2 if (IDispatch(ovIE).QueryInterface(IWebBrowser2, pvWeb2) = S_OK) then begin IEEvents1.ConnectTo(pvWeb2); // Release the interface pvWeb2 := nil; end; // Clear the variant ovIE := Unassigned; // Break if we connected if IEEvents1.Connected then break; end; // Release the shell windows interface pvShell := nil; end; procedure TForm1.FormCreate(Sender: TObject); begin // Create the time list FTimeList := TList.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin // Free the time list FTimeList.Free; end; procedure TForm1.IEEvents1DownloadBegin(Sender: TObject); begin // Add the current time to the list FTimeList.Add(Pointer(GetTickCount)); end; procedure TForm1.IEEvents1DownloadComplete(Sender: TObject); var dwTime: LongWord; begin // Pull the top item off the list (make sure there is one) if (FTimeList.Count > 0) then begin dwTime := LongWord(FTimeList[Pred(FTimeList.Count)]); FTimeList.Delete(Pred(FTimeList.Count)); // Now calculate total based on current time dwTime := GetTickCount - dwTime; // Display a message showing total download time ShowMessage(Format('Download time for "%s" was %d ms', [IEEvents1.WebObj.LocationURL, dwTime])); end; end; procedure TForm1.IEEvents1Quit(Sender: TObject); begin ShowMessage('About to disconnect'); end; procedure TForm1.IEEvents1ProgressChange(Sender: TObject; Progress, ProgressMax: Integer); begin Caption := IntToStr(Progress); end; end.
Взято с сайта https://www.swissdelphicenter.ch/en/tipsindex.php