Динамическое создание событий
От: GrayWolf Россия https://kini24.ru
Дата: 13.01.03 07:16
Оценка:
Есть библиотека dll, не содержащаю никаких классов — одни переменные и константы. По ходу выполнения одной из функций создается пункт меню основного приложения. Вопрос в том, как создать событие OnClick для этого пункта меню. Все коды, которые я просматривал делаются так: в проект включается какой-то класс, например, TForm1, и у него уже прописывается событие. Затем это событие назначается кому надо... ))
А мне не нужно создавать класс, я хочу написать, например, так:

library MyLib;

var MenuItem: TMenuItem;
    MainMenu: TMainMenu;

procedure Clicked;
begin
  SowMessage('Hello world!');
end;

begin
  MenuItem:=TMenuItem.Create(MainMenu);
  MenuItem.Caption:='File';
  MainMenu.Items.Add(MenuItem);
  MenuItem.OnClick:=Clicked;
end.

Или так нельзя и придется создавать класс пункта меню? Оченно не хотелось бы...
Помогите, буду очень признателен!

13.01.03 12:19: Перенесено из 'COM/DCOM/ActiveX'
Re: Динамическое создание событий
От: LeXa24  
Дата: 13.01.03 08:45
Оценка:
Здравствуйте, GrayWolf, Вы писали:

Постарайся далее избегать излишнего цитирования.H_D.

Ну собственно так и делают. Вот только наверное Clicked с параметром Sender:TObject
Re[2]: Динамическое создание событий
От: vasketsov Россия http://ntprog.by.ru
Дата: 13.01.03 09:55
Оценка:
Здравствуйте, LeXa24, Вы писали:

LX>Ну собственно так и делают. Вот только наверное Clicked с параметром Sender:TObject


Ага, а Procedure — то же, что и Procedure of Object ?
Короче, я так не думаю, но на 0 не тянет .
Васкецов Сергей
http://registry.km.ru
Re[3]: Динамическое создание событий
От: LeXa24  
Дата: 13.01.03 13:37
Оценка: -1
Здравствуйте, vasketsov, Вы писали:

V>Здравствуйте, LeXa24, Вы писали:


LX>>Ну собственно так и делают. Вот только наверное Clicked с параметром Sender:TObject


V>Ага, а Procedure — то же, что и Procedure of Object ?

Сам то понял что сказал?
V>Короче, я так не думаю, но на 0 не тянет .
Ну предположим ты не хочешь получать Sender. И как ты будешь узнавать на что ты тыкнул?
Или есть большое желание писать под каждый пункт свою процедуру?
В общем вот код, пробуй. Все прекрасно работает.
procedure TForm1.DoSomething(Sender:TObject);
begin
     ShowMessage('NEW');
end;
procedure TForm1.FormShow(Sender: TObject);
var
   MenuItem:TMenuItem;
begin
     MenuItem:=TMenuItem.Create(MainMenu1);
     MenuItem.Caption:='New';
     MenuItem.OnClick:=DoSomething;
     MainMenu1.Items.Add(MenuItem);
end;

Re[4]: Динамическое создание событий
От: vasketsov Россия http://ntprog.by.ru
Дата: 13.01.03 13:59
Оценка: 30 (1)
Здравствуйте, LeXa24, Вы писали:

V>>Ага, а Procedure — то же, что и Procedure of Object ?

LX>Сам то понял что сказал?
Понял.
Тип обработчика этого события — procedure (Sender:TObject) of object;
А это не то же самое, что procedure (Sender:TObject);

LX>В общем вот код, пробуй. Все прекрасно работает.

Вот так — да, работает, никто и не спорит, а как сначала написал — без объекта — не будет.
Васкецов Сергей
http://registry.km.ru
Re: Динамическое создание событий
От: GrayWolf Россия https://kini24.ru
Дата: 13.01.03 18:12
Оценка:
Не согласен с каждым ответом!
Во всех присутствует явно или неявно класс TForm1 (или еще какой-нть). А как обойтись без них? Вот в чем суть вопроса...
Re[2]: Динамическое создание событий
От: Аноним  
Дата: 13.01.03 18:41
Оценка:
Здравствуйте, GrayWolf, Вы писали:

GW>Во всех присутствует явно или неявно класс TForm1 (или еще какой-нть). А как обойтись без них? Вот в чем суть вопроса...


Метод класса отличается от обычной процедуры тем, что в него неявно передается указатель на Self первым параметром. Поэтому если уж так хочется использовать простую процедуру вместо метода класса (зачем — это уже другой вопрос), то сделай первый параметр фиктивным TObject-ом:


procedure DoOnClick(AFake: TObject);
begin
  ShowMessage('test');
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  LHandler: TNotifyEvent;
  P: Pointer;
begin
  // Танец с бубном
  P := @DoOnClick;
  Move(P, LHandler, SizeOf(Pointer));

  // Присвоение
  Button1.OnClick := LHandler;
end;


Но, имхо, это есть извращение, к тому же теряется указатель на Self.
Re[2]: Динамическое создание событий
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 13.01.03 18:46
Оценка:
Здравствуйте, GrayWolf, Вы писали:

GW>Не согласен с каждым ответом!

GW>Во всех присутствует явно или неявно класс TForm1 (или еще какой-нть). А как обойтись без них? Вот в чем суть вопроса...

Ну тогда, наверное, придется пересмотреть архитектуру приложения... То есть, если вчерне набросать, то будем иметь что-то вроде (сорри за Билдеровский код):


 TMenuItem* MenuItem= new TMenuItem(MainMenu);
  MenuItem->Caption = "File";
  MainMenu->Items->Add(MenuItem);

  MenuItem->Tag = 1; // уникальное число

  MenuItem->OnClick = SharedClickHandler;

void __fastcall TForm1::SharedClickHandler(TObject* Sender)
{ 
TMenuItem* mi = dynamic_cast<TMenuItem*>(Sender); // if(Sender is TMenuItem)
if(mi)
 {
   if(mi->Tag == 1)
    {
     // вызываем одну функцию
    }
   else ....
  

 }
}


Как хранить указатели на функции — дело ваше... Есть масса удобных способов и классов, например, тот-же TList. Удачи!
Re[3]: Динамическое создание событий
От: Sergey Ten http://www.fastalgo.com
Дата: 13.01.03 19:04
Оценка:
Предыдущее по ветке сообщение тоже от меня — забыл залогиниться. Я подумал, что вот так нагляднее и правильнее:


procedure DoOnClick(AFake: TObject; Sender: TObject);
begin
  ShowMessage(Sender.ClassName);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  LHandler: TNotifyEvent;
  P: Pointer;
begin
  P := @DoOnClick;
  Move(P, LHandler, SizeOf(Pointer));

  Button1.OnClick := LHandler;
end;
Re[4]: Динамическое создание событий
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.03 06:26
Оценка: 29 (3)
Здравствуйте, Sergey Ten, Вы писали:
procedure TForm1.FormCreate(Sender: TObject);
var
  LHandler: TNotifyEvent;
  P: Pointer;
begin
  P := @DoOnClick;
  Move(P, LHandler, SizeOf(Pointer));

  Button1.OnClick := LHandler;
end;

Да, так можно делать. Если мы точно не собираемся использовать в нашей процедуре переданный фейковый указатель, то никаких проблем не возникнет. Однако процедура Move выглядит небезопасной. Борланд позаботилась о нас, грешных, объявив в юните SysUtils тип
  TMethod = record
    Code, Data: Pointer;
  end;

Таким образом, можно переписать код вот так:
procedure TForm1.FormCreate(Sender: TObject);
var
  LHandler: TNotifyEvent;
begin
  with TMethod(LPhandler) do
  begin 
    Data:= nil;
    Code:= @DoOnClick;
  end;
  Button1.OnClick := LHandler;
end;
... << RSDN@Home 1.0 beta 3 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Динамическое создание событий
От: Sergey Ten http://www.fastalgo.com
Дата: 14.01.03 06:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

S> Борланд позаботилась о нас, грешных, объявив в юните SysUtils тип

S>
S>  TMethod = record
S>    Code, Data: Pointer;
S>  end;
S>


Согласен, присвоение поприятнее ударной работы по памяти
Re: Динамическое создание событий
От: vasketsov Россия http://ntprog.by.ru
Дата: 14.01.03 08:17
Оценка:
Здравствуйте, GrayWolf, Вы писали:

А функция класса (в смысле, со словом class) не подойдет?
Это если создавать класс не хочется, но зато без извратов.
Васкецов Сергей
http://registry.km.ru
Re[5]: Динамическое создание событий
От: LeXa24  
Дата: 14.01.03 08:31
Оценка: -1
Здравствуйте, vasketsov, Вы писали:

LX>>В общем вот код, пробуй. Все прекрасно работает.

V>Вот так — да, работает, никто и не спорит, а как сначала написал — без объекта — не будет.

Писал не я. Как раз я и написал, что Sender добавить надо!
от модератора
От: _MarlboroMan_ Россия  
Дата: 14.01.03 08:35
Оценка:
Здравствуйте, LeXa24.

Настоятельно рекомендую воздерживаться от избыточного цитирования.
... << RSDN@Home 1.0 beta 4... наслаждаюсь 10 Нейлоновое сердце >>

— сколько программистов надо чтобы заменить сгоревшую лампочку?
— сколько не бери, а лампочку не поменять — проблема аппаратная, программным путем не решается...
Re[6]: Динамическое создание событий
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.03 08:36
Оценка:
LX>Писал не я. Как раз я и написал, что Sender добавить надо!
Будь еще внимательнее! Дело не в Sender.
... << RSDN@Home 1.0 beta 3 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Динамическое создание событий
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.03 08:41
Оценка: 7 (1)
Здравствуйте, vasketsov, Вы писали:

V>А функция класса (в смысле, со словом class) не подойдет?

V>Это если создавать класс не хочется, но зато без извратов.
Увы, создавать класс все же придется. То есть минимальный код для обработки TNotifyEvent такой:
type TDummyHandleClass = class 
  class Procedure HandleIt(Sender: TObject);
end;
class procedure TDummyHandleClass.HandleIt(Sender: TObject);
begin
  ///
end;
... << RSDN@Home 1.0 beta 3 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Динамическое создание событий
От: vasketsov Россия http://ntprog.by.ru
Дата: 14.01.03 13:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Увы, создавать класс все же придется.


Я имел в виду, что это его описание, его накодить надо, а создавать (т.е. Create) его не надо.
Васкецов Сергей
http://registry.km.ru
Re[4]: Динамическое создание событий
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.01.03 13:21
Оценка:
Здравствуйте, vasketsov, Вы писали:
А-а, я просто всегда встаю в тупик, когда начинаются перемешивания классов и объектов. Все верно. создавать не надо объект! В этом плюс — классы не надо потом уничтожать...
... << RSDN@Home 1.0 beta 3 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Динамическое создание событий
От: vasketsov Россия http://ntprog.by.ru
Дата: 14.01.03 13:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А-а, я просто всегда встаю в тупик

Да, это я недостаточно корректно написал, прошу прощения.
Васкецов Сергей
http://registry.km.ru
Re[6]: Динамическое создание событий
От: GrayWolf Россия https://kini24.ru
Дата: 14.01.03 18:03
Оценка:
Честно говоря, вы меня порадовали...
Так все просто... Конечно, это небольшой изврат, но главное, что это работает.
Что впрочем и требуется. Еще бы набрать хоть чуть времени и потестить код, что получилось...
Но все равно, всем спасибо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.