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

Detect ParentForm change

78 views
Skip to first unread message

Maël Hörz

unread,
Apr 10, 2008, 12:08:37 PM4/10/08
to
Hello,

I'm writing a component that needs to be notified when its parent form
changes.

The parent form is not necessarily the same as the control's immediate
parent, for example when the control is placed on a frame or a panel,
groupbox etc. To get the parent form I use GetParentForm from Forms.pas.

The issue is that overriding SetParent will not work to detect a change
of the parent form since the component could be placed on a frame and
would have the frame as parent. Then when I put that frame on another
form the control's setparent will not be called (only the frame's
setparent).

In summary, is there a way to detect if the parent form has changed?

Regards, Maël.

Remy Lebeau (TeamB)

unread,
Apr 10, 2008, 2:57:55 PM4/10/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47fe...@newsgroups.borland.com...

> I'm writing a component that needs to be notified
> when its parent form changes.

Why? It is very usual for a component to care about such things at all.

> In summary, is there a way to detect if the parent form
> has changed?

There is no direct way to detect that, no. Such a change is not propagated
down the parent/child hierarchy to child components. About the only thing
that you would be able to detect is your component's HWND being destroyed
(if it has one) due to its parent HWND being destroyed during the change.
But that is not a good indicator, since other factors can also cause HWNDs
to be destroyed/recreated on the fly.


Gambit


Maël Hörz

unread,
Apr 10, 2008, 3:25:39 PM4/10/08
to
>> I'm writing a component that needs to be notified
>> when its parent form changes.
>
> Why? It is very usual for a component to care about such things at all.
Because I need to detect when a form's OnCloseQuery event is called.
I.e. I do something like ParentForm.OnCloseQuery := FormCloseQuery;
where FormCloseQuery is a method of my component. (If OnCloseQuery was
already set, I call the old event handler in FormCloseQuery).

Unfortunately I haven't found a way to make the VCL ask a components
"permission" before it closes, that is why I need to use the
OnCloseQuery-event.

When the parent form changes I have to handle the OnCloseQuery-event of
the new parent form and not the old one, that is why I need to know when
the parent form changes.

Remy Lebeau (TeamB)

unread,
Apr 10, 2008, 5:03:04 PM4/10/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47fe6928$1...@newsgroups.borland.com...

> Because I need to detect when a form's OnCloseQuery
> event is called.

Again, why? Components do not need, and should not care about, that kind of
access to begin with. What are you trying to accomplish exactly? There is
likely to be a better option that you have not considered yet.

> I do something like ParentForm.OnCloseQuery := FormCloseQuery;

That is a very bad idea. That prevents the user from being able to assign
his/her own handler at all, or worse overrides yours.

> where FormCloseQuery is a method of my component. (If
> OnCloseQuery was already set, I call the old event handler
> in FormCloseQuery).

Still a bad idea. What if the user changes their OnCloseQuery handler after
you have stored it? Events are not easily chainable like that.

Why not just have the user manually call a public method of your component
inside their own OnCloseQuery handler? Or have your component expose its
own OnCanClose event that the user can assign a handler to after
assigning/changing the parent form.

> Unfortunately I haven't found a way to make the VCL
> ask a components "permission" before it closes

Because there isn't a way to do that.

> that is why I need to use the OnCloseQuery-event.

But for what reason, though? Why does the component need to have any say in
whether its parent form can close or not?

> When the parent form changes I have to handle the

> OnCloseQuery event of the new parent form and not
> the old one

Only because your component design is suspicious to begin with, and likely
needs to be changed.

> that is why I need to know when the parent form changes.

Sorry, but there simply is no automated way to detect that from inside a
component. The user's code will have to manually inform the component when
the change occurs.


Gambit


Maël Hörz

unread,
Apr 10, 2008, 6:18:01 PM4/10/08
to
>> Because I need to detect when a form's OnCloseQuery event is
>> called.
>
> Again, why? Components do not need, and should not care about, that
> kind of access to begin with. What are you trying to accomplish
> exactly? There is likely to be a better option that you have not
> considered yet.
It is work that has to be done by the component, since it is about
validation. I have considered other options which would be cleaner from
a design point of view but not from usability, and usability is the
whole point of the component.

>> where FormCloseQuery is a method of my component. (If OnCloseQuery
>> was already set, I call the old event handler in FormCloseQuery).
>
> Still a bad idea. What if the user changes their OnCloseQuery
> handler after you have stored it? Events are not easily chainable
> like that.

I know, IMO this is a design problem of events. Anyway, it is the only
way to get notified.

> Why not just have the user manually call a public method of your
> component inside their own OnCloseQuery handler? Or have your
> component expose its own OnCanClose event that the user can assign a
> handler to after assigning/changing the parent form.

Would be possible, but the component needs to do some checks before the
form gets closed and stop it from closing if the validation fails. This
is not an optional behavior, therefore I dislike the idea of letting the
user (just me in this case, anyway) assign the event. Things that should
always be done should not rely on you doing it all the time (calling a
public method of the component), but should work automatically to reduce
the potential of errors.

>> Unfortunately I haven't found a way to make the VCL ask a
>> components "permission" before it closes
>
> Because there isn't a way to do that.

I haven't found anything in the VCL source code, but I avoid being so
affirmative. Most of the time there is a way.

>
>> that is why I need to use the OnCloseQuery-event.
>
> But for what reason, though? Why does the component need to have any
> say in whether its parent form can close or not?
>
>> When the parent form changes I have to handle the OnCloseQuery
>> event of the new parent form and not the old one
>
> Only because your component design is suspicious to begin with, and
> likely needs to be changed.

It is not suspicious. Just because the VCL doesn't gives me the
notification I need doesn't mean my design is suspicious. A component
also gets notified about focus changes to another control, even if the
focus is not moving or going to your control (CM_FOCUSCHANGED). So you
get informed about an action on the form level and things happening to
other components. The CloseQuery-method I want to hook is on the same level.
I could write a descendant of TForm to implement a CloseQuery-message,
such that my control would get informed but I wanted to avoid that,
since the control would be dependent of this TForm-descendant.

Still thanks for trying to help,
Maël.

Marc Rohloff [TeamB]

unread,
Apr 10, 2008, 6:42:49 PM4/10/08
to

IMO, You have it backwards. Your form should ask any frames if it can
close. I also wouldn't move controls from one form to another.

--
Marc Rohloff [TeamB]
marc -at- marc rohloff -dot- com

Remy Lebeau (TeamB)

unread,
Apr 10, 2008, 7:05:37 PM4/10/08
to

"Marc Rohloff [TeamB]" <ma...@nospam.marcrohloff.com> wrote in message
news:u8yhdt7u...@dlg.marcrohloff.com...

> IMO, You have it backwards. Your form should ask any
> frames if it can close.

Agreed.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 10, 2008, 7:13:10 PM4/10/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47fe918b$1...@newsgroups.borland.com...

> Would be possible, but the component needs to do some checks
> before the form gets closed and stop it from closing if the validation
> fails.

There are ways a TForm can be closed without triggering the OnCloseQuery
event at all, thus bypassing your component's operations.

> I haven't found anything in the VCL source code, but I avoid
> being so affirmative. Most of the time there is a way.

Not this time.

> It is not suspicious. Just because the VCL doesn't gives me
> the notification I need doesn't mean my design is suspicious.

Depends on what kinds of validation you are trying to do.

> A component also gets notified about focus changes to another
> control, even if the focus is not moving or going to your control
> (CM_FOCUSCHANGED).

Only because TButton needs that notification in order to change its
appearence and behavior based on the currently focused control when its
Default property is set to True. No other component issues or processes
that notification otherwise.

Most other VCL notifications is not broadcasted all the way down the
parent/child hierarchy to all components like that. They are only issued to
a control's the immediate children. System notifications, like
WM_SYSCOLORCHANGE, WM_WININICHANGE, WM_FONTCHANGE, etc, get broadcasted
further down the chain to every component. But those are isolated cases.
There is no general purpose broadcast-to-all functionality in the VCL.

> So you get informed about an action on the form level and things
> happening to other components.

Even then, component do not have any influence over the broadcast, or the
action being broadcasted about. They can only update themselves locally
based on whatever was changed higher up. That is not the case for what you
are attempting.

> The CloseQuery-method I want to hook is on the same level. I
> could write a descendant of TForm to implement a CloseQuery

> message such that my control would get informed

Only if you manually iterate through every nested component yourself. The
Broadcast() and NotifyControls() methods of TWinControl only broadcast a
given message to the TWinControl's immediate child controls. Those
controls, in turn, only broadcast the message onwards for certain system
messages. You can't pass your own custom message to Broadcast() or
NotifyControls() and expect every component to see it. That is not how the
VCL's message system works. Also, broadcasting only works for
TControl-based components anyway. If your component is non-visual, derived
from TComponent directly, then you will never receive broadcast messages at
all.

If you ended up writing a custom TForm descendant, I would not suggest using
broadcasted messages at all. I would suggest instead having your TForm
class maintain an internal list of pointers to any component instances that
belong to it. It can then run through that list when needed, notifying the
components directly.

> I wanted to avoid that, since the control would be dependent of this
> TForm-descendant.

There is simply nothing you can do in the current VCL architecture to
accomplish what you are attempting. Some amount of manual work outside of
the component is required to fill in the missing gap.


Gambit


Marc Rohloff [TeamB]

unread,
Apr 10, 2008, 8:13:54 PM4/10/08
to
On Fri, 11 Apr 2008 00:18:01 +0200, Maël Hörz wrote:

> It is work that has to be done by the component, since it is about
> validation.

I'm curious as to how you handle it when a form is cancelled and
validation shouldn't happen?

Maël Hörz

unread,
Apr 10, 2008, 8:30:59 PM4/10/08
to
>> When the parent form changes I have to handle the OnCloseQuery-event of
>> the new parent form and not the old one, that is why I need to know when
>> the parent form changes.
>
> IMO, You have it backwards. Your form should ask any frames if it can
> close.
... And the frame should ask the components if it could close.
As a design principle, sure, that is the way to go. This is also what I
was looking for in the VCL, but didn't exist. So I looked for a hack :-)

> I also wouldn't move controls from one form to another.

I don't intend to. But somebody could move it using a SetParent call,
and since I cannot exclude that there is a legitimate use (after all
Parent is a public property), I want the component to handle this safely.

Having a TForm-descendant (TXForm) is the "most natural" implementation,
though as I want to guarantee that the component gets asked if the form
can close I have to reject parent form that are not of type TXForm.

So I'm still left with the problem how to detect when the parent form
changes to reject parent forms of the wrong type. I don't need this
check for the implementation, but I want to avoid such a mistake to go
unnoticed.

Regards, Maël.

Pieter Zijlstra

unread,
Apr 10, 2008, 8:33:21 PM4/10/08
to
Maël Hörz wrote:

When talking about forms and components there is a mechanism where the
component is informed when the *owner* changes, usually all components
are owned by the the form (when just using the form designer and not
creating them at runtime).

More in general, it might help if you tell "the why", you want it to be
notified. That might give you some alternative approaches to the
"problem".

--
Pieter

Maël Hörz

unread,
Apr 10, 2008, 9:01:03 PM4/10/08
to
> I'm curious as to how you handle it when a form is cancelled and
> validation shouldn't happen?
I check the forms ModalResult or if the pressed button has the
Cancel-property set.

Maël Hörz

unread,
Apr 10, 2008, 8:58:52 PM4/10/08
to
>> Would be possible, but the component needs to do some checks
>> before the form gets closed and stop it from closing if the validation
>> fails.
>
> There are ways a TForm can be closed without triggering the OnCloseQuery
> event at all, thus bypassing your component's operations.
Well, Windows messages are caught (WM_CLOSE, WM_QUERYENDSESSION) and the
event is called when the app or a modal form closes. If the process is
killed, then it is okay that this event isn't called, but apart from
forcibly closing a form like this I don't see a case where this event
isn't called.

> Only because TButton needs that notification in order to change its
> appearence and behavior based on the currently focused control when its
> Default property is set to True. No other component issues or processes
> that notification otherwise.

Well, this very much applies the same way to my need. My component is
currently the only one that would use such a CloseQuery-"question",
obviously since that functionality isn't available in the current VCL
(not a feature request). Apart from that, you cannot know if other
custom components wouldn't need to track the focus state the same way
the buttons do (for similar purposes).

>> So you get informed about an action on the form level and things
>> happening to other components.
>
> Even then, component do not have any influence over the broadcast, or the
> action being broadcasted about. They can only update themselves locally
> based on whatever was changed higher up. That is not the case for what you
> are attempting.

I think we are talking about a modified TForm or a TForm-descendant.
In this case this is no problem at all: Just send a message to all
controls (say WM_CANCLOSE) and let each control that wants to influence
the closing behavior set the message-result accordingly. If one returns
false the form doesn't close. To do this is suffices to override
TForm.CloseQuery.

>
>> The CloseQuery-method I want to hook is on the same level. I
>> could write a descendant of TForm to implement a CloseQuery
>> message such that my control would get informed
>
> Only if you manually iterate through every nested component yourself. The
> Broadcast() and NotifyControls() methods of TWinControl only broadcast a
> given message to the TWinControl's immediate child controls. Those
> controls, in turn, only broadcast the message onwards for certain system
> messages. You can't pass your own custom message to Broadcast() or
> NotifyControls() and expect every component to see it. That is not how the
> VCL's message system works. Also, broadcasting only works for
> TControl-based components anyway. If your component is non-visual, derived
> from TComponent directly, then you will never receive broadcast messages at
> all.

CM_SYSFONTCHANGED works, so I can achieve similar things with a custom
message of my own.

> If you ended up writing a custom TForm descendant, I would not suggest using
> broadcasted messages at all. I would suggest instead having your TForm
> class maintain an internal list of pointers to any component instances that
> belong to it. It can then run through that list when needed, notifying the
> components directly.

This is only meant for controls visible to the user, support for
components aren't needed. Either way, it is possible to iterate
*somehow* over all controls/components, the concrete implementation for
notifying them all is really not a problem.

>
>> I wanted to avoid that, since the control would be dependent of this
>> TForm-descendant.
>
> There is simply nothing you can do in the current VCL architecture to
> accomplish what you are attempting. Some amount of manual work outside of
> the component is required to fill in the missing gap.

I understood, but as noted in the reply to Marc, there are still
problems, even if the form ask the controls.

Remy Lebeau (TeamB)

unread,
Apr 11, 2008, 1:08:25 AM4/11/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47fe...@newsgroups.borland.com...

> ... And the frame should ask the components if it could close.

Yes, it should.

> I don't intend to. But somebody could move it using a SetParent
> call, and since I cannot exclude that there is a legitimate use (after
> all Parent is a public property), I want the component to handle
> this safely.

It seems to me that you are probably handling validation at the wrong time.
If your component is visual (which you did not comment on when I asked you
earlier), then perhaps you should be performing validation when the
component looses input focus, rather than when the form is closed.

> So I'm still left with the problem how to detect when the parent
> form changes

To which you already have the answer - there is nothing in the native VCL to
allow that when your component is not placed on the TForm directly
(otherwise you could just override SetParent() and be done with it). You
must implement some kind of manual operation to externally invoke your
component when needed. Either derive a custom TForm, or call a method of
the component from the user's own OnCloseQuery handler, or even derive your
own set of container components (TMyPanel) that can pass your custom
messages down the hierarchy. There is no other way to do what you are
asking for. Otherwise, you will just have to abandon the component. It
won't work the way you want it to, sorry.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 11, 2008, 12:49:50 AM4/11/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47fe...@newsgroups.borland.com...

> Well, Windows messages are caught (WM_CLOSE, WM_QUERYENDSESSION)
> and the event is called when the app or a modal form closes. If the
> process is killed, then it is okay that this event isn't called, but apart
> from forcibly closing a form like this I don't see a case where this
> event isn't called.

Post a WM_QUIT message to the main thread, such as by calling
Application.Trminate(), and see what happens.

> Well, this very much applies the same way to my need. My component
> is currently the only one that would use such a CloseQuery-"question",

The point I was making is that the VCL is designed to allow CM_FOCUSCHANGED
and other system messages to be broadcasted to all components in the
parent/child hierarchy. It is not designed to do the same thing with custom
messages.

> Apart from that, you cannot know if other custom components wouldn't
> need to track the focus state the same way the buttons do (for similar
> purposes).

I know that none of Borland's standard components do. I have their source
code, from a half-dozen different versions. If third-party components do,
that is separate.

> CM_SYSFONTCHANGED works

Because that is one of a handful of system-level messages that all visual
controls must handle, so TControl is specifically coded to allow that
message (and a few others) to be broadcasted to every component in the
hierarchy.

> so I can achieve similar things with a custom message of my own.

Only if you manually loop through every component yourself. Again, the VCL
is *NOT* coded to allow custom messages to be broadcasted deep enough to do
what you are asking. If your component were placed on another component
(TPanel, for instance) instead of the TForm directly, it would not receive
the broadcast if it was sent at the TForm level.

> This is only meant for controls visible to the user, support for
> components aren't needed.

Non-TControl components can't receive messages anyway.

> Either way, it is possible to iterate *somehow* over all
> controls/components

Of course it is possible. But you have to do it yourself, in a recursive
loop.

> the concrete implementation for notifying them all is really not a
> problem.


The issue is that you are asking for a feature that the VCL simply does not
have, and you are not willing to implement it yourself for lack of
convenience. You have deadlocked yourself.


Gambit


Maël Hörz

unread,
Apr 11, 2008, 8:50:39 AM4/11/08
to
> Post a WM_QUIT message to the main thread, such as by calling
> Application.Trminate(), and see what happens.
If it would close without calling OnCloseQuery, that is ok, since the
entire app is closed. I only want to avoid that the form is closed
before the entries are validated. If the form is closed together with
the app than the values are discarded anyway. (It is about checking
entry in a visual control).

>> Well, this very much applies the same way to my need. My component
>> is currently the only one that would use such a CloseQuery-"question",
>
> The point I was making is that the VCL is designed to allow CM_FOCUSCHANGED
> and other system messages to be broadcasted to all components in the
> parent/child hierarchy. It is not designed to do the same thing with custom
> messages.

I think that is technical problem, broadcasting can be done in some way,
for example by just iterating over all controls and calling perform. I
don't think that is the problem. Though, another design might be better,
such as a control that wants to control if a form can close must
register as a CanClose-Handler. So you would have a
RegisterCanClose/UnregisterCanClose pair, and an internal list. Anyway,
my point is: if a descendant of TForm is implemented there is one way or
another to ask controls for permission to close.

>> Apart from that, you cannot know if other custom components wouldn't
>> need to track the focus state the same way the buttons do (for similar
>> purposes).
>
> I know that none of Borland's standard components do. I have their source
> code, from a half-dozen different versions. If third-party components do,
> that is separate.

I also have the source and look at it, else I couldn't make the
statements I do. This was about sensible design or not, and my argument
was there are legitimate uses and there is no reason similar problems
should not be solved in a similar way. That it is not implemented/used
in other standard controls doesn't change anything whether such a
feature can be useful/is sensible. A control doesn't live in isolation,
therefore it might very well need to know the state of other controls
(not what it needs mainly, but cannot be excluded as bad design per se).
How you implement this is another question. I just try to follow the
patterns of the VCL I can find in hope of changing the least possible of
the underlying infrastructure. But let's not get distracted from the
subject of this thread.

>> CM_SYSFONTCHANGED works
>
> Because that is one of a handful of system-level messages that all visual
> controls must handle, so TControl is specifically coded to allow that
> message (and a few others) to be broadcasted to every component in the
> hierarchy.

Ok, but there are ways to broadcast since I can iterate over all
controls (using recursion - which in fact is also done when broadcasting
CM_SYSFONTCHANGED) of a form and call every WindowProc.
A broadcast function that would work could be something like (pseudo-code):
procedure Broadcast(Control: TControl; Msg: TMessage);
begin
for ChildControl in Control do
begin
ChildControl.Perform(Msg);
Broadcast(ChildControl, Msg);
end;
end;
You don't need the controls to collaborate if you make your own
TForm-descendant.

>> so I can achieve similar things with a custom message of my own.
>
> Only if you manually loop through every component yourself. Again, the VCL
> is *NOT* coded to allow custom messages to be broadcasted deep enough to do
> what you are asking. If your component were placed on another component
> (TPanel, for instance) instead of the TForm directly, it would not receive
> the broadcast if it was sent at the TForm level.

It would work, see explanation above.

>> Either way, it is possible to iterate *somehow* over all
>> controls/components
>
> Of course it is possible. But you have to do it yourself, in a recursive
> loop.

:-) Well, that really is not a problem then, we agree. So why talk about
this at all...

>> the concrete implementation for notifying them all is really not a
>> problem.
>
>
> The issue is that you are asking for a feature that the VCL simply does not
> have, and you are not willing to implement it yourself for lack of
> convenience. You have deadlocked yourself.

A deadlock is usually the reason for a post.
It is more than just convenience, since with a TForm descendant there is
still the problem as described with detecting the changed parent. The
deadlock is the reason I posted, I didn't really need that somebody
rethinks what I did. As said I hoped for a *hack*, since I don't get
one, I'll look for an alternative design - it will require much more
change than I wanted, that's all.

Maël Hörz

unread,
Apr 11, 2008, 9:04:38 AM4/11/08
to
> It seems to me that you are probably handling validation at the wrong time.
> If your component is visual (which you did not comment on when I asked you
> earlier), then perhaps you should be performing validation when the
> component looses input focus, rather than when the form is closed.
Yes I do that, but the form should not close when a validation error
occurs (only when canceled), so unfortunately that doesn't solve the
problem.

>> So I'm still left with the problem how to detect when the parent
>> form changes
>
> To which you already have the answer - there is nothing in the native VCL to
> allow that when your component is not placed on the TForm directly
> (otherwise you could just override SetParent() and be done with it). You
> must implement some kind of manual operation to externally invoke your
> component when needed. Either derive a custom TForm, or call a method of
> the component from the user's own OnCloseQuery handler, or even derive your
> own set of container components (TMyPanel) that can pass your custom
> messages down the hierarchy. There is no other way to do what you are
> asking for. Otherwise, you will just have to abandon the component. It
> won't work the way you want it to, sorry.

Thanks for your thoughts. I understood what you said and only tried to
explain the problems with alternative solutions (i.e. "You have it
backwards"). There is probably a solution but it requires much more
changes than I intended.

Remy Lebeau (TeamB)

unread,
Apr 11, 2008, 2:11:50 PM4/11/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47ff5e12$1...@newsgroups.borland.com...

> Though, another design might be better, such as a control
> that wants to control if a form can close must register as a
> CanClose-Handler. So you would have a
> RegisterCanClose/UnregisterCanClose pair, and an internal list.

That is exactly what I suggested earlier. But you need code that is
external to the component in order to query that list. The list management
itself can be implemented inside your component's unit privately, but you
still need to either derive a new TForm class, or require the user to use
their own OnCloseQuery event handler, in order to invoke the query.

> Anyway, my point is: if a descendant of TForm is implemented
> there is one way or another to ask controls for permission to
> close.

Yes. I never disagreed with that. But you said you did not want to go that
way if you can avoid it. Well, you can't avoid it, since you don't want to
rely on the user to hook up the component to the TForm manually.

> Ok, but there are ways to broadcast since I can iterate over
> all controls (using recursion - which in fact is also done when
> broadcasting CM_SYSFONTCHANGED) of a form and
> call every WindowProc.

Yes, but that is something you have to do manually in your own code for
custom messages. I never disagreed that it could not be done at all.

> A broadcast function that would work could be something like
> (pseudo-code):

You are not taking into account the return value of the TMessage, ie:

procedure MyBroadcast(Control: TControl; Msg: TMessage);
var
I: Integer;
Child: TControl;
begin
Control.WindowProc(Message);
if Message.Result <> 0 then Exit;
if Control is TWinControl then
begin
for I := 0 to TWinControl(Control).ControlCount-1 do
begin
MyBroadcast(TWinControl(Control).Controls[I], Message);
if Message.Result <> 0 then Exit;
end;
end;
end;

> It would work, see explanation above.

Only if you use your own manualy loop, not the VCL's native broadcasting.

> It is more than just convenience, since with a TForm descendant there
> is still the problem as described with detecting the changed parent.

If you implement your own TForm, then the issue becomes a no-brainer to
solve. The custom TForm handles the problem automatically. But you kept
saying that you wanted the component to do everything by itself, and it
simply cannot do that.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 11, 2008, 2:13:47 PM4/11/08
to

"Maël Hörz" <no...@none.invalid> wrote in message
news:47ff6158$1...@newsgroups.borland.com...

> Yes I do that, but the form should not close when a
> validation error occurs (only when canceled), so
> unfortunately that doesn't solve the problem.

If you validate when the control loses focus, before the form is closed,
then you can discard any changes made and there would be no invalid data
present to save when the form is closed.


Gambit


Maël Hörz

unread,
Apr 11, 2008, 3:43:01 PM4/11/08
to
Remy Lebeau (TeamB) schrieb:
Error messages are shown, but shouldn't be shown when Cancel is pressed.
But to explain everything is taking too much time.

Maël Hörz

unread,
Apr 11, 2008, 3:43:03 PM4/11/08
to
>> Anyway, my point is: if a descendant of TForm is implemented
>> there is one way or another to ask controls for permission to
>> close.
>
> Yes. I never disagreed with that. But you said you did not want to go that
> way if you can avoid it. Well, you can't avoid it, since you don't want to
> rely on the user to hook up the component to the TForm manually.
I think we agree here (there is just a meta-level of mutual
misunderstanding)...

>> A broadcast function that would work could be something like
>> (pseudo-code):
>
> You are not taking into account the return value of the TMessage, ie:

Oh, please. This was just a rough outline. Obviously you would have to
take the result into account and process it some way. (It wouldn't hurt
to assume that I am able to work out trivialities like this).

>> It is more than just convenience, since with a TForm descendant there
>> is still the problem as described with detecting the changed parent.
>
> If you implement your own TForm, then the issue becomes a no-brainer to
> solve.

Not exactly. It solves one problem but there are other ones left. Though
I don't want to discuss this further, this leads too far.

Robert Cerny

unread,
May 8, 2008, 5:17:08 AM5/8/08
to
You should turn around your way of thinking.
The form (or frame) needs to do some validation of its objects/states,
right? It's a component, so it can do it on itself, rather than having an
additional component which checks owner's/parent form objects/states.
So, you simply override the CloseQuery method on your form. A user can still
assign own OnClosequery event and class CloseQuery validation is in proper
place.

"Maël Hörz" <no...@none.invalid> wrote in message

news:47fe...@newsgroups.borland.com...

0 new messages