Link to home
Start Free TrialLog in
Avatar of GiantMatrix
GiantMatrix

asked on

Delphi Types Question

Hi All,

I am having a problem understanding the Type declared below and what is its benefit / usage...so can someone please help me by explaining it to me?

As far as I understand a type like ( TMyNewType = (rcKeys, rcValues, rcData); ) is a set of enumeration where I can define a new Type to be used later in the unit.  But I can't understand function/ procedure types...what they are ? what is their benefit/ usage? What are their usage conditions?

===============================================
unit RegSearch;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Forms;

type
  TRegOnProgress = procedure(const RegCurrentPath: string; const Keys,
Values, DataValues: int64) of object;

TRegSearch = class(TComponent)
.
.
.
===============================================

And in Unit1 where i use the unit RegSearch

===============================================

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Buttons, StdCtrls, Dialogs, ExtCtrls, Menus, ComCtrls, RegSearch;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure RegOnProgress(const RegCurrentPath: string; const Keys,
Values, DataValues: int64);
.
.
.
procedure TForm1.RegOnProgress(const RegCurrentPath: string; const Keys,
Values, DataValues: int64);
begin

end;
//------------------------------------------------------------------------------

===============================================
Thanks in advance
ASKER CERTIFIED SOLUTION
Avatar of Jacco
Jacco
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You can also pass a procedure as a parameter using this technique.

Say you have the procedures in place like I mentioned above: RegProc1 and RegProc2. You can now make another method that takes a procedure as a param:

procedure TForm1.DoStuff(aProc: TRegOnProgress);
begin
  aProc('RegPath', 0, 3, 5);
end;

This calls the procedure you pass.

Have fun

Regards Jacco
Avatar of GiantMatrix
GiantMatrix

ASKER

Jacco,

Thanks a lot for your reply and help...please don't get upset but I am sorry to say I didn't understand your reply...so can you please elaborate more or give me another simple example?

Thanks in advance
It is the same as a TNotifyEvent which is actually defined as:

type
  TNotifyEvent = procedure(Sender: TObject) of object;

If you have a form with some methods like this:

procedure TForm1.Button1Click(Sender: TObject);

and

procedure TForm1.Button2Click(Sender: TObject);

They are both compatible with the class TNotifyEvent.

A button has a OnClick event property which can be assigned any procedure that has the same signature as the procedural type definition of TNotifyEvent. So both Button1Click and Button2Click can be assigned to any TButton.OnClick event property.

Now TNotifyEvent is already predefined but Delphi lets you also define types yourself like the one you mention above TRegOnProgress where you can specify a different parameter signature.

Regards Jacco
Jacco,

But TNotifyEvent is a type that belong to a class, but the types defined in my example does not belong to any class they simply belong to the RegSearch unit.

So I can't see any relation between them

Jacco, just not to waste your time do you have to know any refrence I can read to learn more about those Types so that I can have a bit of a background?

thanks in advance
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
When you drop TRegSearch component on the form look on the ObjectInspector and switch its tab to Events you will probably see an RegOnProgress property. When you double click it Delphi will create an empty procedure TForm1.RegOnProgress in the published section of the form for you.

The event property RegOnProgress of the TRegSearch component is now linked to this method, just like an Button1Click would be linked to the Button1.OnClick event.

See it as a callback mechanism for the TRegSearch component. The TRegSearch component is now able to call the method of your form!

Delphi uses the type information to see what published methods match the signature so that the dropdown box on the object inspector shows the correct methods when you drop it down. I.e. only method complying with the TNotifyEvent signature will show when you use the dropdown box on a Button.OnClick and only method that have the signature of TRegOnProgress will show up when you use it on the RegOnProgress property of the TRegSearch component.

A good learning source is the VCL code. It comes with Delphi professional. A way of making yourself familiar with the uses it trying to make a component yourself.

Regards Jacco
ZhaawZ,

Wow...what an explanation...thank you so much for your "detailed" reply :)

Now as of this part
>> TMyNewType = (rcKeys, rcValues, rcData);

Your example simply made it more and more clear in my mind, but just one last question...can you please explain to me what is meant by

TTestTypeSet = set of TTestType;

I mean what is its usage and how it makes programmers life easier?

Thanks in advance.
Well.. have you worked with font styles? That's the first thing that comes in my mind, hehe

Few examples:

[source]
// empty set - remove all values
Edit1.Font.Style := [];
// set only 1 value
Edit1.Font.Style := [fsBold];
// set 2 values
Edit1.Font.Style := [fsBold, fsItalic];
// remove from previous values 1 value and add 1 value
Edit1.Font.Style := Edit1.Font.Style - [fsBold] + [fsStrikeOut];
// check if value is in set
if fsItalic in Edit1.Font.Style then ShowMessage('is italic') else ShowMessage('isn`t italic');
[/source]

Edit1.Font.Style is a set of (fsBold, fsItalic, fsUnderline, fsStrikeOut)

[source]
type
  TFontStyle = (fsBold, fsItalic, fsUnderline, fsStrikeOut);
  TFontStyles = set of TFontStyle;
[/source]

So it can contain one or more of those values. Same thing with your custom sets.
About "making programmer's life easier" - you may do all this stuff also with plain integer values and "and / or / xor". Some people think that using such "set of TType" is easier and more undestandably. I like using integers and "and / or / xor" instead ;)
Hi ZhaawZ,

No this part I do understand, so I apologize if my question wasn't clear.

My question is in the following code block

[source]
type
  TTestType = (valA, valB, valC, valD, valE);
  TTestTypeSet = set of TTestType;
[/source]

What is meant by

TTestTypeSet = set of TTestType;


Is it something like for example when you make a Vector/ Pair in C++ where each vector cell represents a structure or array?

Or in other words TTestTypeSet represent a one dimensional array where each cell in this array represent a new TTestType ?

Thanks in advance
Do not know about C++...

TTestType is not an array. It's a single value. You can't assigne multiple values to it. You can assign valA OR valB OR valC etc, but you can't assign several values.
That's why sets are - to be able to add or remove value.

TTestTypeSet is a "set of values" (or "array of bits" if handling it in low level) in which each "cell" (bit) represents presence of one of values of type TTestType.

var x : TTestTypeSet;
x := [valA, valC, valE];  <-- this set shows that it has valA, valC and valE in it, but does not have valB and valD
so, for

type
  TTestType = (valA, valB, valC, valD, valE);

you can have (only one value at a time)

var
  atestType:TTestType;
begin
  atestType:=valA;
//or
  atestType:=valB;
//or
  atestType:=valC;

and for

type
  TTestTypeSet = set of TTestType;

var
  aTestTypeSet:TTestTypeSet;
begin
  aTestTypeSet:=[valA];
//or
  aTestTypeSet:=[valA, valB];
//or
  aTestTypeSet:=[valA, valB, valC];
//etc...

that's why is a "SET"
BlackTigerX, ZhaawZ,

Thank you all for your help and support concerning Sets, now I fully understand Sets :)
Hi All,

Just to make sure I understood everything correct:

A** In any unit if I wrote under "Type" and function / procedure in either of the following formats:
type
  TEvent1 = function(const param1, param1: string): boolean;
  TEvent2 = procedure(const param1, param1: string) of object;

Then I am defining a new event for the class this block of code....correct?


B** ALL the object events must be declared just in the "Type" section and before class definition...Example:

type
  TEvent1 = function(const param1, param1: string): boolean;
  TEvent2 = procedure(const param1, param1: string) of object;

TRegSearch = class(TComponent)
  private

...correct?
Here I have another question…what is the difference between events ending up with "of Object" and events not ending with "of Objects"?


C** Event definitions can either end by "of object" or not...correct?


D** Events can only be declared in any component / class, but we can not write code in the function/ procedure representing the event…correct?

Thanks in advance
A and B are correct. You can also have funtion of object types:

TEvent1 = function(const param1, param1: string): boolean of object;

These are not used very often but occasionally I have found a use for it. You have to take special care that the implementor initialised the result he wants to pass back since you can't do that for him. That is why it is more common to use a var parameter in stead.

TEvent1 = procedure(const param1, param1: string; var Result: Boolean) of object;

"of objects" is not used. Where have you seen this?

C If "of object" is added the event must be implemented with a method of a class instance. If you define a procedural type without "of object". The Implementation is then just plain procedures or functions. This is mostly used to pass procedures (not method) as parameters or store references to procedures (not methods).

D When I understand you correctly you are correct. The implementation of the event is omitted to make the component more flexible and generic. For example a button that can do only one thing (pop up a specific screen) is not very usefull since you would need another button class for anything youwould want to do when the user clicks a button.

Regards Jacco

Jacco,

>>These are not used very often but occasionally I have found a use for it. You have to take special care that the >>implementer initialized the result he wants to pass back since you can't do that for him. That is why it is more >>common to use a var parameter in stead.
>>TEvent1 = procedure(const param1, param1: string; var Result: Boolean) of object;

I am sorry I couldn't understand this part 100% so can you please elaborate.

>>"of objects" is not used. Where have you seen this?
Here is a simple example without "of object":
type
  TEvent1 = function(const param1, param1: string): boolean;

>>If you define a procedural type without "of object". The Implementation is then just plain procedures or functions. >>This is mostly used to pass procedures (not method) as parameters or store references to procedures (not >>methods).

Can you please elaborate this part by any example?

D. Yes you understood me correctly, what I meant was that the events defined for any component/ class won't have a corresponding in the implementation.

Thanks in advance
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial