Board index » delphi » Referencing A VCL Object

Referencing A VCL Object

What's the best way to reference a VCL object within it's event
handler?  Is it better to refer to a hardcoded name or use the Sender
parameter?  For example I usually do this:

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  If CheckBox1.Checked Then
    blah
  Else
    blahblah;
end;

If I rename CheckBox1 and recompile, Delphi stops with an "Undeclared
Identifier" error because CheckBox1 no longer exists.  No big deal, I
change the code to reflect the new name and move on.  However if I had
used this instead:

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  If TCheckBox(Sender).Checked Then
    blah
  Else
    blahblah;
end;

then I could rename the CheckBox to my heart's content without ever
seeing the error.  From that perspective, the second method is better.
 Am I missing anything?  Is there ever a case when Sender is NOT a
TCheckBox which causes an invalid typecast?  What do you experts do?

 

Re:Referencing A VCL Object


"Sonny Grunter" <spoogebucke...@yahoo.com> skrev i melding
news:6d132e5b.0202112316.482f7865@posting.google.com...

Quote
> What's the best way to reference a VCL object within it's event
> handler?  Is it better to refer to a hardcoded name or use the Sender
> parameter?  For example I usually do this:

> procedure TForm1.CheckBox1Click(Sender: TObject);
> begin
>   If CheckBox1.Checked Then
>     blah
>   Else
>     blahblah;
> end;

> If I rename CheckBox1 and recompile, Delphi stops with an "Undeclared
> Identifier" error because CheckBox1 no longer exists.  No big deal, I
> change the code to reflect the new name and move on.  However if I had
> used this instead:

> procedure TForm1.CheckBox1Click(Sender: TObject);
> begin
>   If TCheckBox(Sender).Checked Then
>     blah
>   Else
>     blahblah;
> end;

> then I could rename the CheckBox to my heart's content without ever
> seeing the error.  From that perspective, the second method is better.
>  Am I missing anything?  Is there ever a case when Sender is NOT a
> TCheckBox which causes an invalid typecast?  What do you experts do?

I don't know about the experts, but here's what I do:

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  with Sender as TCheckBox do begin
    If Checked Then
      blah
    Else
      blahblah;
  end;
end;

...er, well, that's what I am *going* to do, at least.

Exception I:  When I'm not 100% certain *what* object is the 'sender', like
with TActions, for example - I have never figured out whether the action
object or the invoking control is the 'sender'. Whan I'm not sure, I do not
write code that way, either.

Exception II: Event handlers may be called as regular methods, too, and when
used that way I often wouldn't rely on the 'sender' parameter. This is not
particulary good design, and most of the time I would move the code from the
event handler into a new method, and let the "manual" call access this one
instead.

There may be some differences between "should's" and "actually do's"
throughout my units...;-)

--
Bj?rge S?ther
bjorge@hahaha_itte.no

Re:Referencing A VCL Object


Quote
"Sonny Grunter" <spoogebucke...@yahoo.com> wrote in message

news:6d132e5b.0202112316.482f7865@posting.google.com...

Quote
> What do you experts do?

I guess they write their code very carefully. :-)

Anyway, I use hardcoded name because I often call events as methods. I use
Sender typecasting when I share event within more controls. It depends a lot
of the situation.

Re:Referencing A VCL Object


On 11 Feb 2002 23:16:22 -0800, Tony wrote:

Quote
>What's the best way to reference a VCL object within it's event
>handler?  Is it better to refer to a hardcoded name or use the Sender
>parameter?  For example I usually do this:

>procedure TForm1.CheckBox1Click(Sender: TObject);
>begin
>  If TCheckBox(Sender).Checked Then
>    blah
>  Else
>    blahblah;
>end;

>then I could rename the CheckBox to my heart's content without ever
>seeing the error.  From that perspective, the second method is better.
> Am I missing anything?  Is there ever a case when Sender is NOT a
>TCheckBox which causes an invalid typecast?  What do you experts do?

Easy just park a button next to and set it's OnClick event to the
checkBox1Click Method. Then your code falls over in a big heap.

Personally the first thing I do is give my components 'proper' names
and then I just use them from then on.
When you use sender it is recomended to use the Is Operator to ensure
sender is of the correct class.

Re:Referencing A VCL Object


Im Artikel <6d132e5b.0202112316.482f7...@posting.google.com>,
spoogebucke...@yahoo.com (Sonny Grunter) schreibt:

Quote
>Is there ever a case when Sender is NOT a
>TCheckBox which causes an invalid typecast?  What do you experts do?

In Delphi you can assign the same event handler to any number and kind of
objects, provided the procedure type is compatible. Then the Sender must be
used in  order to address the appropriate object. Your code then may look like:

if Sender is TCheckBox then ...
else if Sender is TEdit then...

Once you have tested with "is" that the Sender has the correct type, you can
use checked or unchecked type casts, i.e. "Sender as TCheckBox" or
"TCheckBox(Sender)". A "with" clause may be useful here, but it can lead to
confusion when the a field (e.g. Caption) is both a member of the Sender class
and the event handler class (Form). That's why experts tend to not use "with".

DoDi

Re:Referencing A VCL Object


Sonny Grunter <spoogebucke...@yahoo.com> schrieb in im Newsbeitrag:
6d132e5b.0202112316.482f7...@posting.google.com...
[snip]

Quote
> procedure TForm1.CheckBox1Click(Sender: TObject);
> begin
>   If TCheckBox(Sender).Checked Then
>     blah
>   Else
>     blahblah;
> end;

> then I could rename the CheckBox to my heart's content without ever
> seeing the error.  From that perspective, the second method is better.
>  Am I missing anything?  Is there ever a case when Sender is NOT a
> TCheckBox which causes an invalid typecast?

Hi,
you've to know yourself whether you assigned that procedure to
anything else than a checkbox. If you're sure you didn't, there's
no problem referencing the Sender.
If you're not sure, you can insert
if not (Sender is TCheckBox) then Exit;
at the beginning of your procedure, just to make sure there won't
occur any AVs.

HTH
(
--
Florian Haag
ICQ: 114504497
http://fhaag.de.vu/

Re:Referencing A VCL Object


Quote
"Sonny Grunter" <spoogebucke...@yahoo.com> wrote in message
> then I could rename the CheckBox to my heart's content without ever
> seeing the error.  From that perspective, the second method is better.
>  Am I missing anything?  Is there ever a case when Sender is NOT a
> TCheckBox which causes an invalid typecast?  What do you experts do?

I often typecast Sender because not only does it give me the freedom to
change names but it also allows me to easily reuse the event. As a result
whenever I call an event handler directly I always pass it a non-nil
Sender - just one of my rules. I often check the Sender type using as or is,
but not always. Its safer undoubtedly, but the fact is that only a major
programming error would cause an invalid parameter and the great likelihood
is that the method is going to blow up anyways because of an invalid
reference.

That being said, I don't always use Sender. When a behavior is strictly
one-off and the control's name is well chosen I'll often use the named
reference. Principally because the code is usually much more understandable.
I.E.

if LogAllErrors.Checked
then . . .

makes much more sense than

if (Sender as tCheckBox).Checked
then . . .

In addition to readability, using the named reference does force one to stop
and consider each use when a name change is made. Often this can provide one
with insights of the code structure.

Re:Referencing A VCL Object


Quote
Bj?rge S?ther wrote in message ...
>"Sonny Grunter" <spoogebucke...@yahoo.com> skrev i melding
>news:6d132e5b.0202112316.482f7865@posting.google.com...

<Use hardcoded names or Sender in event handlers?>

As several people have observed, this touches on the important
subject of event handler sharing. That makes the answer an
unequivocal "Sender, always". Hardcoded names are for lazy
programmers and quick & dirty programs. Which rules out any
program that _might_ grow to more than ten lines of custom
code - meaning all of them. Sender, always.

Quote
>I don't know about the experts, but here's what I do:

You're being overly modest, Bj?rge.

Quote
>procedure TForm1.CheckBox1Click(Sender: TObject);
>begin
>  with Sender as TCheckBox do begin
>    If Checked Then
>      blah
>    Else
>      blahblah;
>  end;
>end;

>...er, well, that's what I am *going* to do, at least.

>Exception I:  When I'm not 100% certain *what* object is the 'sender',
like
>with TActions, for example - I have never figured out whether the action
>object or the invoking control is the 'sender'. Whan I'm not sure, I do
not
>write code that way, either.

That should be easy to figure out. I also feel strongly that
it should be the control, not the action object.

Quote
>Exception II: Event handlers may be called as regular methods, too, and
when
>used that way I often wouldn't rely on the 'sender' parameter. This is not
>particulary good design, and most of the time I would move the code from
the
>event handler into a new method, and let the "manual" call access this one
>instead.

"Not particularly good design" is an understatement. Event
handlers should (I feel strongly about that, too) be called
through dispatcher functions: TButton.DoClick comes to mind.
Event handlers essentially have an extra Self parameter; if
you want to use it, you can dispatch the event to the right
object; if you don't want to use it, the code should be
abstracted out as in the "manual" call you mention.

Groetjes,
Maarten Wiltink

Re:Referencing A VCL Object


Quote
Bruce Roberts wrote in message ...

[...]
Quote
>That being said, I don't always use Sender. When a behavior is strictly
>one-off and the control's name is well chosen I'll often use the named
>reference. Principally because the code is usually much more

understandable.

Of course, event handlers should have sensible names, too.
If you keep them short enough, that should keep them
understandable even when using Sender.

Groetjes,
Maarten Wiltink

Re:Referencing A VCL Object


"Maarten Wiltink" <maar...@kittensandcats.net> skrev i melding
news:a4c46g$dpn$1@news1.xs4all.nl...

Quote
> Bj?rge S?ther wrote in message ...
> >"Sonny Grunter" <spoogebucke...@yahoo.com> skrev i melding
> >news:6d132e5b.0202112316.482f7865@posting.google.com...
> <Use hardcoded names or Sender in event handlers?>

> As several people have observed, this touches on the important
> subject of event handler sharing. That makes the answer an
> unequivocal "Sender, always". Hardcoded names are for lazy
> programmers and quick & dirty programs. Which rules out any
> program that _might_ grow to more than ten lines of custom
> code - meaning all of them. Sender, always.

There are a few things about writing event handlers that make me feel a
little uncomfortable:
- naming: When more controls share a common event handler, it should *not*
be named after one of the controls, but this is what happens when one
doubleclicks the event in Object Inspector. A little awkward to alter this
name. No big deal, but anyway...
- the untyped 'Sender' parameter (well, as good as) - leads to if's or as'es
that make code both harder to read *and* harder to write (code completion,
you know).
- the fact that most events refer to a physical movement to a mouse or a
key, while we are allways coding for "logical events" like "OnItemSelected",
"OnValueSet", "OnFilterKey", etc... Confusing events like
OnKeyDown/Press/Up, the meaning of "OnClick" ?...this could be done a little
different.

Quote
> >Exception I:  When I'm not 100% certain *what* object is the 'sender',
> like
> >with TActions, for example - I have never figured out whether the action
> >object or the invoking control is the 'sender'. Whan I'm not sure, I do
> not
> >write code that way, either.

> That should be easy to figure out. I also feel strongly that
> it should be the control, not the action object.

Well, in that case the Sender parameter is utterly useless, isn't it ?

Quote
> >Exception II: Event handlers may be called as regular methods, too, and
> when
> >used that way I often wouldn't rely on the 'sender' parameter. This is
not
> >particulary good design, and most of the time I would move the code from
> the
> >event handler into a new method, and let the "manual" call access this
one
> >instead.

> "Not particularly good design" is an understatement. Event
> handlers should (I feel strongly about that, too) be called
> through dispatcher functions: TButton.DoClick comes to mind.
> Event handlers essentially have an extra Self parameter; if
> you want to use it, you can dispatch the event to the right
> object; if you don't want to use it, the code should be
> abstracted out as in the "manual" call you mention.

100% agreed. One should have a banner{*word*154} on ones wall:

  "Don't let RAD temptation lead you into wilderness !"

- it gets me from time to time. "Laziness", it's called...;-)

--
Bj?rge S?ther
bjorge@hahaha_itte.no

Re:Referencing A VCL Object


Quote
Bj?rge S?ther wrote in message ...

[...]

Quote
>There are a few things about writing event handlers that make me feel a
>little uncomfortable:
>- naming: When more controls share a common event handler, it should *not*
>be named after one of the controls, but this is what happens when one
>doubleclicks the event in Object Inspector. A little awkward to alter this
>name. No big deal, but anyway...

"Laziness", it's called.

Quote
>- the untyped 'Sender' parameter (well, as good as) - leads to if's or
as'es
>that make code both harder to read *and* harder to write (code completion,
>you know).

"La...<SLAP>

In truth, not many of my event handlers are shared; the
only ones I can think of right now are OnClick handlers
for (several different) menu items that are possibly also
mirrored in toolbuttons. In general, these don't depend
on the activating object's identity but on its Tag or
something like that. So I extract that into a local variable
at the top of the handler. This takes a few lines and those
may make up almost half of the method, but that's the price
you pay for increased generality. Plus, it saves a complete
event handler - perhaps several. It's to be expected that
the remaining one becomes a bit longer.

Quote
>- the fact that most events refer to a physical movement to a mouse or a
>key, while we are allways coding for "logical events" like
"OnItemSelected",
>"OnValueSet", "OnFilterKey", etc... Confusing events like
>OnKeyDown/Press/Up, the meaning of "OnClick" ?...this could be done a
little
>different.

My later, larger, applications have all had several layers
of events. One layer that translates UI events as they come
in: a shortcut key being pressed; a selection changing; a
menu item being completed. One layer at the application logic
level: an object becoming read-only; a selection changing;
a new object being loaded. One layer that matches the UI to
the new state of the application: a toolbutton depressing
itself; the contents pane updating; the titlebar updating.

The events that come in from the UI dispatch themselves to
the application logic events; the application logic events
dispatch themselves back to the UI. It's quite a lot of
bookkeeping, but it suits me well.

I developed this system in response to my inability to keep
the menus in sync with the state of the application - disabling
the File/Close menu item unless an object is actually loaded,
and such. I tried to do it with the OnPopup event, and found
that it didn't work. The shortcut keys linked to the menu items
were available when they shouldn't be, but they don't trigger
popup events. So I came up with what I described above, and I
found that not only did it keep menu items, shortcut keys, and
tool buttons in perfect sync with the _current_ application
state, but it also stopped duplicate repaints and other doubtful
behaviour.

Quote
>> >Exception I:  When I'm not 100% certain *what* object is the 'sender',
>> like
>> >with TActions, for example - I have never figured out whether the
action
>> >object or the invoking control is the 'sender'. Whan I'm not sure, I do
>> not
>> >write code that way, either.

>> That should be easy to figure out. I also feel strongly that
>> it should be the control, not the action object.

>Well, in that case the Sender parameter is utterly useless, isn't it ?

Hmm... You have a point. It's an abstraction of several UI
elements, and as such _it_ should be the Sender - then you
can trace back to _all_ the widgets that might have triggered
it... and update their state to match the changed application
state.

I've regarded action objects as a somewhat inferior way to
update the UI in response to UI events. The scheme I described
above separates the layers rather thoroughly; action objects
are more direct and less abstract. They are closely matched
to the UI, while I saw the effect I was trying to obtain at a
different conceptual level. I've never considered the option
of using them in a more abstract way. (Actually, since I "only"
have D3, I've never used them at all. But that doesn't stop
me from having an opinion about them.)

Groetjes,
Maarten Wiltink

Re:Referencing A VCL Object


"Maarten Wiltink" <maar...@kittensandcats.net> skrev i melding
news:a4ekhi$g8c$1@news1.xs4all.nl...

Quote
> Bj?rge S?ther wrote in message ...
> [...]
> >There are a few things about writing event handlers that make me feel a
> >little uncomfortable:

> >- naming: When more controls share a common event handler, it should
*not*
> >be named after one of the controls, but this is what happens when one
> >doubleclicks the event in Object Inspector. A little awkward to alter
this
> >name. No big deal, but anyway...

> "Laziness", it's called.

> >- the untyped 'Sender' parameter (well, as good as) - leads to if's or
> as'es
> >that make code both harder to read *and* harder to write (code
completion,
> >you know).

> "La...<SLAP>

Yes, I agree, but I object this: the doubleclcicking of event handlers in
components is one of the basic concepts in "RAD Delphi". As a newbie you use
all the RAD features, and later you'll have to dicipline yourself into *not*
doing it ! The "RAD trap" !

- Show quoted text -

Quote
> My later, larger, applications have all had several layers
> of events. One layer that translates UI events as they come
> in: a shortcut key being pressed; a selection changing; a
> menu item being completed. One layer at the application logic
> level: an object becoming read-only; a selection changing;
> a new object being loaded. One layer that matches the UI to
> the new state of the application: a toolbutton depressing
> itself; the contents pane updating; the titlebar updating.

> The events that come in from the UI dispatch themselves to
> the application logic events; the application logic events
> dispatch themselves back to the UI. It's quite a lot of
> bookkeeping, but it suits me well.

> I developed this system in response to my inability to keep
> the menus in sync with the state of the application - disabling
> the File/Close menu item unless an object is actually loaded,
> and such. I tried to do it with the OnPopup event, and found
> that it didn't work. The shortcut keys linked to the menu items
> were available when they shouldn't be, but they don't trigger
> popup events. So I came up with what I described above, and I
> found that not only did it keep menu items, shortcut keys, and
> tool buttons in perfect sync with the _current_ application
> state, but it also stopped duplicate repaints and other doubtful
> behaviour.

This seems mature. A kind of non-visible "object" of some kind that controls
trig and read state info from. Coding the form's event handlers should
ideally be reduced to accessing this object in one-liners. I have this
application that very much rely on non-visible objects for state
information, and now I want to restructure the whole application to be able
to serve both as a traditional Windows client *and* a web server app. I have
planned for replacing all interaction controls <> underlying object with a
few methods / properties. Exception is drawing in  complex controls, where
different descendants of a common base class either knows how to interact
with forms, or they provide HTML output. The necessary rebuild solves a lot
of other issues, as well; the ones you have solved through creating a
"logical layer" that maps interaction man <> code in a more model-true way.

- Show quoted text -

Quote
> >> >Exception I:  When I'm not 100% certain *what* object is the 'sender',
> >> like
> >> >with TActions, for example - I have never figured out whether the
> action
> >> >object or the invoking control is the 'sender'. Whan I'm not sure, I
do
> >> not
> >> >write code that way, either.

> >> That should be easy to figure out. I also feel strongly that
> >> it should be the control, not the action object.

> >Well, in that case the Sender parameter is utterly useless, isn't it ?

> Hmm... You have a point. It's an abstraction of several UI
> elements, and as such _it_ should be the Sender - then you
> can trace back to _all_ the widgets that might have triggered
> it... and update their state to match the changed application
> state.

> I've regarded action objects as a somewhat inferior way to
> update the UI in response to UI events. The scheme I described
> above separates the layers rather thoroughly; action objects
> are more direct and less abstract. They are closely matched
> to the UI, while I saw the effect I was trying to obtain at a
> different conceptual level. I've never considered the option
> of using them in a more abstract way. (Actually, since I "only"
> have D3, I've never used them at all. But that doesn't stop
> me from having an opinion about them.)

When I first opened D4 and saw TActionList, I cried "Yes ! Yes !", but later
versions have given me nothing more of this...;-(

I believe the TActionList was a small step in the right direction: Define
your interesting "topics" and centralize code around them rather than in
zillions of OnMouse/OnKey...Button1.Enabled:=... Mapping of controls to
these topics are more or less taken care of by TAction classes. It is a
*small* step, because it is, as you say, mainly designed for GUI controls. A
more generic model dividing an application into 'actions',
'topics'/'states', 'modules', etc., is a natural evolution, IMHO. A gizmo
like a global TActionManager, giving you an easy way of creating complete
lists of keyboard shortcuts for your entire application, for a start.

--
Bj?rge S?ther
bjorge@hahaha_itte.no

Re:Referencing A VCL Object


Quote
Bj?rge S?ther wrote in message

<_hBa8.5539$HL2.119...@news2.ulv.nextra.no>...
[...]

Quote
>Yes, I agree, but I object this: the doubleclcicking of event handlers in
>components is one of the basic concepts in "RAD Delphi". As a newbie you
use
>all the RAD features, and later you'll have to dicipline yourself into
*not*
>doing it ! The "RAD trap" !

I'm afraid you're right. This is just one instance of a very
common problem: that software should really adapt to the
experience level of its user. It's a _very_ hard problem in
general.

In this case, I see the root cause as being that event handler
methods should be named after something on a different level
than the IDE has access to. The IDE knows about widgets and
events, not about what you're trying to _do_.

<three layers of events: UI -> application-logic -> UI>

Quote
>This seems mature.

Well, it took a few weeks before it had reached its final form
and I understood what had happened. I like to think it deserves
to be called mature.

Quote
>                      ...restructure the whole application to be able
>to serve both as a traditional Windows client *and* a web server app.

I you hadn't said it so drily, I would not have believed it to
be possible at all.

Quote
>                                                                ...I have
>planned for replacing all interaction controls <> underlying object with a
>few methods / properties. Exception is drawing in  complex controls, where
>different descendants of a common base class either knows how to interact
>with forms, or they provide HTML output. The necessary rebuild solves a
lot
>of other issues, as well; the ones you have solved through creating a
>"logical layer" that maps interaction man <> code in a more model-true

way.

Thanks for the compliment. Is this the famous "peer recognition"?

I can _almost_ see how that solves the traditional impedance
mismatch between the Windows GUI and the Web model. It's about
channelling events back and forth, with state kept in the
application where I still see everything that's in a browser
as stateless HTML pages.

It's good to know I still have things to look forward to, new
things to learn. What web server do you use? Is the application
multi-user by design? How do you identify a session?

Groetjes,
Maarten Wiltink

Re:Referencing A VCL Object


"Maarten Wiltink" <maar...@kittensandcats.net> skrev i melding
news:a4o56n$dhn$1@news1.xs4all.nl...

Quote
> Bj?rge S?ther wrote in message
> <_hBa8.5539$HL2.119...@news2.ulv.nextra.no>...
> [...]
> >Yes, I agree, but I object this: the doubleclcicking of event handlers in
> >components is one of the basic concepts in "RAD Delphi". As a newbie you
> use
> >all the RAD features, and later you'll have to dicipline yourself into
> *not*
> >doing it ! The "RAD trap" !

> I'm afraid you're right. This is just one instance of a very
> common problem: that software should really adapt to the
> experience level of its user. It's a _very_ hard problem in
> general.

> In this case, I see the root cause as being that event handler
> methods should be named after something on a different level
> than the IDE has access to. The IDE knows about widgets and
> events, not about what you're trying to _do_.

> <three layers of events: UI -> application-logic -> UI>

> >This seems mature.

> Well, it took a few weeks before it had reached its final form
> and I understood what had happened. I like to think it deserves
> to be called mature.

Do you solve this by using object instances in parallell to e.g. form
objects in a 1 - to - 1 relationship, or what ?

Quote
> >                      ...restructure the whole application to be able
> >to serve both as a traditional Windows client *and* a web server app.

> I you hadn't said it so drily, I would not have believed it to
> be possible at all.

Well, it remains to see if it's a good solution. The application itself has
a quite simple GUI, with only 5 different screens. The complexity lies
within calculation of what to display in these forms for a certain
combination of selected parameters. The application needs to be split in two
also at a lower level, to allow for multiple sessions to share a common
system data structure. But again, this is a topic also for standard Windows
applications: How to split static systemdata from instance-specific data,
e.g. to allow for opening a second form showing something completely
different without having to duplicate more data than necessary. It is all
about where stateful data is located and where you put stateless data.
If the two "lower" layers, stateless systemdata and instance-specific,
stateful data is written without being GUI-specific, it should be fairly
easy to replace the Windows GUI with an HTTP-producer.

Quote
> >                                                                ...I have
> >planned for replacing all interaction controls <> underlying object with
a
> >few methods / properties. Exception is drawing in  complex controls,
where
> >different descendants of a common base class either knows how to interact
> >with forms, or they provide HTML output. The necessary rebuild solves a
> lot
> >of other issues, as well; the ones you have solved through creating a
> >"logical layer" that maps interaction man <> code in a more model-true
> way.

> Thanks for the compliment. Is this the famous "peer recognition"?

Yes !

Quote
> I can _almost_ see how that solves the traditional impedance
> mismatch between the Windows GUI and the Web model. It's about
> channelling events back and forth, with state kept in the
> application where I still see everything that's in a browser
> as stateless HTML pages.

The main problem is, it seems, that if one does not utilize JavaScript or
Java/ActiveX, the flow of a Web application is very different from a Windows
client:

Typical Windows Client:
1) Open a form
2) Invoke Command through a control
3) Reflect changes by repainting some window(s)

Web app:
1) Return HTTP document (form) upon request
2) Invoke Command through a control
3) return to 1)

These two models need to be "mapped" to a common underlying structure. I
have thought that the common point will be a dispatching procedure,
providing command and parameters. There is also a difference in program
flow, in that a web request needs to return the resulting HTTP immediately,
whereas in Windows, you typically respond to messages.

Example (Web-app):

(sample url:
http://www.itte.no/bin/WebApp.exe?Session=23443321?Command=OpenDetail...
s=CustID:201122)

function Invoke(const Command: string; Params: string): string; // returns
HTTP
var
  StateFulObj: THTTPStatefulObj;
begin
  StateFulObj:=FindSessionInstance(Params); // extracts "SessionID" param
  if Assigned(StateFulObj) then begin
    StatefulObj.Invoke(Command, Params); // Extracts "Command" & "Params",
executes command
    result:=StatefulObj.HTTP; // In win-app, the result is "returned"
through a call to the event handler
  end
  else
    result:=InvalidSessionOutput(Command, Params);
end;

Example (Windows-app):

(sample: Invoke('OpenDetails', GetCustId);)

proceudre Invoke(Sender: TObject; const Command: string; Params: string);
var
  StateFulObj: TWinStatefulObj;
begin
  StateFulObj:=Sender as TWinStatefulObj;
  if Assigned(StateFulObj) then
    StatefulObj.Invoke(Command, Params) // Extracts "Command" & "Params",
executes command
  else
    raise Exception.Create('Invalid "Sender" parameter in function
Invoke;');
end;

...now, the latter doesn't really need to return anything, as messages will
be sent back to controls of the calling form.

Quote
> It's good to know I still have things to look forward to, new
> things to learn. What web server do you use? Is the application
> multi-user by design? How do you identify a session?

Well, the make of the Web-server doesn't matter that much, as long as you
don't use MS-specific techniques. I don't know, really, wherther I'll have
to use the ISAPI interface or whatever. If so, I understand that the .dll is
loaded / unloaded upon every call, so I need to make this one as small as
possible, dispatching calls to a steadily running server application. Maybe
a complete Web-Server application is the best ? Frankly, I have not been
doing this before...;-)

My application is multi-user by design, only that it needs a quite
complicated system database to work, and loading this one typically is a
quite expensive operation. I believe that a Server application should only
do this once, and let all sessions share the system data. It is a
"parameterized SQL-applications", where no fields are defined at designtime.
The main task of the client is to use system data for generating SQL calls
to pass to the server.

If you're interested, I'll send you a test URL the day something works ;-)

--
Bj?rge S?ther
bjorge@hahaha_itte.no

Re:Referencing A VCL Object


Quote
Bj?rge S?ther wrote in message ...
>"Maarten Wiltink" <maar...@kittensandcats.net> skrev i melding
>news:a4o56n$dhn$1@news1.xs4all.nl...
[...]
>> <three layers of events: UI -> application-logic -> UI>

>> >This seems mature.

>> Well, it took a few weeks before it had reached its final form
>> and I understood what had happened. I like to think it deserves
>> to be called mature.

>Do you solve this by using object instances in parallell to e.g. form
>objects in a 1 - to - 1 relationship, or what ?

No, I simply added all those events to the form. It's a *big*
unit. About 2500 lines - that's big for a form of mine. And
much of the interesting stuff happens in plug-ins, so it really
is mostly administration of the UI.

Excerpt from the code:

    FOnTouchGrammar          : TNotifyEvent;
    FOnTouchAppData          : TNotifyEvent;
    FOnTouchDirty            : TNotifyEvent;
    FOnTouchFileName         : TNotifyEvent;
    FOnTouchReadOnly         : TNotifyEvent;
    FOnTouchSelection        : TNotifyEvent;
(These are the application-level events.)

    FOnTouchTitleBar         : TNotifyEvent;
    FOnTouchToolBar          : TNotifyEvent;
    FOnTouchNavPane          : TNotifyEvent;
    FOnTouchDebugPane        : TNotifyEvent;
    FOnTouchContPane         : TNotifyEvent;
    FOnTouchEditPane         : TNotifyEvent;
    FOnTouchStatusBar        : TNotifyEvent;
(These are the UI synchronisation events, excluding the menu.)

    FOnAffectFileMenu        : TNotifyEvent;
    FOnAffectFileNew         : TNotifyEvent;
    FOnAffectFileOpen        : TNotifyEvent;
    FOnAffectFileOpenAppend  : TNotifyEvent;
    FOnAffectFileOpenGrammar : TNotifyEvent;
    FOnAffectFileSep0        : TNotifyEvent;
    FOnAffectFileSave        : TNotifyEvent;
    FOnAffectFileSaveAs      : TNotifyEvent;
    FOnAffectFileSep1        : TNotifyEvent;
    FOnAffectFileSep2        : TNotifyEvent;
    FOnAffectFileAdoptGrammar: TNotifyEvent;
    FOnAffectFileSep3        : TNotifyEvent;
    FOnAffectFileClose       : TNotifyEvent;
    FOnAffectFileExit        : TNotifyEvent;
(That's the file menu; the other ones are smaller. Plug-ins
add menu-items at run-time.)

These are the field variables; _all_ these properties also
have property definitions, event dispatchers, and event
handlers. Then there's the input UI event handlers (the
ones you'd see in the Object Inspector). The source does
tend to get a bit repetetive.

As an example: choosing File/Save As from the file menu
will trigger the FileSaveAs event handler, that'll call
a method on the editor object (which is assigned, or that
menu item would have been disabled) to save it under a
different name, that'll trigger an OnRename event in the
editor object, that triggers an OnTouchFileName event in
the form, that triggers OnTouchTitleBar. Once I got the
causalities straightened out, the titlebar was refreshed
exactly once when the name of the loaded object changed.

Groetjes,
Maarten Wiltink

Go to page: [1] [2]

Other Threads