Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Creating an onChange event for a class

Posted on 2002-04-10
14
446 Views
Last Modified: 2013-11-23
I have the following class declared:

type dbEntry = class(TObject)
public
  Problem : string;
  Chapter : string;
  Section : string;
  PointValue : string;
  Time : string;
 
  procedure splitInfo(source : TObject);
  procedure loadLargeData(source : TObject);
  procedure clearLargeData;

private

   endPoint,startPoint : integer;
   input : string;

end;

I want to be able to have an onChange event for this class, so that whenever any of the values stored in the variables changes, a procedure can be called.  The idea, is that whenever the user enters a new value into one of them, I want the new values posted to a corresponding dbTable immediately. Instead of doing this manually at every point in the code where the user might change one of the values, I would like an onChange event for the class that takes care of it.

any thoughts?

chmod101
0
Comment
Question by:chmod101
  • 6
  • 4
  • 4
14 Comments
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6931945
< add this code to Private section >

FOnChanged        : TNotifyEvent;

< add this code to public section >

property OnChanged : TNotifyEvent read FOnChanged write FOnChanged;

< Now u have an Event >


< add this code to ur set Value Procedures ?

if Assigned(FOnChanged) then FOnChanged(Self);

< But at first u should make some set value procedures like this  >

< add this code to ur private section >
< we suppose it is an Integer Data >

 FMyData : Integer;
 procedure SetMyData(Val : Integer);

< add this code at public section

 property MyData : Integer read FMyData write SetMyData ;


< now u have an OnChange Event >
but
u can make ur Event Type : if u need more than ( Sender : TObject ) bye a little code . TNotifyEvent and other events are just some "Procedure" types. see Delphi help.

also it is better for u to make this Event as Published not pubil section. although at public section you shuld refer a Function to that TNotifyEvent.

I am ready to more comments;
Hamed


0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6931959
about ur own Event type , see that TNotifyEvent has the follow type :

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

infact an Event is a <Procedure() of object;

therfore u can make a new Event type :

Type
TMyEvent = procedure ( Sender : TObject; MyNewData : Integer ) of Object;

therefore at ur setMyData() procedure you should do it :

if Assigned(FOnChanged) then FOnChanged(Self,MyNewData);
                                         |       |
                                         |       |
                                        Sender   Data

Hamed ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6933135
hi hamed,
how are you?
(sorry to be off topic)
meikl ;-)
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6934262
hi Meikl ;-)

very nice to see u again :-) how are you and your family , specialy the nice Children :-) ?

I was graduated last month. and taked the MS enterance exam last month too. now I am working in a Team at a Automation Co. , we are designing a Distributed PC Based Automation System - Like my BS univ. project - but unfortunately by VC++ not Delphi :-( They did not Accpect Delphi! . in general I am still alive ;-)

what are u doing ? I am sure u are completely successful in ur work and ur life .

Hamed;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6934743
hamed,
i write a email to you,
is the email-adress at your profile correct?
meikl ;-)

(sorry to be off topic)
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6934829
Meikl,

Yes It is Correct , also h_mohsenian@yahoo.com

Thanks for your favours.
Hamed

(sorry to be off topic)
0
 

Author Comment

by:chmod101
ID: 6942063
Well, Harmed, thank you for the help, but that wasn't very clear.  Could you include a small example, without any comments, on where exactly to place this stuff?  I have never done anything like this, and I dont really understand how to use the setValue procedure.

Could you post a brief example of a class with an onChange event included?

Thanks for your help,
chmod101
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6942108
hamed, i'm a lazy mail-writer, i know :-)
but mail is in work ;-)
0
 
LVL 1

Accepted Solution

by:
h_mohsenian earned 30 total points
ID: 6942800
hi chmod101 ,
Sorry, Maybe u r right ;-)

now : I wana suggest u to make ur New Class at the Base of <TComponent> not <TObject> therefore u will see ur Result easily and .... :

1. Go to < Component Menu >
2. Select < New Component >
3. Choose ( or write ) <TComponent> at <Ancestor Field>
4. Write <TdbEntry> at <Class Name> Filed
5. accept other defualt Values and Click on <OK> buttom
6. Now u have a Unit page
7. write this code at that page :
// ------------------- Starts Unit dbEntry ---------
unit dbEntry;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TMyEvent = procedure ( Sender : TObject; MyNewData : Integer ) of Object;

  TdbEntry = class(TComponent)
  private
    FMyData : Integer;
    FOnChanged : TMyEvent;
    procedure SetMyData(Value : Integer);
    { Private declarations }
  protected
    { Protected declarations }
  public
    property MyData : Integer read FMyData write SetMyData ;
    { Public declarations }
  published
    property OnChanged : TMyEvent read FOnChanged write FOnChanged;
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Hamed', [TdbEntry]);
end;

procedure TdbEntry.SetMyData(Value : Integer);
begin
  FMyData := Value;
  if Assigned(FOnChanged) then FOnChanged(Self,Value);
end;

end.

// ------------------- Ends Unit dbEntry ---------

8. Save this File .Now u should Install this New Component
9. Go again to <Component Menu> and Click on <Install Component >
10. use all defualt Settings and Install ur New Component.
11. save all opended Files and after that Close all of them.
12. Open a New Application
13. u will see ur New Component at 'Hamed' Tab of Component List ( up and Right at Delphi Page )
14. select it and Drop it on ur Form
15. go to the Event Tab of this new Object ( at Object Inspector )
16. u will see an OnChanged Event
17. Use it and test it in every Case that u want but there is an Example for this Test :


// -------------------- Example Code Starts --------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  dbEntry, StdCtrls;

type
  TForm1 = class(TForm)
    dbEntry1: TdbEntry;
    Button1: TButton;
    procedure dbEntry1Changed(Sender: TObject; MyNewData: Integer);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.dbEntry1Changed(Sender: TObject; MyNewData: Integer);
begin
  showmessage('New Value is' + IntToStr(MyNewData));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  dbEntry1.MyData := 10;
end;

end.

// -------------------- Example Code Ends --------------------

BUTTTTTTT, if u want TObject as ur Base class I guess u can not Use Published and Object Inspector ....... therefor u shoul make that Event Property at <Public> mode , instead of <published> mode. and u shoul refer a Procedure in Type of  TMyEvent to that Event of Ur Object BY CODE ( not easy like Object Inpector ). But as a general suggestion I recommend u to us TComponent . It is easy to use. ;-)

also Mikle can Help us to for more comments ;-)

I hope it will be help full for u ;-)
Hamed






Hi Meikl ,

:-)) Take It easy . :-)) Do you Remember my Antient email About IRAN!! ;-) I am waiting for ur emails every times. Thanks for ur favours. u are a good friend and always care ur Little Student ( Hamed ) .

Hamed ;-)  
0
 

Author Comment

by:chmod101
ID: 6945105
Alright,

Thanks for the clarification, but I still have a problem. The type of data you used was an integer.  I need to use a class. I have about 30 different fields of data that need to be grouped together, and anytime anyone of them gets changed, I want to call the onChange event.  My thought was to create a class,dbData, that groups all of these, and then insert dbData where you have integer. So, FMyData becomes of dbData type, and so on. It worked, and the unit compiled and was added succesfully, however, it wont work.

It doesnt allocated memory for the class, so when you try to assign a value to one of its members, it causes an access violation.  So, how do I do this without having to write an onChange event for all 30 db Fields?

chmod101
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6945226
you should raise the points a bit,
because you're about to expand
the context of your question

normally you code for each attribute
a set procedure and a get procedure
to have properties (if you want to publish it)


you could call in each set procedure a procedure
maybe called changed, which then check and calls the assigned onChange procedure

hameds sample is for one attribut,
you have to expand it to the other attributs
of your class

like

procedure TdbEntry.SetProblem(Value : String);
begin
 if value <> Problem then
 begin
   Problem := Value;
   Changed;
 end;  
end;


procedure TdbEntry.SetChapter(Value : String);
begin
 if value <> Chapter  then
 begin
   Chapter  := Value;
   Changed;
 end;  
end;

// and so on

procedure TdbEntry.Changed;
begin
  if Assigned(FOnChanged) then
    FOnChanged(Self);
end;

meikl ;-)


0
 

Author Comment

by:chmod101
ID: 6945480
Thanks for the help,

If I have any more questions, I will post them.

chmod101
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6945533
Hi and thanks for the Points,

I guess meikl's code is clear and perfect for your question. but we are ready for more help.

Hamed ;-)

0
 

Author Comment

by:chmod101
ID: 6947734
hey, I am about to post another question which is an extension of this topic. check it out.


chmod101
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Find and Replace Stream with 0s 8 69
Graphics32 under Delphi 10.1 Berlin 2 98
Delphi: making a BW image transparent 10 59
Delphi Seattle StructureView color 1 14
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question