Bonjour

Ayant souvent besoin de désactiver un événement d'un composant dans le programme qui occupe la majeure partie de mon temps, j'ai voulu simplifier la chose.
Pour ne plus être obligé dans chaque procédure de déclarer un TNotifyEvent et l'utiliser pour lui assigner l'événement ciblé, mettre l'événement à nil, faire mon opération et réassigner l'événement au composant, j'ai écris vite fait le code suivant:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 
unit UEventManager;
 
interface
 
uses System.SysUtils, System.Classes, System.StrUtils, System.Generics.Collections,
     System.Rtti,
     FMX.Controls, FMX.StdCtrls, FMX.Listbox, FMX.Edit,
     EditNumerique;
 
type
 
  TEventManager = class(TObject)
  private
    Events: TDictionary<TControl, TNotifyEvent>;
  protected
 
  public
    constructor Create;
    destructor Destroy; override;
 
    procedure EnableEvent(Ct: TControl);
    procedure DisableEvent(Ct: TControl);
 
    function IsEnabled(Ct: TControl): Boolean;
    function IsDisabled(Ct: TControl): Boolean;
  end;
 
var
  EvtMgr: TEventManager;
 
implementation
 
{ TEventManager }
 
constructor TEventManager.Create;
begin
  inherited Create;
  Events := TDictionary<TControl, TNotifyEvent>.Create;
end;
 
destructor TEventManager.Destroy;
begin
  Events.Clear;
  FreeAndNil(Events);
  inherited;
end;
 
const
  Props: array[0..1] of string = ('OnChange', 'OnClick');
 
procedure TEventManager.DisableEvent(Ct: TControl);
var
  P: TPair<TControl, TNotifyEvent>;
begin
 
  // On ne peut pas désactiver un évènement déjà désactivé
  if Events.ContainsKey(Ct) then
    Exit;
 
  if Ct is TCheckBox then
  begin
    Events.Add(Ct, TCheckBox(Ct).OnClick);
    TCheckBox(Ct).OnClick := nil;
  end
  else if Ct is TComboBox then
  begin
    Events.Add(Ct, TComboBox(Ct).OnChange);
    TComboBox(Ct).OnChange := nil;
  end
  else if Ct is TEdit then
  begin
    Events.Add(Ct, TEdit(Ct).OnChange);
    TEdit(Ct).OnChange := nil;
  end
  else if Ct is TEditNumeric then
  begin
    Events.Add(Ct, TEditNumeric(Ct).OnChange);
    TEditNumeric(Ct).OnChange := nil;
  end;
 
end;
 
 
procedure TEventManager.EnableEvent(Ct: TControl);
var
  P: TPair<TControl, TNotifyEvent>;
  Prt: TRttiProperty;
  S: string;
begin
  if Events.ContainsKey(Ct) then
  begin
    P := Events.ExtractPair(Ct);
 
    if Ct is TCheckBox then
      TCheckBox(Ct).OnClick := P.Value
    else if Ct is TComboBox then
      TComboBox(Ct).OnChange := P.Value
    else if Ct is TRadioButton then
      TRadioButton(Ct).OnChange := P.Value
    else if Ct is TEdit then
      TEdit(Ct).OnChange := P.Value
    else if Ct is TEditNumeric then
      TEditNumeric(Ct).OnChange := P.Value;
 
  end;
end;
 
function TEventManager.IsDisabled(Ct: TControl): Boolean;
begin
  Result := Events.ContainsKey(Ct);
end;
 
function TEventManager.IsEnabled(Ct: TControl): Boolean;
begin
  Result := not Events.ContainsKey(Ct);
end;
 
initialization
  EvtMgr := TEventManager.Create;
 
finalization
  FreeAndNil(EvtMgr);
 
end.
et il s'utilise tout simplement comme ça:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
 
UEventManager.EvtMgr.DisableEvent(EditAdd);
// .....
UEventManager.EvtMgr.EnableEvent(EditAdd);
ça fonctionne très bien et ça demanderait surement quelques améliorations mais pour le moment ça me suffit.

Mais comme vous le voyez, le côté "générique" n'y est pas vraiment.

Comment je pourrais améliorer ça pour ne pas avoir à rajouter un test sur le type de classe si je devais prendre en compte d'autres types que ceux que j'ai inclus ?

Evidemment, si l'idée de ce bout de code vous séduit, n'hésitez pas à l'utiliser