Я хотел бы иметь возможность динамически генерировать всплывающие меню в pascal.Динамическое назначение анонимных функций в pascal
Я также хотел бы иметь возможность динамически назначать обработчики OnClick каждому элементу меню.
Это то, что я привык делать в C#, это моя попытка в pascal.
Элемент меню обработчик события onClick должен принадлежать объекту (of Object
), поэтому для этого создаю объект-контейнер.
Вот мой код:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Menus;
type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TFoo = class
public
Bar : String;
Val : Integer;
end;
TNotifyEventWrapper = class
private
FProc: TProc<TObject>;
I : Integer;
public
constructor Create(Proc: TProc<TObject>);
published
procedure Event(Sender: TObject);
end;
var
Form1: TForm1;
NE : TNotifyEventWrapper;
implementation
{$R *.dfm}
constructor TNotifyEventWrapper.Create(Proc: TProc<TObject>);
begin
inherited Create;
FProc := Proc;
end;
procedure TNotifyEventWrapper.Event(Sender: TObject);
begin
ShowMessage(IntToStr(I));
FProc(Sender);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
F : TFoo;
I: Integer;
mi : TMenuItem;
begin
if Assigned(NE) then FreeAndNil(NE);
for I := 1 to 10 do
begin
F := TFoo.Create;
F.Bar := 'Hello World!';
F.Val := I;
NE := TNotifyEventWrapper.Create
(
procedure (Sender :TObject)
begin
ShowMessage(F.Bar + ' ' + inttostr(F.Val) + Format(' Addr = %p', [Pointer(F)]) + Format('Sender = %p, MI.OnClick = %p', [Pointer(Sender), Pointer(@TMenuItem(Sender).OnClick)]));
end
);
NE.I := I;
mi := TMenuItem.Create(PopupMenu1);
mi.OnClick := NE.Event;
mi.Caption := inttostr(F.Val);
PopupMenu1.Items.Add(mi);
end;
end;
end.
При нажатии пункта меню номер 6
Программа показывает ожидаемое сообщение
Однако следующее сообщение не было t показывает ожидаемый результат.
Вместо 6 он не показывает пункт 10
Независимо от того, какой элемент в списке я нажимаю на все они, кажется, срабатывает обработчик событий для последнего элемента в списке (10).
Мне было предложено, чтобы процедура объекта объекта NE
Event
была одинаковым адресом памяти для всех экземпляров этого объекта.
Какой бы элемент меню я нажимаю, адрес памяти MI.OnClick
такой же.
Мне интересно, нашел ли я ошибку/ограничение delphi – sav
Нет, у вас ее нет. Вы еще не полностью поняли нюанс переменной захвата. Он фиксирует переменные, а не значения. –
Обратите внимание, что ваш код протекает. Я предполагаю, что вы это знаете и планируете заняться этим позже. –