 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
dierk Guest
|
Posted: Sat Oct 04, 2003 2:27 pm Post subject: How can catch a component its ownerform´s windows messages? |
|
|
How can catch a component its ownerform´s windows messages?
The component should do something on following messages.
procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
procedure WMSize(var Message: TSIZE); message WM_Size;
procedure WMShowWindow (var Message: TWMShowWindow); message WM_ShowWindow;
procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
Thanks in adv.
Dierk
|
|
| Back to top |
|
 |
Yorai Aminov (TeamB) Guest
|
Posted: Sat Oct 04, 2003 3:08 pm Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
On 4 Oct 2003 07:27:59 -0700, "dierk" <nospam.ds (AT) csslabs (DOT) de> wrote:
| Quote: | How can catch a component its ownerform´s windows messages?
|
You need to subclass the form and replace its window procedure. You
can do this by setting its WindowProc property, or by calling
SetWindowLong, passing GWL_WNDPROC and an address for the new window
procedure.
Note that both methods are risky, and the only way to be sure they
work as expected is if you control all the code on the form and every
component on it. There is no standard way to "chain" subclasses, and
other components may try to do the same thing, effectively messing up
your new window procedure.
When using the WindowProc property, there's a greater risk that other
components will not call your window method. When using the
SetWindowLong function, there's a risk the window handle will be
destroyed (for example, when RecreateWnd is called), and your window
procedure will no longer be registered for the new window.
---
Yorai Aminov (TeamB)
http://develop.shorterpath.com/yorai
(TeamB cannot answer questions received via email.)
|
|
| Back to top |
|
 |
Jens Gruschel Guest
|
Posted: Sat Oct 04, 2003 6:54 pm Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
| Quote: | When using the WindowProc property, there's a greater risk that other
components will not call your window method. When using the
SetWindowLong function, there's a risk the window handle will be
destroyed (for example, when RecreateWnd is called), and your window
procedure will no longer be registered for the new window.
|
If more than one component changes the WindowProc, I think a great problem
is that these components have to be destroyed in reverse order. Of course
this doesn't matter if all components are destroyed when the form is
destroyed, but if you create A, then create B, and then remove A, B will not
work properly any more. That's because it is some kind of single linked
list, where you cannot remove one element in the middle of the chain, but I
see no way to implement a double linked list for such components.
Since the form knows all of its components (and everyone who knows the form,
knows the components, too), it would be possible to create a base class for
components, which change the form's WindowProc. Every new object of that
class type could check for other objects of this type and it would be
possible to make sure that the chain is not broken. Unfortunatelly you
cannot force everyone, who writes such a component, to inherit from a
certain class type (especially since a lot of such components already exist,
which all work well when used alone, whereas noone can guarantee they work
well together).
This is a problem I was thinking about for quite a while, so I really
welcome your comments.
Jens
|
|
| Back to top |
|
 |
Yorai Aminov (TeamB) Guest
|
Posted: Sun Oct 05, 2003 12:50 am Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
On Sat, 4 Oct 2003 20:54:14 +0200, "Jens Gruschel" <nospam (AT) pegtop (DOT) net>
wrote:
| Quote: | This is a problem I was thinking about for quite a while, so I really
welcome your comments.
|
Generally speaking, Windows is based on a simple object model, in
which every window (object) is responsible for its own behavior, by
responding to messages. This model does not include delegates, or
satellite objects, taking the workload off the main objects.
The Windows model includes one major exception to this rule -
notification messages are sent by controls to their parent windows.
This separates window objects into two class categories - windows and
controls (several other categories - such as dialogs - exist, but are
not fundamentally different than these two major categories).
The VCL is based on a similar model, since it was designed
specifically for Windows. Controls are encapsulated in components, and
messages are handled by object methods. In the VCL model, a control is
also responsible for handling notifications. This is achieved by
rerouting notification messages from parent windows to controls.
(Another fundamental difference between the VCL and the Windows model
is the notion of subclassing controls vs. instantiating a specific
class, but this is irrelevant to the messaging/invocation model.)
The basic model was designed to allow the creation and management of
screen objects, but did not include more advanced features, such as
multicast events and notifications. Since the VCL was built on that
model, and its goal was to provide a RAD framework, no major changes
to the basic model were introduced. (It's worth noting that the .NET
model includes multicast events.)
It has been my experience that fighting with deep-rooted design
decisions is an excercise in futility. More often than not, when
Windows makes it very difficult to do something, it's an indication
you're going about it the wrong way. I see such attempts every day in
these newsgroups - disabling task switching, changing the Windows
caption bar, overriding Windows security - these are all indications
of incorrect design or platform choices. You have to play by the rules
of your selected platform. If you wish to ignore them, you may have to
create a complete replacement (such as the .NET framework).
Once you realize this, the only valid solution to the problem at hand
- changing a window's behavior - has to be based on modifying the
window itself, not relying on external code. The cleanest, safest
method of changing a control's behavior is to subclass the control and
handle all relevant messages. This is true for every Windows object,
including main windows (VCL forms). If you want your form to behave
differently, create a new form class. The VCL and the IDE provide
means of making this class available to other developers (form
inheritance, RegisterCustomModule, IDE experts).
---
Yorai Aminov (TeamB)
http://develop.shorterpath.com/yorai
(TeamB cannot answer questions received via email.)
|
|
| Back to top |
|
 |
Jens Gruschel Guest
|
Posted: Sun Oct 05, 2003 10:35 am Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
| Quote: | It has been my experience that fighting with deep-rooted design
decisions is an excercise in futility. More often than not, when
Windows makes it very difficult to do something, it's an indication
you're going about it the wrong way. I see such attempts every day in
these newsgroups - disabling task switching, changing the Windows
caption bar, overriding Windows security - these are all indications
of incorrect design or platform choices. You have to play by the rules
of your selected platform. If you wish to ignore them, you may have to
create a complete replacement (such as the .NET framework).
|
I agree to almost everything you say (except that I don't like .net
multicast events very much, I prefer Java's listener model - but that's not
the point, I like Windows default behaviour, too, and hate applications that
try to "hack" things you don't expect). But sometimes a component that
catches its parent's messages really would be nice. If you need a window
that moves in a special way (sticking together with other windows like in
Photoshop for example), you can write you own TMagnetForm. But now you want
a special communication mechanism between two forms using messages, no
problem, write your own TCommunicationForm. Write some more of these special
forms... I'm pretty sure you will need a form that needs to be both, a
TMagnetForm and a TCommunicationForm (or whatever). And I'm no friend of a
TSuperMagnetCommunicationAndEverythingForm. Yes, you can write components
(or simple classes) that don't catch the messages themselves, but provide
some method for passing them (and add some additional code to the form's
WndProc). But I really think it would be smarter just to drop a component
onto the form. There is nothing you can do wrong, and even if someone else
works on this project later, it's easy to understand. And it's not for some
special hack, that tricks Windows. It's just something that was not included
to Delphi because noone thought of it. Well, that's my opinion.
Jens
|
|
| Back to top |
|
 |
Guest
|
Posted: Mon Oct 06, 2003 4:05 pm Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
Mhh...I tested this..It seems to work.
Could this be the way, how I can serve my problem? Or is this on anyway
risky?
Regards
Dierk
__________________________________________
constructor TMyComponent.Create(AOwner: TComponent);
begin
if not (AOwner is Tform) then
raise Exception.Create('Owner must be TFORM');
inherited Create(AOwner);
FOwnerForm:=Tform(AOwner);
if not (csDesigning in ComponentState) then
begin
SetNewWnd; // set the New wnd routine - look next procedure
........
__________________________________________
procedure TMyComponent.SetNewWnd;
begin
FNewProc := MakeObjectInstance(NewWndProc);
FOldProc := Pointer(GetWindowLong((FOwnerForm as TForm).Handle,
GWL_WNDPROC));
SetWindowLong((FOwnerform).Handle, GWL_WNDPROC, Longint(FNewProc));
end;
__________________________________________
procedure TMyComponent.NewWndProc(var Message: TMessage);
begin
//calling first the old windowproc
Result := CallWindowProc(FOldProc, (FOwnerForm as TForm).Handle, Msg,
wParam, lParam);
// and than do what you want
with Message do
begin
........
__________________________________________
|
|
| Back to top |
|
 |
Yorai Aminov (TeamB) Guest
|
Posted: Tue Oct 07, 2003 12:26 am Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
On Mon, 6 Oct 2003 18:05:54 +0200, <antispam.ds (AT) csslabs (DOT) de> wrote:
| Quote: | Mhh...I tested this..It seems to work.
|
Good. Just remember you may have problems is other components on the
form try to do the same thing.
---
Yorai Aminov (TeamB)
http://develop.shorterpath.com/yorai
(TeamB cannot answer questions received via email.)
|
|
| Back to top |
|
 |
Guest
|
Posted: Tue Oct 07, 2003 10:50 am Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
| Quote: | Good. Just remember you may have problems is other components on the
form try to do the same thing.
|
Really? I think that if the other component do it by the same way (save on
create and calling in new Window proc first the previously window proc), it
should be work also.
Perhaps I am wrong?
Dierk
|
|
| Back to top |
|
 |
Jens Gruschel Guest
|
Posted: Tue Oct 07, 2003 3:29 pm Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
| Quote: | Really? I think that if the other component do it by the same way (save on
create and calling in new Window proc first the previously window proc),
it
should be work also.
|
Yes, it should work as long as you don't remove the component you created
first, which restores the original WindowProc, not knowing that it was
changed meanwhile.
Jens
|
|
| Back to top |
|
 |
Yorai Aminov (TeamB) Guest
|
Posted: Wed Oct 08, 2003 12:18 am Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
On Tue, 7 Oct 2003 12:50:33 +0200, <antispam.ds (AT) csslabs (DOT) de> wrote:
| Quote: | Really? I think that if the other component do it by the same way (save on
create and calling in new Window proc first the previously window proc), it
should be work also.
|
Only if the components release their hooks in reverse order to the
hook creation order. Also, all such components have to treat window
re-creation the same way - refresh their hook or ignore it.
---
Yorai Aminov (TeamB)
http://develop.shorterpath.com/yorai
(TeamB cannot answer questions received via email.)
|
|
| Back to top |
|
 |
Guest
|
Posted: Wed Oct 08, 2003 4:33 pm Post subject: Re: How can catch a component its ownerform´s windows messag |
|
|
OK! Wonderful, then I can solve this problems on that way.
Thanks
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|