BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Generic Pointers, and fun with OnShowHint

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> comp.lang.pascal.delphi.misc
View previous topic :: View next topic  
Author Message
Paul E. Schoen
Guest





PostPosted: Wed Jan 18, 2006 10:15 pm    Post subject: Generic Pointers, and fun with OnShowHint Reply with quote



(Note: I tried to post this previously, but apparently because of the DFM
attachment it was rejected. Yet I sent another DFM a while ago that posted
OK. Is there another way to attach such a file, or would it be best to put a
zipfile (which I have done) on my website www.Ortmaster.com, as Test1.zip?)

Here is a simple test program that seems to require the use of the generic
Pointer type almost universally rejected by Delphi folk, from my recent
learning experiences. I also added a simple but unusual use for the
OnShowHint event, that may be termed cute or fun. It was inspired by a silly
web app that made you click on a choice that was, well, not what most of us
would want to choose :)

Anyway, the attached project shows a way to handle an array of multiple
types of controls, which is actually what I needed to do. I made it work
with a generic Pointer, which, in a previous posting, prompted kneejerk
rejection, and my failed attempts to make it work more elegantly, the
"Delphi Way". I admit that I am more of a "C" programmer at heart, and I
miss my curly braces, and I have broken several keyboards by "Typing so
Strongly" :)

Thanks for all the advice. I have great respect for the depth of knowledge
provided here, and humbly realize how much I would need to learn to become a
professional programmer. I invite comments on my little program, but
remember that it is mostly a learning tool for me and perhaps a seed for
some other unusual and tricky applications. I would like to see a way to
implement this in the best, or most Delphi-ish way, but I tried various
other ways and this just seemed the best, at least for my low-level (C,asm)
mindset.

Now I will be busy trying to optimize and clean up my several thousand lines
of sometimes ugly code, and I'm sure I will have more urgent questions. I
hope you have enjoyed our discussions as much as I have, and as Arnold might
say, "I'll be back".

--
Paul E. Schoen
www.pstech-inc.com


Back to top
Rob Kennedy
Guest





PostPosted: Wed Jan 18, 2006 11:23 pm    Post subject: Re: Generic Pointers, and fun with OnShowHint Reply with quote



Paul E. Schoen wrote:
Quote:
(Note: I tried to post this previously, but apparently because of the DFM
attachment it was rejected. Yet I sent another DFM a while ago that posted
OK. Is there another way to attach such a file, or would it be best to put a
zipfile (which I have done) on my website www.Ortmaster.com, as Test1.zip?)

Yes, that is the best place to put it. That way, the folks who have read
your message and are still interested can download the large file if
they want to.

Quote:
Here is a simple test program that seems to require the use of the generic
Pointer type almost universally rejected by Delphi folk, from my recent
learning experiences.

It doesn't require Pointer. Every time you read from it, you type-cast
it to TControl. Every time you assign to it, you assign from a variable
of a type that is a subtype of TControl. Thus, the proper declaration
from the CtlPtr field is TControl.

Once you fix that, the most of type-casts aren't even needed anymore.
You type-cast to TEdit and to TLabel before accessing the Visible
property, but Visible is a property introduced in TControl. Since CtlPtr
is declared as type TControl, you can say "CtlPtr.Visible" no matter
what kind of control the variable actually refers to.

Furthermore, your TCtlType enum isn't really necessary, either. You can
ask a control what its type is, and you can also ask whether it is a
subtype of another type. Your loop can be rewritten as this:

for i := 1 to 4 do begin
CtlPtr := CtlArray[i].CtlPtr;
CtlPtr.Visible := not CtlPtr.Visible;
if CtlPtr is TEdit then begin
TEdit(CtlPtr).Text := 'Hello!';
end else if CtlPtr is TLabel then begin
TLabel(CtlPtr).Caption := 'I Say:';
end;
end;

The type-casts before accessing the Caption and Text properties are
still necessary because although both those properties are introduced in
TControl, neither is public. You need to type-cast to a type in which
the property is public.

The OnShow event isn't the best place to initialize your CtlArray
variable. The OnCreate event would be better, or the Loaded method.
OnShow may fire many times during the course of your program, but
OnCreate and Loaded only get called once.

--
Rob

Back to top
Paul E. Schoen
Guest





PostPosted: Thu Jan 19, 2006 6:28 am    Post subject: Re: Generic Pointers, and fun with OnShowHint Reply with quote




"Rob Kennedy" <me3 (AT) privacy (DOT) net> wrote

Quote:
Paul E. Schoen wrote:

Here is a simple test program that seems to require the use of the
generic
Pointer type almost universally rejected by Delphi folk, from my recent
learning experiences.

It doesn't require Pointer. Every time you read from it, you type-cast
it to TControl. Every time you assign to it, you assign from a variable
of a type that is a subtype of TControl. Thus, the proper declaration
from the CtlPtr field is TControl.

OK. It works fine, and is certainly more concise and elegant than my way. I

am almost sure I had tried that in my experiments, and got errors, but that
is not the case now. I was using D4 Standard (at another location) rather
than Pro, but that should not have made any difference. This will be a great
help for cleanup.
Quote:


The OnShow event isn't the best place to initialize your CtlArray
variable. The OnCreate event would be better, or the Loaded method.
OnShow may fire many times during the course of your program, but
OnCreate and Loaded only get called once.

I was afraid that possibly the OnCreate event would fire before all of the

components on the form had been created. If the event happens after the
entire form and all components have been created, then all is well. I was
gunshy because I had used OnCreate in my other (big) application for some
major initialization that sometimes caused access errors, because other
forms had not been completed, and I may have referenced some objects in
them. Maybe it would be better to think of it as OnCreated, if it fires
after all is done. I think Loaded may occur even later, and so may be safer.
Probably not an issue for this little demo, but a complex form may take some
significant time.

Thanks!

Paul



Back to top
Maarten Wiltink
Guest





PostPosted: Thu Jan 19, 2006 8:59 am    Post subject: Re: Generic Pointers, and fun with OnShowHint Reply with quote

"Paul E. Schoen" <pstech (AT) smart (DOT) net> wrote

[...]
Quote:
I was afraid that possibly the OnCreate event would fire before all
of the components on the form had been created.

It may in other components, but TForm is special. Being "the" form class,
it tries to load itself from the .dfm file (resource) during creation.


Quote:
If the event happens after the
entire form and all components have been created, then all is well. I
was gunshy because I had used OnCreate in my other (big) application
for some major initialization that sometimes caused access errors,
because other forms had not been completed, and I may have referenced
some objects in them.

That _is_ a bit problematic. You can change autocreation of forms and
the order in which they are created in the IDE, but the form source
doesn't know about it.

It could be solved by creating all forms except the main form on demand.
This may be a bit over the top for some cases.


Quote:
Maybe it would be better to think of it as OnCreated, if it fires
after all is done.

OnCreate means OnCreated really. It would be named OnCreating otherwise.


Quote:
I think Loaded may occur even later, and so may be safer.

Loaded occurs exactly when the component has been Loaded. Really, it
means what it says, and there is a difference.


Quote:
Probably not an issue for this little demo, but a complex form may
take some significant time.

It's going to take that time anyway. You cannot interact with your
application until all forms have been initialised and the message loop
starts running. Look in the project file: all the CreateForms have to
return before Application.Run (ctrl-click on it) is called.

There are very few things that truly take significant time on modern
computers - although some of them are very common. Like all those awful
animations in the UI.

Groetjes,
Maarten Wiltink



Back to top
alanglloyd@aol.com
Guest





PostPosted: Thu Jan 19, 2006 9:38 am    Post subject: Re: Generic Pointers, and fun with OnShowHint Reply with quote

Quote:
for i := 1 to 4 do begin
CtlPtr := CtlArray[i].CtlPtr;
CtlPtr.Visible := not CtlPtr.Visible;
if CtlPtr is TEdit then begin
TEdit(CtlPtr).Text := 'Hello!';
end else if CtlPtr is TLabel then begin
TLabel(CtlPtr).Caption := 'I Say:';
end;
end;

The type-casts before accessing the Caption and Text properties are
still necessary because although both those properties are introduced in
TControl, neither is public

What is even more interesting is to realise that both TEdit and TLabel
descend from TControl (although both ae protected). Not only so but
they both access the same string (at least they do in D3).

The Delphi access (private, protected, public) is a compiler activity
and in pursuit of that, any descendent of a class can access any
protected properties within the unit it is declaed in. So if you
declare a class as a descendant of TControl, then type-casting to that
descendant enables you to access Caption, or Text by calling Text or
Caption.

So by declaring ...

type
TTextCaption = class(TControl);

.... one can then access ...

TTextCaption(TEdit).Caption; // access Edit1.Text

.... or ...

TTextCaption(TLabel).Text; // access Label1.Caption

.... to access the TEdit.Text, or the TLabel.Caption. Or any descendant
of TControl.

Leading to simple code of ...

if (MyComponent is TEdit) or (MyComponent is TLabel) then
TTextCaption(MyComponent).Caption := 'Some string';

.... where you want to deal only with TEdit or TLabel and either has the
same string.

As a convention where I do this sort of coding I name the type-casting
descendant with the properties I want to access.

Alan Lloyd


Back to top
Hans-Peter Diettrich
Guest





PostPosted: Thu Jan 19, 2006 6:59 pm    Post subject: Re: Generic Pointers, and fun with OnShowHint Reply with quote

Paul E. Schoen schrieb:

Quote:
I was afraid that possibly the OnCreate event would fire before all of the
components on the form had been created. If the event happens after the
entire form and all components have been created, then all is well. I was
gunshy because I had used OnCreate in my other (big) application for some
major initialization that sometimes caused access errors, because other
forms had not been completed, and I may have referenced some objects in
them.

Sometimes a HandleNeeded call will help to force the creation of
specific controls, at the right time.

For auto-created forms you can place an call to a after-construction
procedure in the DRM. For dynamically created forms such a call can be
placed right after the Create.

Apropos after-construction, every class has a class method
AfterConstruction, where you also can put code that shall be executed
when the constructor has finished. But have a look at
TCustomForm.AfterConstruction in online help...

DoDi

Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> comp.lang.pascal.delphi.misc All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.