Присвоение значений OnClick

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
novo
новенький
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Присвоение значений OnClick

Сообщение novo »

Доброго времени суток)

Такая проблема:
Не получается присвоить значение OnClick созданной кнопке

Делал так:

Код: Выделить всё

var
  b:TButton;
.....
  b := TButton.Create(nil);
  with b do begin
    Parent := Form1;
    Name:=n;
    Caption:=capt;
    left:=l;
    top:=t;
    Width:=20;
    Height:=20;
    OnClick:=@Label1Click;
  end;

procedure TForm1.Label1Click(Sender: TObject);
begin
  showmessage('ok');
end;     
 
Maxizar
постоялец
Сообщения: 385
Зарегистрирован: 20.03.2010 18:48:14

Сообщение Maxizar »

А у меня все работает:
вот пример: http://zalil.ru/32286589

Так же вот можно почитать: Вопросы по указателям на методы!
tema
постоялец
Сообщения: 376
Зарегистрирован: 24.03.2011 19:19:27

Сообщение tema »

Пробовал явно указать?

Код: Выделить всё

b.OnClick:=@Label1Click;

Так работает?
novo
новенький
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Сообщение novo »

tema писал(а):Пробовал явно указать?

Код: Выделить всё

b.OnClick:=@Label1Click;

Так работает?

Действительно работает)
Спасибо.

А можно ли как нибудь присвоить значение собственной процедуры и передать ей значения?
что то вроде этого:

Код: Выделить всё

procedure mypocedure(text:string);
begin
showmessage(text);
end;

b.OnClick:=@mypocedure('передаваемые данные');
tema
постоялец
Сообщения: 376
Зарегистрирован: 24.03.2011 19:19:27

Сообщение tema »

novo писал(а):Действительно работает)
Спасибо.

Это просто такой глюк я давно заметил бывает, если явно не указать, то ИНОГДА он может воспринять, например, OnClick как Form1.OnClick, игнорируя with
novo писал(а):А можно ли как нибудь присвоить значение собственной процедуры и передать ей значения?

Можно.
Чтобы не париться, можно просто внести процедуру в класс формы.

Код: Выделить всё

procedure Form1.mypocedure(text:string);
begin
showmessage(text);
end;
b.OnClick:=@mypocedure('передаваемые данные');

И добавить строчку

Код: Выделить всё

procedure mypocedure(text:string);

В описание класса Form1. Куда-нибудь в private, ну или куда надо хоть в public
novo
новенький
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Сообщение novo »

tema писал(а):
novo писал(а):Действительно работает)
Спасибо.

Это просто такой глюк я давно заметил бывает, если явно не указать, то ИНОГДА он может воспринять, например, OnClick как Form1.OnClick, игнорируя with
novo писал(а):А можно ли как нибудь присвоить значение собственной процедуры и передать ей значения?

Можно.
Чтобы не париться, можно просто внести процедуру в класс формы.

Код: Выделить всё

procedure Form1.mypocedure(text:string);
begin
showmessage(text);
end;
b.OnClick:=@mypocedure('передаваемые данные');

И добавить строчку

Код: Выделить всё

procedure mypocedure(text:string);

В описание класса Form1. Куда-нибудь в private, ну или куда надо хоть в public


Не получается однако

unit1.pas(76,15) Error: Incompatible types: got "<procedure variable type of procedure(AnsiString) of object;Register>" expected "<procedure variable type of procedure(TObject) of object;Register>"
tema
постоялец
Сообщения: 376
Зарегистрирован: 24.03.2011 19:19:27

Сообщение tema »

Тьфу стормозил не понял сразу вопрос :-)
Дело в том, что у OnClick есть стандартный вид: Button1Click(Sender: TObject); т.е. процедура ждёт параметрами не string, а TObject.

Добавлено спустя 5 минут 2 секунды:
Придётся делать какой-нибудь объект. Или перегружать процедуру в исходниках TButton.

Код: Выделить всё

procedure Form1.mypocedure(mytext:TObject);
begin
showmessage((mytext as TStrings).Strings[0]);
end;
novo
новенький
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Сообщение novo »

Возможно я что то не понял
убрал with
сделал все как сказано
однако
в строке
b.OnClick:=@mypocedure('передаваемые данные');

unit1.pas(76,28) Fatal: Syntax error, ";" expected but "(" found
tema
постоялец
Сообщения: 376
Зарегистрирован: 24.03.2011 19:19:27

Сообщение tema »

Не так. Ты не понял. Ты не можешь передать в эту процедуру строку. Тебе её надо для этого перегрузить в исходниках лазаруса.
Если не хочешь лезть в исходники я написал как можно воспользоваться костылём. Но ты должен передавать какой-нибудь Object, а не строку. Я в виде костыля поставил TStrings.
Т.е. вместо этого:

Код: Выделить всё

b.OnClick:=@mypocedure('передаваемые данные');

Должно быть написано:

Код: Выделить всё

var
s:TStringList;
......
.....
s:=TStringList.Create;
s.Append('передаваемые данные');
b.OnClick:=@mypocedure(s);
Odyssey
энтузиаст
Сообщения: 580
Зарегистрирован: 29.11.2007 16:32:24

Сообщение Odyssey »

novo писал(а):А можно ли как нибудь присвоить значение собственной процедуры и передать ей значения?
что то вроде этого...

Нет, при установке обработчика параметры в него передавать нельзя. То есть код:

Код: Выделить всё

b.OnClick:=@mypocedure('передаваемые данные');
работать не будет.
Параметры в обработчик может передавать только тот объект, который вызывает этот обработчик. То есть кнопка b, когда её нажмут, передаст в качестве параметра Sender себя.

Как вариант, можно сделать так:

Код: Выделить всё

procedure mypocedure(text:string);
begin
  showmessage(text);
end;

procedure ClickHandler(Sender: TObject);
begin
  if Sender = b then
    mypocedure('передаваемые данные');
end;
...
b.OnClick:=@ClickHandler;
novo
новенький
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Сообщение novo »

Спасибо ребята :D
Все работает!

Код: Выделить всё

var 
  b:TButton;
  A: array  of TButton;
  len:integer;
  list:TStringList;
............
............

procedure TForm1.FormShow(Sender: TObject);
 var i:integer;
begin
 list:=tstringlist.Create;
 list.LoadFromFile('filelist.txt');
 len:=list.Count;
     SetLength(A,len);
      for i:=0 to len-1 do begin
    b := TButton.Create(form1);
     with b do begin
    Parent := Form1;
    left:=i*20;
    top:=5;
    width:=20;
    height:=20;
    OnClick:=@ClickHandler;
    popupmenu:=PopupMenu1;
    end;
    A[i]:=b;
end;
end;

procedure TForm1.ClickHandler(Sender: TObject);
var
  i:integer;
begin
 for i:=0 to length(A)-1 do begin
  if Sender = A[i] then begin
    showmessage(list[i]);
  end;
 end;
end;

Ответить