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

HookMainWindow problem

363 views
Skip to first unread message

Maggie Owens

unread,
May 1, 2001, 7:26:26 PM5/1/01
to
In a component I'm writing, I'm attempting to use HookMainWindow to set
the value of a variable every time the user presses a key or clicks the
mouse. Problem is, even though the procedure is executed constantly, it
never seems to detect the proper messages. I need a bit of help with
this.

Here's the relevant code:

constructor TMyComponent.Create(AOwner: TComponent);
begin
// code
Application.HookMainWindow(MessageHook);
// more code
end;

function TMyComponent.MessageHook(var Msg: TMessage): Boolean;
begin
case Msg.msg of
WM_NCLBUTTONDBLCLK, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP,
WM_NCMBUTTONDBLCLK,
WM_NCMBUTTONDOWN, WM_NCMBUTTONUP, WM_NCRBUTTONDBLCLK,
WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_MENUCHAR, WM_MBUTTONUP,
WM_MBUTTONDOWN, WM_MBUTTONDBLCLK, WM_LBUTTONUP, WM_LBUTTONDOWN,
WM_LBUTTONDBLCLK, WM_KEYUP, WM_KEYDOWN, WM_HOTKEY, WM_CUT, WM_COPY,
WM_PASTE:
// Set variable -- THIS IS NEVER EXECUTED!
end;
Result := False; // allow normal processing of the event.
end;

TIA
--
Auto-replies will bounce. To reply to me, remove the "invalid"s from my
address.

Mike Lischke

unread,
May 1, 2001, 3:01:10 PM5/1/01
to
Hi Maggie,

> In a component I'm writing, I'm attempting to use HookMainWindow to set
> the value of a variable every time the user presses a key or clicks the
> mouse. Problem is, even though the procedure is executed constantly, it
> never seems to detect the proper messages. I need a bit of help with
> this.

You should be aware that not every message for every window in an application is
sent through the hidden application window's message queue (which you are
hooking with HookMainWindow). In fact most messages are directly sent to the
window message queue they belong to.

Some messages though (like those for keys) are forwarded within the VCL to the
owner form of a control. This could be a way to intercept them.

Ciao, Mike
--
Homepage: http://www.lischke-online.de
GraphicEx: http://www.lischke-online.de/Graphics.html
Virtual Treeview: http://www.lischke-online.de/VirtualTreeview.html
Unicode Edit and library: http://www.lischke-online.de/Unicode.html
Joint Endavour of Delphi Innovators (JEDI): www.delpi-jedi.org


Maggie Owens

unread,
May 1, 2001, 8:09:24 PM5/1/01
to
Mike,

Thanks. Now I feel like I'm not so crazy. The problem is that this code
needs to be self-contained within the component, and should not require
the component's user to add code to every form in the application. The
particular application I am using to test it has many forms.

I was originally using Application.ProcessMessages but became concerned
that if the user defines his own application.processmessages after I have
already set my own (which *is* designed to call the user's procedure),
there would be no way for me to know that, and some people on this ng
suggested I use HookMainWindow.

I think I may have to use SetWindowsHookEx, which looks a bit involved.
Do you have any other suggestions?

Thanks again.

Maggie;

In article <3aef07fa_1@dnews>, Mike Lischke quoth...

--

Alex Yackimoff

unread,
May 1, 2001, 4:35:43 PM5/1/01
to
Maggie, there's something wrong with your time or time zone settings.


Maggie Owens

unread,
May 1, 2001, 4:40:10 PM5/1/01
to
Yep. Sorry about that. I'd changed the time on my PC to test a routine
based on time, and forgot to put it back. My apologies! I'm always
annoyed when other people do this...

But Alex, do you have any hints for me? <g>

In article <3aef1e3f_2@dnews>, Alex Yackimoff quoth...


> Maggie, there's something wrong with your time or time zone settings.

Alex Yackimoff

unread,
May 2, 2001, 9:26:42 AM5/2/01
to
> But Alex, do you have any hints for me? <g>

First time I didn't look at the post closely.

HookMainWindow creates a hook for application window that is in fact only a
button in taskbar, it is always invisible and 0x0 in size, so it can't
receive mouse messages. If you want to intercept messages sent to form your
component is placed on you may assign WindowProc property and save old
procedure pointer and call it in yours.

[code]

procedure TMyComponent.HookForm;
if Owner is TForm then
begin
SaveWindowProc := TControl(Owner).WindowProc;
TControl(Owner).WindowProc := MyHook;
end;
end
...
procedure TMyComponent.MyHook(var Message: TMessage);
begin
...
SaveWindowProc(Message)
end;
...
destructor TMyComponent.Destroy;
begin
if Owner is TForm then
TControl(Owner).WindowProc := SaveWindowProc;
end;

[/code]

--
Alex Yackimoff http://yackimoff.cjb.net


Maggie Owens

unread,
May 2, 2001, 10:02:00 AM5/2/01
to
Alex,

Thanks for your reply. I don't think that this will work for me, for two
reasons:
1. This code needs to be encapsulated in a component.
2. It will generally need to work in an application with multiple forms,
any of which may need to be operated upon by the component.

This is why I think I might have to use SetWindowsHookEx, but I would
prefer to avoid it -- thus I am looking for suggestions, or at least a
*very* simple example of the use of SetWindowsHookEx, which doesn't do
anything fancy like record the keystrokes, send them to another
application or anything like that....

Maggie;

In article <3af00b3d_2@dnews>, Alex Yackimoff quoth...

--

Mike Lischke

unread,
May 2, 2001, 2:39:34 PM5/2/01
to
Maggie,

> I was originally using Application.ProcessMessages but became concerned
> that if the user defines his own application.processmessages after I have
> already set my own (which *is* designed to call the user's procedure),
> there would be no way for me to know that, and some people on this ng
> suggested I use HookMainWindow.

You cannot simply hook every window and redirect its messages without at least a
bit effort. My recommendation is to use a kind of registration scheme.
Everything (every window) which is supposed to work with your component must be
registered with your component, which keeps a list of windows and their
WndProcs. On register the window proc is replaced by your internal one and
whenever a message arrives it is redirected to the original proc (use the window
handle to identify it in your list). On unregister the original version is
restored.

Maggie Owens

unread,
May 2, 2001, 3:13:54 PM5/2/01
to
Mike,

Thanks for your reply, but I'm afraid I don't quite get what you mane by
a "registration scheme." Are you saying that I am going to have to make
some reference to the component in the FormCreate of each new window? (If
I, as the user of the component have to remember to do that, I might as
well remember not to reassign Application.ProcessMessages after creating
the component!) Or am I missing something.

BTW, in case you didn't read the beginning of this thread, all I really
need to trap is mouse clicks and key presses.

In article <3af0546d$1_1@dnews>, Mike Lischke quoth...


> You cannot simply hook every window and redirect its messages without at least a
> bit effort. My recommendation is to use a kind of registration scheme.
> Everything (every window) which is supposed to work with your component must be
> registered with your component, which keeps a list of windows and their
> WndProcs. On register the window proc is replaced by your internal one and
> whenever a message arrives it is redirected to the original proc (use the window
> handle to identify it in your list). On unregister the original version is
> restored.
>
> Ciao, Mike
--

Alex Yackimoff

unread,
May 2, 2001, 3:29:23 PM5/2/01
to
Maggie,

you better explain what (kind of) forms you need to watch at, under wich
circumstances the form should get beeing watched by your component.

Maggie Owens

unread,
May 2, 2001, 3:52:00 PM5/2/01
to
Alex,

Beginning at a certain time of day, I want to know when the user has
clicked the mouse or pressed a key and record the time (ticks, actually).
A timer which fires periodically compares the ticks now to the ticks
saved when the key press / mouse click message was detected. If five
minutes have passed, the application is terminated.

I had this working fine in an Application.ProcessMessages procedure, but
as I believe I explained before, But I realized that there would be a
problem if the user of the component reassigns
Application.ProcessMessages after the component has been created. That's
why I think some sort of hook ought to do the trick for me. I don't want
to require anything special of the component's user.

Maggie;

In article <3af0603b$1_1@dnews>, Alex Yackimoff quoth...

--

0 new messages