Toon posts:

[delphi] eigen events

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ondanks dat het volgens de Delphi help erg ongebruikelijk is wil ik toch eigen events gaan maken. In de help staat hier wel een stappenplan voor, maar m.i. mist er iets.

Ik heb de help gevolgd en weet volgens mij alles. Alleen vraag ik mij heel hard af hoe en waar ik de code moet schrijven die bepaald dat het event gegenereerd moet worden.

En dat kan ik dus niet in de help, niet op GoT, of waar dan ook vinden. Heeft iemand hier een opzetje voor?

Verwijderd

Je moet eerst een type maken, de standaard TNotifyEvent ziet er als volgt uit:
code:
1
TNotifyEvent = procedure (Sender: TObject) of object;

Dit wordt een 'method pointer' genoemd.

Wil je dit in een component gebruiken, dan doe je zoiets:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{ Definieer je methode pointer }
TIetsEvent = procedure(Sender: TObject; const Var1, Var2: TSomeType; 
  var Var3: TAnderType) of object;

TMyComp = class(TComponent)
private
  { Je hebt een variabele nodig }
  FOnIets: TIetsEvent;
protected
  { Met DoIets roep je het event aan }
  procedure DoIets(const Var1, Var2: TSomeType; var Var3: TAnderType);
published
  { En mbv property OnIets kan iemand er iets mee doen }
  property OnIets: TIetsEvent read FOnIets write FOniets;
end;

[..]

procedure TMyComp.DoIets(const Var1, Var2: TSomeType; var Var3: TAnderType);
begin
  if Assigned(FOnIets) then FOnIets(Self, Var1, Var2, Var3);
end;

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Waarom niet gelijk de FOnIets aanroepen (natuurlijk wel met een assigned check)? Wat is het voordeel van die extra procedure?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Eh, maakt de code leesbaarder :) En je hoeft minder te tikken ofzo.

Is meer een stijl kwestie denk ik.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Op maandag 01 april 2002 23:40 schreef DiFool het volgende:
Eh, maakt de code leesbaarder :) En je hoeft minder te tikken ofzo.

Is meer een stijl kwestie denk ik.
Doet Borland zeker ook in zijn VCL code, of niet?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

LOL, je hebt me door :)

Misschien doe ik het daar door wel; hoewel, ik deed het eerst ook meestal door gewoon in de code te zetten - if assigned etc. - maar als je het mbv een procedure doet, wordt je code echt leesbaarder.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Dit doet borland alleen zo als het een visueel object is (dus instelbaar via de object inspector),

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Topicstarter
Na bovenstaande tips en nog wat internet gespeur ben ik aan de slag gegaan met de voorgestelde opzet. Dit heb ik er uiteindelijk van gebrouwen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
unit MyNewComp;

interface

uses
  Windows, Messages, SysUtils, Classes;

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

  TMyNewComp = class(TComponent)
  private
    { Private declarations }
    FOnIets: TNotifyEvent;
    FBlaat: string;
  protected
    { Protected declarations }
    procedure DoIets();
  public
    { Public declarations }
    property Blaat: string read FBlaat write FBlaat;
  published
    { Published declarations }
    property OnIets: TNotifyEvent read FOnIets write FOniets;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Dennis', [TMyNewComp]);
end;

procedure TMyNewComp.DoIets();
// In deze functie wordt m.i. de voorwaarde voor het event gedefinieerd
begin
  if FBlaat = 'X'  then FOnIets(Self);
end;

end.

Mijn bedoeling is dat als er 'X' in de variable Blaat komt te staan dat dan het event OnIets wordt getriggerd. In dit geval werkt dat niet.

Komt dat omdat ik iets fout doe, of omdat ik iets onmogelijks wil?

  • Knutselsmurf
  • Registratie: December 2000
  • Laatst online: 10-09 09:02

Knutselsmurf

LED's make things better

Even uit mijn hoofd zul je zelf de procedure Doiets aan moeten roepen in de Onchange van je component. Mocht aan de voorwaarde voldaan zijn dan zal het event getriggerd worden. Zoals ik je code nu zie, zie ik niet wanneer die check uitgevoerd zou moeten worden..........

- This line is intentionally left blank -


Verwijderd

Op dinsdag 02 april 2002 12:26 schreef Creepy het volgende:
Dit doet borland alleen zo als het een visueel object is (dus instelbaar via de object inspector),
Dit is onzin... borland gebruikt events zowel bij visueel als nonvisuele components. (Dialogs, Database, Timers, enz enz)

Trouwns die events zijn echt super handig om de code duidelijk te houden...

  • ajvdvegt
  • Registratie: Maart 2000
  • Laatst online: 15-08 12:40
Op woensdag 03 april 2002 21:16 schreef mgfun het volgende:
[..]
Trouwns die events zijn echt super handig om de code duidelijk te houden...
Ze zijn ook heel geschikt om volkomen onleesbare code te maken. :o
Toen ik events eenmaal in de vingers had zitten gooide ik ze overal tegen aan. Gecombineerd met virtuele functies en he overschrijven van functies (met 'override'), en kind-objecten die events met dezelfde namen maar een andere aanroep hebben kan je van alles gaan doen. Leuke dingen allemaal, maar als je dat na een maandje ofzo terug ziet snap je er echt niets meet van.
Use with care!

En zoals Knutselsmurf al zei, moet je ergnes nog iets aan een OnChange event koppelen. Je kan OnChange overschrijven als je wilt, zoals je nu OnIets definieerd.

En is het type TNotifyEvent niet een standaard type in Delphi? Dat hoef je niet meer te declareren toch?

I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum


Verwijderd

Op maandag 01 april 2002 23:28 schreef jelmervos het volgende:
Waarom niet gelijk de FOnIets aanroepen (natuurlijk wel met een assigned check)? Wat is het voordeel van die extra procedure?
Als je die OnIets nu ook virtual maakt, kan je hem in afgeleide klasses overriden(opnieuw definieren). dus kan je in je afgeleide klasse ook iets doen op het event.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Op woensdag 03 april 2002 21:16 schreef mgfun het volgende:

[..]

Dit is onzin... borland gebruikt events zowel bij visueel als nonvisuele components. (Dialogs, Database, Timers, enz enz)

Trouwns die events zijn echt super handig om de code duidelijk te houden...
Ook als die message NIET door de gebruiker is in te stellen (in code of visueel...)??
Hmm.. morgen op m'n werk eens wat Delphi source door spitten.

Het gebruik van een property als die toch altijd hetzelfde is en allene private wordt gebruikt ontgaat me namelijk (zoals in dit geval..)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

ff uit het hoofd:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
unit MyNewComp;
interface

uses
  Windows, Messages, SysUtils, Classes;

type
//  TNotifyEvent = procedure(Sender: TObject) of object;// niet nodig, is een standaard-type
 
  TMyNewComp = class(TComponent)
  private
    { Private declarations }
    FOnIets: TNotifyEvent;
    FBlaat: string;
  protected
    { Protected declarations }
    procedure DoIets();
    Procedure SetBlaat(const newblaat:string);
  public
    { Public declarations }
    property Blaat: string read FBlaat write SetBlaat;
  published
    { Published declarations }
    property OnIets: TNotifyEvent read FOnIets write FOnIets;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Dennis', [TMyNewComp]);
end;


Procedure TMyNewComp.SetBlaat(const newblaat:string);
begin
FBlaat:=Newblaat;
if FBlaat = 'X'  then DoIets;
end;
  

procedure TMyNewComp.DoIets();
// In deze functie wordt m.i. de voorwaarde voor het event gedefinieerd
begin
  if assigned(FOnIets)  then FOnIets(Self);
end;

end.

Verwijderd

Creepy:
Ook als die message NIET door de gebruiker is in te stellen (in code of visueel...)??
Hmm.. morgen op m'n werk eens wat Delphi source door spitten.

Het gebruik van een property als die toch altijd hetzelfde is en allene private wordt gebruikt ontgaat me namelijk (zoals in dit geval..)
Ik begrijp niet precies wat je bedoelt met een event die niet door de gebruiker is in te stellen. Bedoel je dat de property protected of private is. Dat lijkt me inderdaad zwaar overbodig. Tenzij het een abstract/base class is natuurlijk.

Voorbeelden van Do.. in delphi source zijn de Changing en Changed methods van veel base classen zoals TGraphicsObject, TBasicAction etc.

Die base classen leggen dan vast wanneer die Do.. aangeroepen wordt, en de ancestor classen kunnen die dan eventueel overriden; dan is het eigenlijk ook een soort event naar die ancestor class.

BTW: als jij zegt visueel component dan denk ik aan een TControl ancestor terwijl jij het volgens mij hebt over een TComponent ancestor.

Verwijderd

Topicstarter
Op woensdag 03 april 2002 22:06 schreef deur het volgende:
ff uit het hoofd:
code:
1
2
3
4
5
unit MyNewComp;

//...

end.
OK, bovenstaande werkt. Thanx.

Nou was bovenstaande natuurlijk een testproggie. In de praktijk wil ik een event laten gebeuren als ik bepaalde informatie op een poort binnen krijg. Ik zal dus een functie in een loop de poort moeten laten testen en een event laten genereren als de info binnen is. Maar logischerwijs wil ik dat mijn applicatie meer kan dan in die loop blijven staan.

Is het hier dan de bedoeling en het best om gebruik van Threads te maken?

Ik wil nog niet de code weten, want wil eerst zelf proberen het een en ander aan de praat te krijgen.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Op donderdag 04 april 2002 00:22 schreef DiFool het volgende:

[..]

Ik begrijp niet precies wat je bedoelt met een event die niet door de gebruiker is in te stellen. Bedoel je dat de property protected of private is. Dat lijkt me inderdaad zwaar overbodig. Tenzij het een abstract/base class is natuurlijk.
Yep, dat bedoel ik (ik ken helaas een aantal mensen die dit wel doen..).. en bepaalde messages zoals onderstaande (deze is ook private):
code:
1
2
3
4
5
6
7
8
9
procedure WMIconEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ICONERASEBKGND;

procedure TCustomForm.WMIconEraseBkgnd(var Message: TWMIconEraseBkgnd);
begin
  if FormStyle = fsMDIChild then
  if (FormStyle = fsMDIChild) and not (csDesigning in ComponentState) then
    FillRect(Message.DC, ClientRect, Application.MainForm.Brush.Handle)
  else inherited;
end;
BTW: als jij zegt visueel component dan denk ik aan een TControl ancestor terwijl jij het volgens mij hebt over een TComponent ancestor.
Hmm.. ik riep visueel component, maar eigenlijk bedoelde ik elk component dat events heeft die niet in te stellen zijn door de gebruiker (omdat ze bijv. private zijn). En negen van de tien keer stel je die events in via de Object Inspector (en dan zijn ze dus "visueel").

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Volgens mij wordt TControl ook afgeleid van TComponent.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Op donderdag 04 april 2002 10:35 schreef kwakeld9 het volgende:
Volgens mij wordt TControl ook afgeleid van TComponent.
Klopt ja (handig die VCL Object hierarchy hier aan de muur :) ).

Object, component.. ik gebruik ze gewoon door elkaar, maar ik gebruik ze niet om aan te geven dat ik een (afgeleide van) TCOmponent of TObject bedoel. Gewoon om aan te geven dat het een instantie van een klasse is. Maar beter zou voor mij zijn om daar alleen object voor te gebruiken (Object Oriented.. klassen en objecten).

maar wordt wel redelijk offtopic zo...

Elke klasse kan events hebben in Delphi, dus eigenlijk zou je het dan over TObject in het algemeen moeten hebben (elke klasse in Delphi is een afgeleide van TObject).

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Op donderdag 04 april 2002 08:48 schreef delighteddennis het volgende:

[..]
Nou was bovenstaande natuurlijk een testproggie. In de praktijk wil ik een event laten gebeuren als ik bepaalde informatie op een poort binnen krijg. Ik zal dus een functie in een loop de poort moeten laten testen en een event laten genereren als de info binnen is. Maar logischerwijs wil ik dat mijn applicatie meer kan dan in die loop blijven staan.

Is het hier dan de bedoeling en het best om gebruik van Threads te maken?
In dat geval zou ik een tread aanmaken waarin die loop zit die de info op een poort checkt.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Creepy:
[..]
en bepaalde messages zoals onderstaande (deze is ook private):
code:
1
2
3
4
5
6
7
8
9
10
procedure WMIconEraseBkgnd(var Message: TWMEraseBkgnd); 
  message WM_ICONERASEBKGND;

procedure TCustomForm.WMIconEraseBkgnd(var Message: TWMIconEraseBkgnd);
begin
  if FormStyle = fsMDIChild then
  if (FormStyle = fsMDIChild) and not (csDesigning in ComponentState) then
    FillRect(Message.DC, ClientRect, Application.MainForm.Brush.Handle)
  else inherited;
end;
De grap is dat je private message handlers wel kunt overriden in een ancestor class :) Wel rare code trouwens met die dubbele FormStyle = fsMDIChild.
kwakeld9:
Volgens mij wordt TControl ook afgeleid van TComponent.
Dat klopt, maar niet elke TComponent ancestor is een TControl ancestor; dus niet elke TComponent ancestor is een 'visueel' component, bedoelde ik.

Verwijderd

Op donderdag 04 april 2002 08:48 schreef delighteddennis het volgende:
Nou was bovenstaande natuurlijk een testproggie. In de praktijk wil ik een event laten gebeuren als ik bepaalde informatie op een poort binnen krijg. Ik zal dus een functie in een loop de poort moeten laten testen en een event laten genereren als de info binnen is. Maar logischerwijs wil ik dat mijn applicatie meer kan dan in die loop blijven staan.

Is het hier dan de bedoeling en het best om gebruik van Threads te maken?
Ik heb eens een keer zo'n soort programma geschreven en het kwam erop neer, dat je een read en write thread hebt. Deze zitten in een waitable state nadat ze aan windows aangegeven hebben dat ze de poort in de gaten willen houden.

Windows geeft dan - als er iets op die poort gebeurt - een event naar de read/write thread. En deze kan die dan weer doorgeven naar de main thread.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 18:56

Creepy

Tactical Espionage Splatterer

Op donderdag 04 april 2002 11:55 schreef DiFool het volgende:

[..]
De grap is dat je private message handlers wel kunt overriden in een ancestor class :) Wel rare code trouwens met die dubbele FormStyle = fsMDIChild.
[..]
Hmm.. ik dacht dat dat alleen met protected kon. Zo eens proberen :)

En die vreemde coding style heeft zo te zien te maken met die inherited.Die wordt nu uitgevoerd als het WEL een MDIChild is, en in designmode zit. Zonder die eerste if kan ie ook worden uitgevoerd als het GEEN MDIChild is. Het waarom van dit geheel ontgaat me op het moment, maar goed :)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

Ik bedoelde dat deze code hetzelfde doet:
code:
1
2
3
4
5
6
7
8
procedure TCustomForm.WMIconEraseBkgnd(var Message: TWMIconEraseBkgnd);
begin
  if FormStyle = fsMDIChild then
    if not (csDesigning in ComponentState) then
    FillRect(Message.DC, ClientRect, Application.MainForm.Brush.Handle)
    else
    inherited;
end;

Ik denk dat ze die 'if FormStyle = fsMDIChild then' er later voor hebben gezet, ofzo..
Pagina: 1