Solved

about TWebBrowser's OnBeforeNavigate2

Posted on 2001-06-28
28
713 Views
Last Modified: 2010-08-05
in OnBeforeNavigate2(Sender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
so I can get the URL,but how can I get the URL title
for exp. <a href='http://www.experts-exchange.com'>E_E</a>
I can get the href's value, how can I get the 'E_E'
0
Comment
Question by:kangxy
  • 10
  • 9
  • 7
  • +2
28 Comments
 

Author Comment

by:kangxy
ID: 6236823
Who can Help me ?
0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6237195
first of all use ondocumentcomplete
You can't know the document title before you have received the page.
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
    tit:variant;
begin
      tit:=webbrowser1.document;
      edit1.text:=tit.title;{title of the page}
end;
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 6237200
f15iaf, read the question carefully...
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6237582
In OnBeforeNavigate2 no way to obtain URL title or any other
anchor attributes. You must implement event sink and attach it
to HTMLAnchorEvents OnClick using DHTML object model.

First you must add units SHDocVw, Mshtml, ComObj:

uses ...., SHDocVw, Mshtml, ComObj;

Next, create Event Sink


const
  Disp_OnClick = -600; // See MSHTML.pas DispID

type
  TAnchorEvent = class(TInterfacedObject, IDispatch)
  protected
    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
    Title: String;
    Form: TForm;
    constructor Create(aForm: TForm; const aTitle: String);
  end;

constructor TAnchorEvent.Create(aForm: TForm; const aTitle: String);
begin
  inherited Create;
  Form := aForm;
  Title := aTitle;
end;

function TAnchorEvent.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function TAnchorEvent.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function TAnchorEvent.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function TAnchorEvent.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
begin
  if DispID = Disp_OnClick then
    begin
          // You actions here
    end;
  Result := S_OK;
end;

then
you define OnDocumentComplete event and expand all anchors element:

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);

procedure ExtractAnchors(Document: OleVariant);
var
  collection: OleVariant;
  Index: Integer;
  DummyCookie: Integer;
begin
  collection := Document.all.tags('A');
  for Index := 0 to collection.length -1 do
    begin
      ListBox1.Items.Add(collection.item(Index).href);
      InterfaceConnect(IDispatch(collection.item(Index, 0)), HTMLAnchorEvents,
        TAnchorEvent.Create(self, collection.item(Index).innerText), DummyCookie);
    end;
  for Index := 0 to Document.frames.length -1 do
    begin
      ExtractAnchors(Document.frames.item(Index).document);
    end;
end;

Note: UnAdvise you events optionally if you don't refer in
  TAnchorEvent  to any DHTML interfaces.
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6237592
// procedure TForm1.WebBrowser1DocumentComplete tail

begin
  if pDisp = WebBrowser1.ControlInterface then
    ExtractAnchors(WebBrowser1.Document);
end;
0
 
LVL 6

Expert Comment

by:edey
ID: 6239237
I suppose  you could enumerate all the anchors on the page until you find one who's href = the url parameter.  This wouldn't necessarily work if you've got multiple links pointing to the same url.

GL
Mike
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6239286
but this anchors can have different title
0
 
LVL 6

Expert Comment

by:edey
ID: 6239304
In JScript you've got access to the window.event object, which in turns has a srcObject property.  So if you can get access to the window object (I've been trying, but haven't figured out how) you can get a variant ref. to the link in question.

GL
Mike
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6239393
This is good idea, but window.event defined during processing event and not work in
BeforeNavigate2 or you will use another event ?
0
 
LVL 6

Expert Comment

by:edey
ID: 6240147
I just had an idea - I don't have delphi here to test it though.  What about trying webBrowser.document.activeElement?  you've clicked it so I would think that the anchor should have focus.

GL
Mike
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6240296
Ok, but how you catch click ?
I think in any case need advise event sink
on every anchor in web page. But you right inside
event handler we can use window.event or
document.activeElement for obtain element interface.
0
 
LVL 6

Expert Comment

by:edey
ID: 6241367
Is that what kangxy is looking for?  It's a condition not in the original question.  perhaps the scope of the problem needs to be fleshed out a little more.

GL
Mike
0
 

Author Comment

by:kangxy
ID: 6241655
First, Thx all. this weekend, so I not check the web.

Does document.activeElement work?

Can you give me some code?

thx.
0
 
LVL 6

Expert Comment

by:edey
ID: 6241810
I'm currently doing a major hardware shuffle at home :), unfortunately it's unlikely that I'll have a delphi install until mon or tues.  if it does work, though, the code would look like this:

var
 doc : variant;
begin
 doc := webBrowser1.document;
//note that doc will be nil if you've not navigated anywhere.
 caption := doc.activeElement.innerText;
end;

This snippet should set the form's caption to the visible text of the active element.  You can check if doc.activeElement.className = 'A' to see if it is indeed an anchor.

GL
Mike
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 2

Expert Comment

by:SChertkov
ID: 6242079
Mike you absolutely right !
But i think you forget about frames.
This is small modification you code, i try it and
its work fine:

procedure TForm1.WebBrowser1BeforeNavigate2(Sender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
var
 doc, activeElement: OleVariant;
begin
  if webBrowser1.document = nil then
    Exit;
  doc := webBrowser1.document;
  activeElement := doc.activeElement;
  while not VarIsEmpty(activeElement) and
    ((activeElement.tagName = 'FRAME')
      or (activeElement.tagName = 'IFRAME')) do
     activeElement := activeElement.contentWindow.document.activeElement;
  if not VarIsEmpty(activeElement) and (activeElement.tagName = 'A') then
       ShowMessage(activeElement.innerText);
end;


0
 
LVL 6

Expert Comment

by:edey
ID: 6242492
Ah, very good point! I just looked it up and sure enough the activeElement _is_ document specific - you can have one for every frame.

GL
Mike
0
 

Author Comment

by:kangxy
ID: 6243485
I've try SChertkov's code. but have some proplem,I use delphi 5. some Exception raised, say "Method 'contentWindow' not supported by automation object" :(
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6243702
What version of IE you using ?
0
 

Author Comment

by:kangxy
ID: 6243721
IE 5.0
0
 

Author Comment

by:kangxy
ID: 6243723
IE 5.0 win2000 server
0
 
LVL 2

Accepted Solution

by:
SChertkov earned 300 total points
ID: 6243837
Following code work in IE 5 (i am sorry,
i work in IE55 on Win2k)

procedure TForm1.WebBrowser1BeforeNavigate2(Sender: TObject;
 const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
 Headers: OleVariant; var Cancel: WordBool);
var
 window: IHTMLWindow2;
 Document: IHTMLDocument2;
 VIndex: OleVariant;

begin
   if webBrowser1.document = nil then
     Exit;
  Document := webBrowser1.document as IHTMLDocument2;
  if Document.activeElement = nil then
    Exit;
  while (Document.activeElement.tagName = 'FRAME') or
    (Document.activeElement.tagName = 'IFRAME') do
  begin
    VIndex := (Document.activeElement as IHTMLFrameBase).name;
    window := IDispatch(Document.frames.item(VIndex)) as IHTMLWindow2;
    Document := window.document;
  end;
  if (Document.activeElement.tagName = 'A') then
    ShowMessage(Document.activeElement.innerText);
end;
0
 

Author Comment

by:kangxy
ID: 6243853
Wooowo, thank you very much, it's work well.
the 300 pts it's your now!
Schertkov:150
edey:150
OK?
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6243856
OK
0
 

Author Comment

by:kangxy
ID: 6243875
how to give the points to two answer?
:)
0
 
LVL 2

Expert Comment

by:SChertkov
ID: 6243888
Do not know. I member expert-exchange four days.
0
 

Author Comment

by:kangxy
ID: 6243903
Does edey here? Maybe he know:)
0
 
LVL 6

Expert Comment

by:edey
ID: 6243947
Hi.  Actually you can post a question to the Customer Support forum asking for this question to have reduced points.  You should provide a link to this question.  Then ask another for 150. C/S is generally pretty good about this :).  Anyway - glad to see you got a solution, at first it was one of those that seemed just impossible, but turn out to be simpler then you think :).

GL
Mike
0
 

Author Comment

by:kangxy
ID: 6244125
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now