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

How Do I Capture WM messages in a component

585 views
Skip to first unread message

Bruce Thomas

unread,
Jul 27, 1998, 3:00:00 AM7/27/98
to
What's the best way to capture WM_???? messages in a custom component. I
used the normal method for a form but a custom component placed on a form
never receives the message I am looking for but the parent form does...

BTW, my component has to be self-contained and not rely on the form
processing the WM message...

Thanks

Rick Rogers (TeamB)

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
On Mon, 27 Jul 1998 17:49:53 -0500, "Bruce Thomas"
<bru...@simplifi.com> wrote:

> What's the best way to capture WM_?

This is tough... you'll need to subclass the form's Window procedure
(see SetWindowLong and GWL_WNDPROC in the API), but this approach is
very fragile. More than one component on a form which subclass the
WndProc can easily step on each other. See if you can't choose another
approach.

--
Rick Rogers (TeamB) | Fenestra Technologies
http://www.fenestra.com/

Kurt Barthelmess (TeamB)

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
Bruce -

Unless your component descends from TWinControl, it will not have a
window handle and therefore can not receive messages. If you think
that's not the problem, exactly what does your component descend from,
and what message are you not getting?

Good luck.

Kurt

Felix Venniker

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
You could intercept the WindowProc property of the form of the custom
component by assigning your own method to it. Then in your component's
method you look for the message you want and the rest you pass back to the
form

Example:

TYourComponent = class(TWinControl)
procedure YourMethod(var Message: TMessage);
end;

procedure TYourComponent.CreateWnd;
begin
inherited;
FForm:= GetParentForm(Self);
if Assigned(FForm) then
begin
FSaveFormWindowProc:= FForm.WindowProc;
FForm.WindowProc:= YourMethod;
end;
end;

procedure TYourComponent.YourMethod(var: Message: TMessage);
begin
if (Message.Msg = WM_XXX) then DoYourStuff;
FSavedFormWindowProc(Message);
end;

--
Felix Venniker

fven...@landmarksdg.com

Bruce Thomas <bru...@simplifi.com> wrote in article
<6pj02m$a6...@forums.borland.com>...

Bruce Thomas

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
>>>You could intercept the WindowProc property of the form of the custom

Felix,

This is what I have and it works. I just want to make sure it the most
efficient way of doing it,

TMyThing = class(TComponent)
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

private
FOnChange: TNotifyEvent;
FWindowHandle : HWND;

procedure WndProc(var Msg: TMessage);
.....

constructor TMyThing.Create(AOwner: TComponent);
begin
inherited Create(AOwner);

FWindowHandle := AllocateHWnd(WndProc);
......

destructor TMyThing.Destroy;
begin

DeallocateHWnd(FWindowHandle);
inherited Destroy ()
........

procedure TMyThing.WndProc(var Msg: TMessage);
begin
try
if (Msg.Msg = WM_?????) then
..........
else
Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam,
Msg.lParam);
except
Application.HandleException(Self);
end;
end;

Thanks,
Bruce


Ray Lischner

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
On Tue, 28 Jul 1998 09:24:03 -0500, "Bruce Thomas"
<bru...@simplifi.com> wrote:

>TMyThing = class(TComponent)
> constructor Create(AOwner: TComponent); override;
> destructor Destroy; override;
>
> private
> FOnChange: TNotifyEvent;
> FWindowHandle : HWND;
>
> procedure WndProc(var Msg: TMessage);

Instead of using WndProc, declare message handlers, e.g.,
procedure WmMsg...(var Msg: TWmMsg....); message WM_Msg...;

Let Delphi do the dispatching for you.
--
Ray Lischner (http://www.tempest-sw.com/)
Author of "Hidden Paths of Delphi 3: Experts, Wizards, and the Open Tools API"

Bruce Thomas

unread,
Jul 28, 1998, 3:00:00 AM7/28/98
to
>Instead of using WndProc, declare message handlers, e.g.,
> procedure WmMsg...(var Msg: TWmMsg....); message WM_Msg...;

>Let Delphi do the dispatching for you.

Ray,

That's exact the way I had it initially, but when I placed the component on
a form it never received the message, even though the parent form was
getting the message. I had the message handler declared in the component
but the component never received it, but I placed the same declaration on
the form and the form got the message. That's why I posted the message to
see I am doing something wrong... If you have some ideas about how I can do
this without WndProc let me know (a sample would be cool...)...


Ray Lischner

unread,
Jul 30, 1998, 3:00:00 AM7/30/98
to
On Tue, 28 Jul 1998 11:48:12 -0500, "Bruce Thomas"
<bru...@simplifi.com> wrote:

>That's exact the way I had it initially, but when I placed the component on
>a form it never received the message, even though the parent form was
>getting the message. I had the message handler declared in the component
>but the component never received it, but I placed the same declaration on
>the form and the form got the message. That's why I posted the message to
>see I am doing something wrong... If you have some ideas about how I can do
>this without WndProc let me know (a sample would be cool...)...

Sorry, my mistake. AllocateHWnd needs a window procedure. That's how
it works. You could have the window procedure dispatch to your
control, but that's not worth the effort.

George Birbilis

unread,
Aug 28, 1998, 3:00:00 AM8/28/98
to
> >Instead of using WndProc, declare message handlers, e.g.,
> > procedure WmMsg...(var Msg: TWmMsg....); message WM_Msg...;
> That's exact the way I had it initially, but when I placed the component
on
> a form it never received the message, even though the parent form was
> getting the message.
I believe the Delphi3 docs were saying that you have to enable
some bool to allow dispatching to your component (was it at
design or run time that you tested it?)...

There is a whole section in the Delphi 3 docs on message
handling, however the "message WM_Msg..."
expects WM_Msg to be a constant...
I want to do IPC (Interprocess communication) through
messages and I need unique messages...
There is a RegisterMessage (or something like that) proc
in Win32 that takes a unique string and registers a message
for you... Next calls to it with the same string return the same
message ID, so that all your running apps can sync on the
same message ID that isn't hardcoded in them but generated
by Win32 at runtime (the first free message ID they can find)
Can't use the standard Delphi dispatcher cause it takes constants,
so one has to dispatch by himself...
What's more controls that are not derived from TWinControl
don't have a real window (maybe that was your problem), so
they can't directly receive events from what I understand (but
expect the form to dispatch events to them [only the ones using
the standard dispatcher mechanism?])

The best way I've found so far was some TBroadcast component
that used WM_COPY to exchange data packets of some length
between apps... It created a window handle for the component...
I changed it to work with any data size and am creating an
hierarchy of provider and consumer components for certain
common properties (TColor,String,TDateTime)...
Hope I can make it with exchanging streamized components...

Does anyone know which other apps use WM_COPY?
I wouldn't want to interfere with the system or other apps when exchanging
data in this way...

BTW it's very fast!!! Put 20 consumers and a provider on different
forms... Changed a property in the provider and all the consumers
changed their corresponding property too immediately...

0 new messages