Friday, October 05, 2007

Fooling around with TWebbrowser #4

TWebbrowser and the Enter key
For some reason the Enter key in TWebbrowser does not work. This is very annoying, because users can't use the enter key to submit a form or, even worse, can not go to the next line in a textarea.

Searching the Internet I found two solutions to this problem:

Solution1: Use your applications MessageHandler;
The best solution,imo, is this one provided by SwissDelphiCenter. This solution 'listens' through the application's messagehandler to handle the keystrokes of your webbrowser. (Webbrowser1 in this case).
In my multitab browser I had to tweak this a little bit to give the handler the active webbrowser. (Don't forget to nil the FOleInPlaceObject when you switch TWebbrowser objects).

if AWebbrowser <> ActiveWebbrowser then begin   
FOleInPlaceActiveObject := nil;
Webbrowser1:= ActiveWebbrowser;

This works just fine! Kind of magic to me, but it works.

How to handle popup browsers?
As told in a previous episode of this serie, it is sometimes necessary to invoke the NewWindow2 event to handle popup-browsers. This is typicaly necessary when you need to retain a browser session.

In the NewWindow2 event a new form of you application is popped up modeless to hold the webbrowsers popup. To get the active webbrowser for your messagehandler in this scenario gets a little complicated, because there could be more popups open at the same time, and a popup could have one or more popups. The next solution seems to be more appropiate for that.

Solution 2: Use the Keybd_Event message
Well the Enter key might not work in textarea's, CONTROL + M seems to be doing just what we need, inserting a new line in the textarea.

So we must send a CTRL + M to our webbrowser. Here a solution, as found on Delphi3000, using the Keybd_event function. This function can be used to synthesize keystrokes. So send the CONTROL + M when an enter key is hit and we are done. (Supposing there is only a webbrowser on your popup form).

However there is one side effect with this solution, if you have a textarea and a submit button on your popup webpage, the page will also be submitted if you enter a new line in the textarea. Simple solution for this is to send the CANCEL event after the handling, so this is the code with the extra line (looks a bit messy):

procedure TfrmPopUpBrowser.FormKeyPress(Sender: TObject; 
var Key: Char);
//Don't forget ot set the Keypreview property
//of the form to true!
if (Key=#13) then begin
Key := #0;
Keybd_Event(VK_LCONTROL, 0, 0, 0); //Ctrl key down
Keybd_Event(Ord('M'), MapVirtualKey(Ord('M'), 0),
0, 0); // 'M' key down
Keybd_Event(Ord('M'), MapVirtualKey(Ord('M'), 0),
KEYEVENTF_KEYUP, 0); // 'M' Key up
0); // Ctrl key up
Keybd_Event(VK_CANCEL, 0, 0, 0);

More info on how use Keybd_event function take a look at the msdn article.

Well in my case it was a little harder to tackle this problem, but it works now just fine. Hope this usefull for others as well.


Jackem said...

This problem has been driving me mad, as neither solution works for me. The standard behaviour in my application seems to be for ENTER keypresses, regardless of whether Keypreview for the form is set to True or False, to go to the form. This means that, if the user is trying to send a message from web mail, the whole page is refreshed and the message wiped. If I try the second solution I think I get the same result. The first one does look promising but, for me, just leads to the ENTER key being ignored completely. This would allow users to send messages, but without any line feeds.

Is there something I've missed? Any help posted here would be gratefully received and would save me from pulling out the rest of my hair.

Jackem said...
This comment has been removed by the author.
Jackem said...

To clarify, if I add the code posted on SwissDelphiCentre to my application, this will compile and run ok with 'read only' web sites. However, if I try to use web mail, the results are still pretty useless. Pressing ENTER while typing into a form field no longer refreshes the whole page and wipes out the message, as it did without this code - instead, it does nothing at all.

I've hunted high and low but no-one else seems to have mentioned having any problems with this code. I'm using Internet Explorer 8 (and Delphi 5). Could it be that Microsoft has changed TWebBrowser's behaviour with that version of IE?

Jackem said...

I realise this is a very old page and that no-one may be reading this! The basic solution to my problem is to make the web browser the ONLY window on the form. The behaviour is then much more sensible with web forms. However, I still have a problem in that my TWebBrowser application will not recognise a default (Submit) button if the user tries to press it using the Enter key - which may have been the problem behaviour originally referred to here. The solutions given here don't seem to make any difference to that issue.

Daniel said...

Thank you. Really Thank you
The information about de TWebBrowser was a great relief for me.

Use an image as your UIBarButtonItem

Using an image as your UIBarButtonItem in your navigationcontroller bar can only be achieved by using a common UIButton as the BarButtonItem...