Link to home
Start Free TrialLog in
Avatar of JamesLondon
JamesLondon

asked on

TWebBrowser Double Click????

Hi there,

Does anyone know a simple way of catching Double-Click in a TWebBrowser component.

I would be greatful for a neat, clean example.

Thanks in Advance.
ASKER CERTIFIED SOLUTION
Avatar of DaFox
DaFox

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of JamesLondon
JamesLondon

ASKER

Thanks Markus,

I tried something similar with the TAppEvents component but was relying on the Browser hWnd which didn't march the Messages Handle.

Your example worked perfectly. Thanks.
Hi Markus,

The example you gave doesn't seem to work reliably (I didn't test it properly at first)...

1) Sometimes it has no effect (i.e. the ShoeMessage is not triggered.

2) I used a TAppEvents component instead so that I can set Handled to "False". The reason is that I want to be able to Double click a word and when TWebBrowser highlights it, get the selection. - When the code you gave works it doesn't let the Highlighting occur even when Handled = False, other times the text is highlighted on double click, but the ShowMessage doesn't happen!

Any suggestions??

Best Regards,
James
Could you show the source that you're using?
I have no clue how to solve this, but give me a try...

Markus
James,

to 1) Could it be that the ShowMessage function is the cause of the problem? In my tests the MessageBox wasn't triggerd, too. If I replace the ShowMessage with a Label the code works perfectly.
Please show me your code so that we can get it to work!

Markus
Hi Markus,

Thanks for your resonse.

Check out this example, add a Memo to a form and add the following event, double click and the word you double clicked will show...

procedure TForm1.Memo1DblClick(Sender: TObject);
begin
  ShowMessage(Memo1.SelText);
end;


I need this same behaviour for the WebBrowser component...

The code is exactly as you gave, but I set Handled = False, because I need the message to go through to the component so that it does the selecting of the word...

procedure TfrmMain.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
begin
 if (Msg.Message = WM_LBUTTONDBLCLK) then
 begin
   if PtinRect(Browser.BoundsRect, ScreenToClient(Msg.pt)) then ShowMessage(Test);
 end;
 Handled := False;
end;


I already implemented and fully tested a SelText property on my TWebBrowser descendant, but the problem is detecting the Double Click.


Is there some way of doing this with COM/OLE??? i.e. the Set_ondblclick in MSHTML unit - problem is I'm new to COM and OLE.

Tearing my hair out!

- James.

Hi Markus,

Thanks for your resonse.

Check out this example, add a Memo to a form and add the following event, double click and the word you double clicked will show...

procedure TForm1.Memo1DblClick(Sender: TObject);
begin
  ShowMessage(Memo1.SelText);
end;


I need this same behaviour for the WebBrowser component...

The code is exactly as you gave, but I set Handled = False, because I need the message to go through to the component so that it does the selecting of the word...

procedure TfrmMain.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
begin
 if (Msg.Message = WM_LBUTTONDBLCLK) then
 begin
   if PtinRect(Browser.BoundsRect, ScreenToClient(Msg.pt)) then ShowMessage(Test);
 end;
 Handled := False;
end;


I already implemented and fully tested a SelText property on my TWebBrowser descendant, but the problem is detecting the Double Click.


Is there some way of doing this with COM/OLE??? i.e. the Set_ondblclick in MSHTML unit - problem is I'm new to COM and OLE.

Tearing my hair out!

- James.

Hi Markus,

Thanks for your resonse.

Check out this example, add a Memo to a form and add the following event, double click and the word you double clicked will show...

procedure TForm1.Memo1DblClick(Sender: TObject);
begin
  ShowMessage(Memo1.SelText);
end;


I need this same behaviour for the WebBrowser component...

The code is exactly as you gave, but I set Handled = False, because I need the message to go through to the component so that it does the selecting of the word...

procedure TfrmMain.AppEventsMessage(var Msg: tagMSG; var Handled: Boolean);
begin
 if (Msg.Message = WM_LBUTTONDBLCLK) then
 begin
   if PtinRect(Browser.BoundsRect, ScreenToClient(Msg.pt)) then ShowMessage(Test);
 end;
 Handled := False;
end;


I already implemented and fully tested a SelText property on my TWebBrowser descendant, but the problem is detecting the Double Click.


Is there some way of doing this with COM/OLE??? i.e. the Set_ondblclick in MSHTML unit - problem is I'm new to COM and OLE.

Tearing my hair out!

- James.

Markus,

Apparently Hitting F5 on my browser posted my message three times!!!! - A Bad programmer day!!


Regarding ShowMessage, I understand what your implication, regarding something funny happening with the focus. However I've just tried the following without success...

if PtinRect(Browser.BoundsRect, ScreenToClient(Msg.pt)) then
Begin
  SelStr := Browser.SelText;
  Label1.Caption := SelStr;
End;

This doesn't work either, the caption is set to garbage.
Problem is not with the SelText implementation because Selecting Text then hitting a button that Shows Browser.SelText works fine!!



Hi James.

> Apparently Hitting F5 on my browser posted my message three times!!!! - A Bad programmer day!!

No problem, happens to me sometimes, too ;-)


What do you think about this code. Does it fit your needs?

{ uses SHDocVw_TLB, MSHTML_TLB, ActiveX }

private
  function SelText: String;
  procedure AppMessage(var Msg: TMsg; var Handled: Boolean);

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMessage;
end;

function TForm1.SelText: String;
var
  Doc: IHTMLDocument2;
  Selection: IHTMLSelectionObject;
  TextRange: IHTMLTxtRange;
begin
  try
    Doc := WebBrowser1.Document as IHTMLDocument2;
    Selection := Doc.Selection;
    TextRange := Selection.CreateRange as IHTMLTxtRange;
    result := TextRange.text;
  except
    result := EmptyStr;
  end;
end;


procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
 handled := IsDialogMessage(Webbrowser1.Handle, Msg) = true;
 if (Msg.Message = WM_LBUTTONDBLCLK) then
 begin
   if PtinRect(Webbrowser1.BoundsRect, ScreenToClient(Msg.pt)) then Label1.Caption := SelText;
 end;
end;


initialization
   OleInitialize(nil);

finalization
   OleUninitialize;


end.

Markus
Hi Markus,

Apologies for the Time difference!

Thanks for your code, your SelText is pretty much identical to mine, I actually managed to solve the problem before reading your post, though I will also try your code.

Here is what I'm doing...

FIRSTLY A BROWSER-EVENT COMPONENT DESCENDING FROM IDISPATCH

type
  TBrowserEvent = Class( TComponent, IUnknown, IDispatch)
  private
    { Private declarations }
    FOnEvent : TNotifyEvent;
    FRefCount : integer;
    function QueryInterface( const IID : TGUID; out Obj) : Integer; stdcall;
    function _AddRef : Integer; stdcall;
    function _Release : Integer; stdcall;
    function Invoke( DispID : Integer; const IID : TGUID; LocaleID : Integer; Flags : Word; var Params; VarResult, ExcepInfo, ArgErr : Pointer) : HResult; stdcall;
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
    property OnEvent : TNotifyEvent read FOnEvent write FOnEvent;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('IE', [TBrowserEvent]);
end;

function TBrowserEvent.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result := S_OK
  else
    Result := E_NOINTERFACE;
end;

function TBrowserEvent._AddRef: Integer;
begin
  Inc(FRefCount);
  Result := FRefCount;
end;

function TBrowserEvent._Release: Integer;
begin
  Dec(FRefCount);
  Result := FRefCount;
end;

function TBrowserEvent.Invoke( DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
begin
  if Assigned(OnEvent) then OnEvent(Self);
  Result := S_OK;
end;


ASSIGN THE ONEVENT IN THE COMPONENT TO THE CODE

procedure TfrmMain.breDoubleClickEvent(Sender: TObject);
begin
  // Do something
end;

ASSIGN THE BROWSER-EVENT TO THE TWEBBROWSER DOCUMENT

procedure TfrmMain.BrowserTitleChange(Sender: TObject;
  const Text: WideString);
// JJA Implemented
// Best place to Assign all TWebBrowser Events
Var
 Doc: OLEVariant;
begin
  Doc := Browser.Document;
  Doc.attachEvent('ondblclick', OleVariant( breDoubleClick as IDispatch) );
end;

SUMMARY

I can create multiple browser-event objects, each having it's own single OnEvent and assign them using attachEvent...

Doc.attachEvent('ondblclick', OleVariant( breDoubleClick as IDispatch) );


Anyway, I really appreciate your efforts, I will also try your code aswell - There was a problem with my example because the best place to assign the events was onNaviationComplete2 but this didn't work so I used BrowserTitleChange instead.

By the way, first time i've seen the API IsDialogMessage!

Thanks again,
Please Let me know what you think.

Best Regards,
- James
James, nice code, really. Why do you spend 120 points when your code is better than mine? :o)
Thank god you posted your code and I got it in my paqs now! ;-)
I'll test the code in the near future, I just looked at it yet.

Markus
Hi Markus,

LOL. What can I say? - I'm a big spender!

Actually I did ask for a net clean example, which you gave in the Message hander - Your logic was perfect though Micro$oft didn't allow it! - I was also desperate because I had loads of other problems to solve - I was trying to Multitask the problem solving.

Appreciate the comments.

Best Regards
James
> Your logic was perfect though Micro$oft didn't allow it!

The new code seems to work now ;-)

Markus

PS: Did I ever told you that I really enjoy reading this thread (and also working with you)?