Можно ли добавить дополнительные параметры в событие OnClick в дополнение к стандартному «Sender: TObject» в Delphi? - PullRequest
3 голосов
/ 08 января 2011

Я выполняю свой вычислительный проект A2 в Delphi и столкнулся с проблемой, когда дело доходит до добавления дополнительных параметров в процедуру обработки события.

Я создаю несколько меток (объект TLabel) и сохраняю их в массиве под моей основной формой "form1".

Вот что у меня сейчас:

** Объявление массива меток и соответствующей процедуры ClickEvent с переданным стандартным параметром (Sender: TObject).

 public
     InventoryLabel : array [0..23] of TLabel;
     procedure InventoryLabelClick(Sender: TObject);

** Это процедура ClickEvent, соответствующая заявленной выше. (Содержание процедуры очень грязное, но имеет отношение к вопросу и является тем, что я использую в настоящее время.)

Procedure TForm1.InventoryLabelClick(Sender: TObject);
begin
if sender = InventoryLabel[0] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[0]].cardpic);
if sender = InventoryLabel[1] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[1]].cardpic);
if sender = InventoryLabel[2] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[2]].cardpic);
if sender = InventoryLabel[3] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[3]].cardpic);
if sender = InventoryLabel[4] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[4]].cardpic);
if sender = InventoryLabel[5] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[5]].cardpic);
if sender = InventoryLabel[6] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[6]].cardpic);
if sender = InventoryLabel[7] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[7]].cardpic);
if sender = InventoryLabel[8] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[8]].cardpic);
if sender = InventoryLabel[9] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[9]].cardpic);
if sender = InventoryLabel[10] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[10]].cardpic);
if sender = InventoryLabel[11] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[11]].cardpic);
if sender = InventoryLabel[12] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[12]].cardpic);
if sender = InventoryLabel[13] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[13]].cardpic);
if sender = InventoryLabel[14] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[14]].cardpic);
if sender = InventoryLabel[15] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[15]].cardpic);
if sender = InventoryLabel[16] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[16]].cardpic);
if sender = InventoryLabel[17] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[17]].cardpic);
if sender = InventoryLabel[18] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[18]].cardpic);
if sender = InventoryLabel[19] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[19]].cardpic);
if sender = InventoryLabel[20] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[20]].cardpic);
if sender = InventoryLabel[21] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[21]].cardpic);
if sender = InventoryLabel[22] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[22]].cardpic);
if sender = InventoryLabel[23] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[23]].cardpic); 
end;

** Это фрагмент кода, который создает метки и присваивает им их атрибуты.

for I := 0 to 23 do
  begin
    InventoryLabel[i] := TLabel.Create(nil);
      with InventoryLabel[i] do
        begin
          Parent := Inventory;
          left := 8;
          OnClick := InventoryLabelClick;
          visible := false;
        end;
end;

Это все очень хорошо и работает (иш), однако я хочу передать параметр, когда я вызываю процедуру «InventoryLabelClick», в этом случае переменную «I», которая будет ссылкой на нажатую метку. Это позволит мне удалить все «if sender = inventorylabel [x]» (x - любое из чисел, указанных выше) и вместо этого заменить только вторым битом «imgInvItem.Picture.LoadFromFile (redcarddeck [redcardpositionsofinventory [I]]). cardpic);» но с параметром «I» вместо числа «x» (как указано выше).

Я попробовал следующие изменения, чтобы посмотреть, сработает ли это.

** Измените его в объявлении

Public
   procedure InventoryLabelClick(Sender: TObject; I: Integer);

** Измените это для процедуры в реализации

Procedure TForm1. InventoryLabelClick(Sender: TObject; I: Integer);

** Тогда при событии оно присваивается объекту

for I := 0 to 23 do
  begin
    InventoryLabel[i] := TLabel.Create(nil);
      with InventoryLabel[i] do
        begin
          Parent := Inventory;
          left := 8;
          OnClick := InventoryLabelClick;
          visible := false;
        end;
end;

** параметр sender является значением по умолчанию, поэтому нет необходимости объявлять его в первом случае. Однако, когда есть несколько параметров, он запрашивает оба.

При запуске возвращается сообщение об ошибке "

E2010 Несовместимые типы: «TNotifyEvent» и «процедура, нетипизированный указатель или нетипизированный параметр»

"Я понимаю, что это означает, что я объявил параметры неверными.

Кто-нибудь может помочь мне решить эту проблему? Если окажется, что невозможно передать дополнительный параметр, как я пытался сделать выше, кто-нибудь может предложить способ сделать код немного более аккуратным?

Заранее спасибо.

Ответы [ 3 ]

7 голосов
/ 08 января 2011

Сохраните значение "i" в свойстве TLabel's Tag.

for I := 0 to 23 do begin
  InventoryLabel[i] := TLabel.Create(nil);
  with InventoryLabel[i] do begin
    Parent := Inventory;
    Tag := i;
    left := 8;
    OnClick := InventoryLabelClick;
    visible := false;
  end;
end;

Затем в событии OnClick введите приведение Sender к TLabel и считайте значение тега, чтобы щелкнуть метку:

Procedure TForm1.InventoryLabelClick(Sender: TObject);
  begin
    imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[TLabel(Sender).Tag]].cardpic);
  end;
3 голосов
/ 08 января 2011

Почему бы тебе не сделать это так?

Procedure TForm1.InventoryLabelClick(Sender: TObject);
var i : integer;
begin
  for i := 0 to 23 do
    if sender = InventoryLabel[i] then imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[i]].cardpic);
end;

Конечно, лучшим способом было бы сделать InventoryLabel не TLabel, а пользовательским классом, который инкапсулирует TLabel и метод LoadPicture, поэтому вы можете сделать:

Procedure TForm1.InventoryLabelClick(Sender: TObject);
begin
  Sender.LoadPicture;
end;

Но это будет немного больше работы.

2 голосов
/ 08 января 2011

Вы не можете изменить подпись TNotifyEvent. Вам необходимо создать собственный элемент управления меткой с собственным событием OnClick, которое принимает дополнительные параметры. Это, вероятно, больше работы, чем требуется для школьного проекта, и в целом я не рекомендую писать пользовательский элемент управления, если у вас нет другой альтернативы.

Однако есть более простой способ.

Procedure TForm1.InventoryLabelClick(Sender: TObject);
var
  I: Integer;
begin
  for I := Low(InventoryLabel) to High(InventoryLabel)do
    if Sender = InventoryLabel[I] then
      imgInvItem.Picture.LoadFromFile(redcarddeck[redcardpositionsofinventory[I]].cardpic);
end;
...