Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Accelerator Keys and TWebBrowser

594 views
Skip to first unread message

Marcio

unread,
Aug 22, 2008, 4:38:06 PM8/22/08
to
Hello all. I have an application that was originally created in
Delphi 6 and that I just compiled using Delphi 2007. So far, so good,
but there's one problem that is puzzling me:

The Setup:
A form containing a TWebBrowser and two TButtons: OK and Cancel. The
TWebBrowser component is in Editor mode so the user can input text.
The OK button has the letter "O" as an accelerator key, and --
likewise -- the Cancel button has the letter "C" as its shortcut
("&OK" and "&Cancel" as captions).

The Problem:
When typing text into the TWebBrowser, the letters "O" and "C" will
call the buttons' actions as if the user is pressing ALT-O or ALT-C.
All other letters work just fine.

What Seems to be the Cause:
When the application is compiled with Delphi 6, TWebBrowser traps all
keyboard messages within itself. In fact, a problem I had with the
old Delphi 6 setup was the inability to call the buttons using their
accelerator keys once the TWebBrowser had the focus. For that, I had
to add handlers for ALT-O and ALT-C (OK and Cancel) in the
TWebBrowser.OnTranslateAccelerator event.
Now, with Delphi 2007, the problem is the opposite: all keyboard
messages are processed within the TWebBrowser, but they are all passed
on to the parent form's handler afterwards, triggering the button
actions.

What I Have Tried So Far:
I added a message handler to the form so I could trap the keystrokes
in TWebBrowser before they're sent to the form. The problem is that
the keyboard messages arrive BEFORE the TWebBrowser has a chance to
process them, so my message handler becomes an ill-suited place to
monitor or fix the situation. TWebBrowser.OnTranslateAccelerator also
traps the keystrokes, but I can only return S_OK (handled) or S_FALSE
(not handled). If I return S_OK, the problem disappears but the user
can't type anything into the box. Likewise, if I allow the
TWebBrowser to continue processing (by returning S_FALSE), then the
keystrokes are also sent to the parent form.

Question:
Why me? Why? :-)
Just kidding, but I can't understand why the problem exists in the
first place. All other controls handle their own keyboard messages
and let out only WM_SYSCHAR messages. TWebBrowser lets out
everything. The other part that I don't understand is why the
accelerators are being called without an ALT key down.

Anyway, is there a way to prevent TWebBrowser from sending keyboard
messages to its parent form?

Any help on solving this problem would be highly appreciated.

MV

Marcio

unread,
Aug 22, 2008, 11:18:14 PM8/22/08
to
OK, like many other questions, this one may never get an answer. But
let me share with all a workaround I found to make TWebBrowser stop
behaving like a rogue component.

I had to find an event that would fire right after
TWebBrowser.OnTranslateAccelerator to give it a chance to perform the
required actions. Application.OnMessage didn't do the trick, as I
mentioned before, because it fired right before
OnTranslateAccelerator. To make this happen, I created my own
"WindowProc" method, replacing the original window procedure of the
form where the TWebBrowser control is located. I noticed that my
WindowProc function is called right after
TWebBrowser.OnTranslateAccelerator(KEYDOWN) and immediately before
TWebBrowser.OnTranslateAccelerator(KEYUP). In other words, the
perfect place to "monitor" the messages coming from TWebBrowser into
my form. The next step was to figure out what message(s) actually
triggered the actions on the form, and I admit that it was a trial and
error ordeal. After a few hours and many message filtering techniques
later, I observed that the first meaningful message coming into my
WindowProc method after TWebBrowser.OnTranslateAccelerator had the ID
45062. I then made my function ignore that message, and voilà. It
worked. I'm not sure yet what else it will break, but so far my tests
have been good. Here's the code:

procedure TForm1.MyWindowProc(var Msg:TMessage);

begin
// call the old handler only if the message is not 45062
if Msg.Msg<>45062 then
OldWindowProc(Msg);
end;

procedure TForm1.FormCreate(Sender: TObject);

begin
OldWindowProc:=Self.WindowProc;
Self.WindowProc:=MyWindowProc;
end;

procedure TForm1.FormDestroy(Sender: TObject);

begin
Self.WindowProc:=OldWindowProc;
end;

One more thing: I do know that this is not an "elegant" solution.
But I'll take something that works half-right over nothing any day.
If anyone knows of another, better method to solve this problem,
please post.

MV

Xu, Qian

unread,
Aug 23, 2008, 6:49:04 PM8/23/08
to

It seems many people use this solution. I do not know, if this is an
issue of Delphi's implementation? If you know C++, maybe you can read
the source of Firefox.

I use a similar solution as yours. It is not only ugly, but also buggy.
I have some problems with ENTER, ESC, especially in ActiveX forms, MHTML
pages and FckEditor.

--
Xu, Qian (stanleyxu)
http://stanleyxu2005.blogspot.com

Marcio

unread,
Aug 25, 2008, 5:26:05 PM8/25/08
to
On Aug 23, 5:49 pm, "Xu, Qian" <quian...@stud.tu-ilmenau.de> wrote:
> If you know C++, maybe you can read
> the source of Firefox.

I don't think Firefox uses IE in the background to render pages (that
would be too funny! :-) But maybe I should start looking at other
ways to render and edit HTML.

MV

Xu, Qian

unread,
Aug 26, 2008, 1:07:34 AM8/26/08
to

No, I mean that they use a similar way to handle keystrokes, which might
be helpful to you.

0 new messages