Poněkud zavádějící nadpis, ale jedná se o případ, kdy potřebujeme mít asociaci mezi položkou menu (nebo něčím podobným) a nějakou datovou strukturou.
Poslední dobou jsem potřeboval vytvářet dynamicky položky menu a zároveň k nim mít vazbu na nějakou datovou strukturu. Za začátku jsem to řešil jako
odkaz přes Tag někam, případně v Tag jsem měl přímo objekt, ale to byl problém s uvolňováním a tak mne napadlo jiné řešení (předpokládám, že mi v komentářích
všichni napíší že je to stará známá věc - ale mne to prostě předtím nenapadlo).
Jádrem pudla je, že do Tag vložíme objekt, ale který je následníkem TComponent a jako vlastníka určíme patřičnou položku menu. Tj. pokud se uvolní položka menu, zároveň uvolní i svůj asociovaný objekt a my se nemusíme o nic starat. Já vím primitivní - ale mne to prostě nikdy dřív nenapadlo.
type
TForm1 = class(TForm)
pop: TPopupMenu;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TItemInfo = class (TComponent)
public
iId: Integer;
sHelp: string;
constructor Create(Owner:TComponent; ID:Integer; const s:string); reintroduce;
end;
{$IFDEF CPUX64}
IntPtr = NativeInt;
{$ELSE}
IntPtr = Integer;
{$ENDIF}
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
function moAddItem(const sCaption:string; iId: Integer; const sHelp:string):TMenuItem;
begin
Result := TMenuItem.Create(pop);
Result.Caption := sCaption;
Result.Tag := IntPtr(TItemInfo.Create(Result, iId, sHelp));
pop.Items.Add(Result);
end;
begin
moAddItem('Pol1', 1, 'help1');
moAddItem('Pol2', 2, 'help2');
moAddItem('Pol3', 3, 'help3');
moAddItem('Pol4', 4, 'help4');
moAddItem('Pol5', 5, 'help5');
end;
{ TItemInfo }
constructor TItemInfo.Create(Owner:TComponent; ID: Integer; const s: string);
begin
inherited Create(Owner);
iId := ID;
sHelp := s;
end;
Klíčem je řádek 36, kdy nově vytvořené položce vytvoříme asociovaný objekt a jako vlastníka dáme tu vytvořenou položku. Obdobně by to mohlo fungovat pro položky treeview (ale tady bych šel asi do Virtual TreeView) nebo další komponenty.
Jinak přístup je pak samozřejmě TItemInfo(item.Tag).
Alternativou (možná i asi správnější, ale zase tím získáte závislost vašich datových struktur na VCL) může být podědění TMenuItem, kde přidáme naše položky a místo instance TMenuItem budeme přidávat instance našeho následníka.
Snad to aspoň někomu pomůže.