WebBrowser SinkEvents 和 DesignMode =“on”
Zarko Gajic 在以下文章和演示中演示了如何在鼠标移到 TWebBrowser 文档上时获取超链接的 url: http://delphi.about.com/od/vclusing/a/wbsinkevents.htm 此演示运行良好,直到 WebBrowser 设置为 designmode = 'on',然后 OnMouseMove 事件不会执行。能否增强演示,以便在 DesignMode = 'on' 时执行 OnMouseMove 事件?如果没有,是否有不同的方法来创建 Document.OnMouseMove 事件?我正在使用 Delphi 2010。
[编辑] 请求更多代码,因此这里是实现
procedure TForm1.DesignMode1Click( Sender: TObject );
var
iDocument: MSHTML.IHTMLDocument2;
begin
if Assigned( WebBrowser1 ) then
begin
iDocument := htmlDoc; //( WebBrowser1.Document as IHTMLDocument2 );
if Assigned( iDocument ) then
begin
if DesignMode1.Checked then
iDocument.DesignMode := 'On'
else
iDocument.DesignMode := 'Off';
WebBrowser1.Refresh2;
end;
end;
end;
procedure TForm1.Document_OnMouseOver;
var
element: IHTMLElement;
begin
if htmlDoc = nil then
Exit;
element := htmlDoc.parentWindow.event.srcElement;
elementInfo.Clear;
if LowerCase( element.tagName ) = 'a' then
begin
elementInfo.Lines.Add( 'LINK info...' );
elementInfo.Lines.Add( Format( 'HREF : %s', [ element.getAttribute( 'href', 0 ) ] ) );
end
else if LowerCase( element.tagName ) = 'img' then
begin
elementInfo.Lines.Add( 'IMAGE info...' );
elementInfo.Lines.Add( Format( 'SRC : %s', [ element.getAttribute( 'src', 0 ) ] ) );
end
else
begin
elementInfo.Lines.Add( Format( 'TAG : %s', [ element.tagName ] ) );
end;
end; (* Document_OnMouseOver *)
procedure TForm1.FormCreate( Sender: TObject );
begin
WebBrowser1.Navigate( 'http://delphi.about.com' );
elementInfo.Clear;
elementInfo.Lines.Add( 'Move your mouse over the document...' );
end; (* FormCreate *)
procedure TForm1.WebBrowser1BeforeNavigate2( ASender: TObject; const pDisp: IDispatch;
var URL, Flags, TargetFrameName, PostData, Headers: OleVariant; var Cancel: WordBool );
begin
htmlDoc := nil;
end; (* WebBrowser1BeforeNavigate2 *)
procedure TForm1.WebBrowser1DocumentComplete( ASender: TObject; const pDisp: IDispatch; var URL: OleVariant );
begin
if Assigned( WebBrowser1.Document ) then
begin
htmlDoc := WebBrowser1.Document as IHTMLDocument2;
htmlDoc.onmouseover := ( TEventObject.Create( Document_OnMouseOver ) as IDispatch );
end;
end; (* WebBrowser1DocumentComplete *)
{ TEventObject }
constructor TEventObject.Create( const OnEvent: TObjectProcedure );
begin
inherited Create;
FOnEvent := OnEvent;
end;
function TEventObject.GetIDsOfNames( const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer;
DispIDs: Pointer ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.GetTypeInfo( Index, LocaleID: Integer; out TypeInfo ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.GetTypeInfoCount( out Count: Integer ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.Invoke( DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params;
VarResult, ExcepInfo, ArgErr: Pointer ): HResult;
begin
if ( DispID = DISPID_VALUE ) then
begin
if Assigned( FOnEvent ) then
FOnEvent;
Result := S_OK;
end
else
Result := E_NOTIMPL;
end;
end.
[修复] 我发现将 webbrowser 设置为设计模式后,WebBrowser1DocumentComplete 未执行,因此我更改了 DesignMode1Click 并解决了问题。我发布此内容是为了其他人也可以看到此内容:
procedure TForm1.DesignMode1Click( Sender: TObject );
begin
// the following is unsafe because you may click on the
// check box even if you don't have any page navigated
-- htmlDoc := WebBrowser1.Document as IHTMLDocument2;
// htmlDoc will be assigned from the OnDocumentComplete
// fired by Navigate procedure
if Assigned( htmlDoc ) then
begin
if DesignMode1.Checked then
htmlDoc.DesignMode := 'On'
else
htmlDoc.DesignMode := 'Off';
// switching to design mode takes some time and if there
// are some pages which doesn't fire OnDocumentComplete
// event when you are switching to design mode, like
// http://delphi.about.com do, then I would wait for
// web browser to be ready
while WebBrowser1.ReadyState < READYSTATE_COMPLETE do
Application.ProcessMessages;
// release the previous "document instance"
htmlDoc := nil;
// assign the new one and attach the event
htmlDoc := WebBrowser1.Document as IHTMLDocument2;
htmlDoc.OnMouseOver := ( TEventObject.Create( Document_OnMouseOver ) as IDispatch );
end;
end;
Zarko Gajic demonstrates how to get the url of a hyperlink when the mouse moves over a TWebBrowser Document in the following article and demo:
http://delphi.about.com/od/vclusing/a/wbsinkevents.htm
This demo works well until the WebBrowser is set to designmode = 'on', then the OnMouseMove event does not execute. Can the demo be enhanced so that the OnMouseMove event is executed when DesignMode = 'on'? If not is there a different way to create a Document.OnMouseMove event? I am using Delphi 2010.
[Edit] More code was requested so here is implementation
procedure TForm1.DesignMode1Click( Sender: TObject );
var
iDocument: MSHTML.IHTMLDocument2;
begin
if Assigned( WebBrowser1 ) then
begin
iDocument := htmlDoc; //( WebBrowser1.Document as IHTMLDocument2 );
if Assigned( iDocument ) then
begin
if DesignMode1.Checked then
iDocument.DesignMode := 'On'
else
iDocument.DesignMode := 'Off';
WebBrowser1.Refresh2;
end;
end;
end;
procedure TForm1.Document_OnMouseOver;
var
element: IHTMLElement;
begin
if htmlDoc = nil then
Exit;
element := htmlDoc.parentWindow.event.srcElement;
elementInfo.Clear;
if LowerCase( element.tagName ) = 'a' then
begin
elementInfo.Lines.Add( 'LINK info...' );
elementInfo.Lines.Add( Format( 'HREF : %s', [ element.getAttribute( 'href', 0 ) ] ) );
end
else if LowerCase( element.tagName ) = 'img' then
begin
elementInfo.Lines.Add( 'IMAGE info...' );
elementInfo.Lines.Add( Format( 'SRC : %s', [ element.getAttribute( 'src', 0 ) ] ) );
end
else
begin
elementInfo.Lines.Add( Format( 'TAG : %s', [ element.tagName ] ) );
end;
end; (* Document_OnMouseOver *)
procedure TForm1.FormCreate( Sender: TObject );
begin
WebBrowser1.Navigate( 'http://delphi.about.com' );
elementInfo.Clear;
elementInfo.Lines.Add( 'Move your mouse over the document...' );
end; (* FormCreate *)
procedure TForm1.WebBrowser1BeforeNavigate2( ASender: TObject; const pDisp: IDispatch;
var URL, Flags, TargetFrameName, PostData, Headers: OleVariant; var Cancel: WordBool );
begin
htmlDoc := nil;
end; (* WebBrowser1BeforeNavigate2 *)
procedure TForm1.WebBrowser1DocumentComplete( ASender: TObject; const pDisp: IDispatch; var URL: OleVariant );
begin
if Assigned( WebBrowser1.Document ) then
begin
htmlDoc := WebBrowser1.Document as IHTMLDocument2;
htmlDoc.onmouseover := ( TEventObject.Create( Document_OnMouseOver ) as IDispatch );
end;
end; (* WebBrowser1DocumentComplete *)
{ TEventObject }
constructor TEventObject.Create( const OnEvent: TObjectProcedure );
begin
inherited Create;
FOnEvent := OnEvent;
end;
function TEventObject.GetIDsOfNames( const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer;
DispIDs: Pointer ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.GetTypeInfo( Index, LocaleID: Integer; out TypeInfo ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.GetTypeInfoCount( out Count: Integer ): HResult;
begin
Result := E_NOTIMPL;
end;
function TEventObject.Invoke( DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params;
VarResult, ExcepInfo, ArgErr: Pointer ): HResult;
begin
if ( DispID = DISPID_VALUE ) then
begin
if Assigned( FOnEvent ) then
FOnEvent;
Result := S_OK;
end
else
Result := E_NOTIMPL;
end;
end.
[Fix]
I figured out that WebBrowser1DocumentComplete was not executed after setting webbrowser to designmode so I changed DesignMode1Click and it fixed the problem. I post this so others may see this as well:
procedure TForm1.DesignMode1Click( Sender: TObject );
begin
// the following is unsafe because you may click on the
// check box even if you don't have any page navigated
-- htmlDoc := WebBrowser1.Document as IHTMLDocument2;
// htmlDoc will be assigned from the OnDocumentComplete
// fired by Navigate procedure
if Assigned( htmlDoc ) then
begin
if DesignMode1.Checked then
htmlDoc.DesignMode := 'On'
else
htmlDoc.DesignMode := 'Off';
// switching to design mode takes some time and if there
// are some pages which doesn't fire OnDocumentComplete
// event when you are switching to design mode, like
// http://delphi.about.com do, then I would wait for
// web browser to be ready
while WebBrowser1.ReadyState < READYSTATE_COMPLETE do
Application.ProcessMessages;
// release the previous "document instance"
htmlDoc := nil;
// assign the new one and attach the event
htmlDoc := WebBrowser1.Document as IHTMLDocument2;
htmlDoc.OnMouseOver := ( TEventObject.Create( Document_OnMouseOver ) as IDispatch );
end;
end;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论