Le Assign copie les objets pour un combobox mais pas pour un mémo
Bonjour à tous,
Je me suis bien pris la tête sur ce point alors, comme ça m'a servi, peut être servira-t-il aux autres ;)
L'assignation des éléments d'une combobox copie les objets associés alors que l'assignation des éléments d'un mémo ne copie pas les objets.
Pourquoi ?
Bien que les éléments d'un mémo et d'une combobox soient tous deux de type TStrings, leur fonctionnement diffère.
1. Pour un memo, les éléments ont pour propriété 'Lines'
Code:
1 2 3 4
| TMemo = class(TCustomMemo)
published
...
property Lines; |
Il dérive de TCustomMemo
Code:
1 2 3 4 5 6 7 8 9
| TCustomMemo = class(TCustomEdit)
private
...
protected
...
public
...
property Lines: TStrings read FLines write SetLines;
end; |
La variable private s'appelle FLines et on va voir comment elle est créée...
Il n'y a pas de TMemo.Create.
On passe à TCustomMemo. Create :
Code:
1 2 3 4 5 6
| constructor TCustomMemo.Create(AOwner: TComponent);
begin
...
FLines := TMemoStrings.Create;
...
end; |
FLines est donc de type TMemoStrings.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| TMemoStrings = class(TStrings)
private
Memo: TCustomMemo;
protected
function Get(Index: Integer): string; override;
function GetCount: Integer; override;
function GetTextStr: string; override;
procedure Put(Index: Integer; const S: string); override;
procedure SetTextStr(const Value: string); override;
procedure SetUpdateState(Updating: Boolean); override;
public
procedure Clear; override;
procedure Delete(Index: Integer); override;
procedure Insert(Index: Integer; const S: string); override;
end; |
Le Assign n'est pas présent dans TMemoStrings, on monte à TStrings.
Code:
1 2 3 4 5 6
| procedure TStrings.Assign(Source: TPersistent);
begin
...
AddStrings(TStrings(Source));
...
end; |
On regarde AddStrings :
Code:
1 2 3 4 5 6
| procedure TStrings.AddStrings(Strings: TStrings);
begin
...
AddObject(Strings[I], Strings.Objects[I]);
end; |
On regarde AddObject :
Code:
1 2 3 4 5
| function TStrings.AddObject(const S: string; AObject: TObject): Integer;
begin
Result := Add(S);
PutObject(Result, AObject);
end; |
On regarde PutObject :
Code:
1 2 3
| procedure TStrings.PutObject(Index: Integer; AObject: TObject);
begin
end; |
-> Ne fait rien... Cool ;)
2. Pour un combo, les éléments ont pour propriété items
Code:
1 2 3 4 5
| TComboBox = class(TCustomComboBox)
published
...
property Items; { Must be published after OnMeasureItem }
end; |
Dérive de TCustomComboBox
Code:
TCustomComboBox = class(TCustomCombo)
qui n'a pas items de défini
Il dérive de TCustomCombo
Code:
1 2 3 4 5 6 7 8 9 10
| TCustomCombo = class(TCustomListControl)
private
...
protected
...
public
...
property Items: TStrings read FItems write SetItems;
...
end; |
La variable private est donc FItems.
On regarde si le create de TCustomCombo la définit...
-> Non...
On regarde donc si le create de TCustomComboBox la définit...
Code:
1 2 3 4 5 6
| constructor TCustomComboBox.Create(AOwner: TComponent);
begin
...
FItems := GetItemsClass.Create;
...
end; |
Oui... Donc FItems est de type GetItemsClass (sans doute descendant de TStrings...)
En fait, GetItemsClass est une fonction qui renvoie la classe TCustomComboBoxStringsClass
Code:
TCustomComboBoxStringsClass = class of TCustomComboBoxStrings;
Code:
1 2 3 4 5 6 7 8 9 10
| TCustomComboBoxStrings = class(TStrings)
private
...
protected
...
procedure PutObject(Index: Integer; AObject: TObject); override;
...
public
...
end; |
PutObject, défini à vide en TStrings est ici déclaré...
Code:
1 2 3 4
| procedure TCustomComboBoxStrings.PutObject(Index: Integer; AObject: TObject);
begin
SendMessage(ComboBox.Handle, CB_SETITEMDATA, Index, Longint(AObject));
end; |
...et pas vide ;)
Voilà donc pourquoi le assign sur les éléments d'un Combo et d'un Memo sont différents, bien que les éléments Lines et Items soient de même type...
Comme ils sont créés avec des types différents, l'un surcharge la copie des objets, ce que l'autre ne fait pas...
Hope it helps ;)