Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вызов процедуры OnClick из модуля


Страницы:   1 2 3

azl ©   (2014-10-17 20:48:00) 

Здравствуйте, уважаемые мастера.

Есть форма Form1. На форме 2 кнопки. Есть модуль Unit2 (без формы).

unit Unit1;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Test;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ShowMessage('Button2Click');
end;

end.


unit Unit2;

interface

procedure Test;

implementation

uses Unit1;

procedure Test;
begin
 Form1.Button2Click(Form1);
end;

end.


Либо:

unit Unit2;

interface

procedure Test(Sender: TObject);

implementation

uses Unit1;

procedure Test(Sender: TObject);
begin
  Form1.Button2Click(Sender);
end;

end.


Ну и, соответственно, вызов процедуры Test будет таков:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Test(Self);
end;


1. Объясните, пожалуйста, популярно в чем разница между:

Form1.Button2Click(Sender); //Только при условии, что процедура объявлена как: procedure Test(Sender: TObject);
Form1.Button2Click(Form1);
Form1.Button2Click(nil);
Form1.Button2.Click;

2. Есть ли необходимость объявлять, как procedure Test(Sender: TObject)?

Большая просьба просто объяснить. Специально задал вопрос в разделе "Начинающим". Не нужно каких-то ненужных комментариев, типа: А зачем это нужно? А не проще ли...? Ты не понимаешь разницу между..., Ты не знаешь азов... и т.д.

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


azl   (2014-10-19 13:04:00) [21]


> Тут программиста нанимать надо, без вариантов.

Во-первых, тут стоит, прежде всего, почитать главное правило раздела, причем, читать на ночь раз по 10, а потом отвечать:


> Конференция для начинающих, а также для тех, кому сложно
> объяснить чего он хочет. Просьба к участникам быть взаимовежливыми,
>   профессионалам отдельная просьба - быть снисходительными.


Во-вторых, если не можешь объяснить, зачем отвечать? Либо сам не знаешь, либо не можешь объяснить. Я ведь специально заострил на этом внимание, зная, как здесь народ любит сотрясать воздух и делать подобные заявления. Мне не нужно решить конкретную задачу, мне нужно всего лишь четкое понимание использования параметров, что я и попросил объяснить.


> Просто надо понять простую основу: модуль - первичен, а
> форма - вторична.
> Модуль ничего не знает ни о каких формах, а форма знает
> требуемые ей модули.

Вот это уже более конструктивно. Но это и так понятно, суть вопроса совершенно в другом.

Ну и наконец, объяснение-то простое.

Form1.Button2Click(Form1); - аналог использования в модуле с формой Button2Click(Self). В случае с событием OnClick не совсем уместно использовать, поскольку Self - это указание на саму форму. Чтобы понять, что это такое, ссылка на ответ Юзрия Зотова выше. Либо http://www.delphibasics.ru/Self.phpКак параметр для события OnClick это пустой звук. По сути, то же, что и Form1.Button2Click(nil); - не передается никакой параметр.
Если в событии OnClick нет никакой проверки, кто же послал команду, то все выполнится без ошибок, но если такая проверка есть, то результат получим не тот, который ожидаем.

Form1.Button2Click(Sender); - пользовательский обработчик события нажатия кнопки, с возможностью размещения дополнительного кода, который должен быть выполнен при физическом действии пользователя.
Более детально о Sender можно почитать здесь: http://www.delphi-manual.ru/sender.php

Собственно, пример.


> procedure TForm1.Example(Sender: TObject);
> begin
>  if (Sender is TButton) then
>    ShowMessage('Button')
>  else
>    ShowMessage('BitBtn')
> end;
>
> procedure TForm1.BitBtn1Click(Sender: TObject);
> begin
>   Example(Sender);
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   Example(Sender);
> end;


Только при таком обработчике условие в процедуре Example выполнится так, как нам нужно, т.е. появится сообщение о том, какая действительно кнопка была нажата. В случае с Example(Self); Example(Form1); Example(nil); все время будет выполняться ShowMessage('BitBtn'), независимо от того, какая кнопка была нажата.

Ну и наконец Form1.Button2.Click; - метод, предназначенный для программного нажатия кнопки. Например, если нужно много раз нажимать кнопку, скажем, через определенный интервал. Чтобы не делать этого вручную, можно это сделать по таймеру. Указав в обработчике таймера Button2.Click; По сути таймер вместо нас будет кликать эту кнопку.

Вот, собственно, то, что я хотел услышать.

Всем спасибо, тему можно закрывать.


kilkennycat   (2014-10-19 12:07:00) [22]

Делай так, как удобно. Хоть гоу-ту используй. ибо всякие "традиции" программирования не всегда обоснованны чем-то более, чем брякнувшем с похмелья каким-то гуру, что так делать не хорошо, что тут же бездумно подхватили остальные.
Я, например, вообще на все кнопки вешаю один обработчик, в нем свитч от tag кнопки, что позволяет мне ваще особо не заморачиваться с вызовом чего угодно откуда угодно. Мне так удобно. А программы пишутся для пользователей, а не для других программистов. И если мне удобно, пользователям удобно, то остальное несущественно.


Германн   (2014-10-19 02:46:00) [23]

Удалено модератором
Примечание: Не надо обсуждать автора


Плохиш   (2014-10-19 02:13:00) [24]

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


Германн   (2014-10-19 02:12:00) [25]

Удалено модератором
Примечание: конференция для начинающих


Плохиш   (2014-10-19 02:08:00) [26]

Удалено модератором


Плохиш   (2014-10-19 02:07:00) [27]

Тут программиста нанимать надо, без вариантов.


azl   (2014-10-19 01:47:00) [28]


> Этой твоей отдельной процедуре нафиг не нужен этот параметр,
>  раз у тебя работает бредовый код

Да ты что? Правда? А если эта процедура выглядит так:

procedure TForm1.Example(Sender: TObject);
begin
 if (Sender is TButton) then
...
end;

Я ведь ясно написал НЕ НУЖНО КАКИХ-ТО НЕНУЖНЫХ КОММЕНТАРИЕВ.


Германн   (2014-10-19 00:31:00) [29]


> А если у этой отдельной процедуры параметр(Sender: TObject),

Этой твоей отдельной процедуре нафиг не нужен этот параметр, раз у тебя работает бредовый код
Button2Click(Self)


azl   (2014-10-18 16:10:00) [30]


> Многократно используемый код оформляется в отдельные процедуры/функции.


А если у этой отдельной процедуры параметр(Sender: TObject), как ее вызывать из модуля?

procedure TForm1.Example(Sender: TObject);
begin
 //do something;
end;


azl   (2014-10-18 16:07:00) [31]


> Но теперь понимаю что если "при нажатии одной кнопки вызвался
> обработчик OnClick другой кнопки", то это явно плохо продуманная
> архитектура.

Видимо, стоило назвать тему по-другому. Правильнее, наверное, нужно было назвать: " Вызов процедуры с параметром (Sender: TObject) из модуля без формы". Ибо тут соль не в OnClick, а именно в (Sender: TObject)


> И всё же чем вам не угодили Form1.Button2.Click; или Form1.
> Button2Click(Nil);

Я не писал, что они мне не угодили, я спросил в чем разница. И можно было бы еще добавить: в каких случаях, что правильнее использовать?


> А из этого как раз следует что если и делать через это место,
>  то правильнее делать Form1.Button2Click(Form1.Button2);

Это зависит от того, что нужно получить.
Sender - (Form1.Button2)
Self - (Form1)


Плохиш   (2014-10-18 15:41:00) [32]


> Form1.Button2Click(Sender); //Только при условии, что процедура
> объявлена как: procedure Test(Sender: TObject);
> Form1.Button2Click(Form1);
> Form1.Button2Click(nil);
> Form1.Button2.Click;
>

Говнокод, приводящий к ошибке доступа к памяти.

Многократно используемый код оформляется в отдельные процедуры/функции. Хотя, чëй-то я... про азы просили не упоминать.


DQ   (2014-10-18 13:48:00) [33]

Каюсь, в институте тоже так частенько делал. Но теперь понимаю что если "при нажатии одной кнопки вызвался обработчик OnClick другой кнопки", то это явно плохо продуманная архитектура. Впрочем, если это «домашний проект одного программиста»™, может и сойдёт, как хотите.
И всё же чем вам не угодили Form1.Button2.Click; или Form1.Button2Click(Nil); (по умолчанию ж Sender не задействован)?

> Ответ от Юрия Зотова [19]

А из этого как раз следует что если и делать через это место, то правильнее делать Form1.Button2Click(Form1.Button2);

P.S.   https://ru.wikipedia.org/w/index.php?title=Устойчивое_выражение, «Не, не слышал?» (с)
Ближайшее приближение Worst Idea.


azl   (2014-10-18 11:47:00) [34]


> Это понятно? и решает твою задачу, или рассказывать про 'Sender'  и 'Unit2'?

Нет, это не решают мою задачу. Если бы можно было делать именно так, я бы не заморачивался. Выношу код в отдельные модули, чтобы основной модуль не был слишком большим, больше 10000 строк.
Но вывод я уже сделал, что разницы никакой в вызове нет. Одни убеждены, что надо делать так, другие, что по-другому. http://delphimaster.net/view/2-1293352804
Но никто не привел ни одного примера, где бы можно было увидеть, что тот или иной вариант будет работать неправильно в том или ином случае.

Если нужно вызывать процедуру в пределах одного модуля, то я всегда делаю так: Button2Click(Self); Self в данном случае соответствует форме, на которой расположена Button2, например, Form1.
http://www.delphimaster.net/view/1-1080637822Ответ от Юрия Зотова [19]
И это всегда работает без каких либо "но".

Поскольку в отдельном модуле Self не работает, то вместо Self нужно писать имя формы. Например, Form1.Button2Click(Form1);
И это работает. Поэтому, думаю, что тему можно закрывать.


> An a Bad Idea.

Your English is poor. You shouldn't use two indefinite article in a row.


DQ   (2014-10-18 10:31:00) [35]

> при нажатии одной кнопки вызвался обработчик OnClick другой кнопки

An a Bad Idea.


NoUser   (2014-10-18 02:26:00) [36]

azl, если
> важно не само событие нажатия кнопки, а алгоритм
> действий, который закреплен за этой кнопкой.

то
> Чтобы было понятнее, приведу пример.
type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   procedure Raz();
   procedure Dva();
   procedure Tru();
 end;

var
 Danc123: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Raz;
begin
 //Raz-raz-raz
 Dva;
 Tru;
end;

procedure TForm1.Dva;
begin
 Raz;
 //Dva-dva-dva;
 Tru;
end;

procedure TForm1.Tru;
begin
 Raz;
 Dva;
 //Tru-tru-tru;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Raz;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Dva;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 Tru;
end;
end.


Это понятно? и решает твою задачу, или рассказывать про 'Sender' и 'Unit2'?


azl   (2014-10-17 23:22:00) [37]

Чтобы было понятнее, приведу пример.

Есть глобальная переменная, например, perem: integer;

В Unit2 за процедурой закреплено, например, следующее:

procedure Test(Sender: TObject);
begin
with Form1 do
 case perem of
  1: //что-то сделать
  2: //что-то сделать
  ...
  50: Button2Click(Form1);
  ...
  100: //что-то сделать
end;
end;


azl   (2014-10-17 23:14:00) [38]

Не совсем так.
В моем случае существует несколько кнопок, за которыми закреплены какие-то действия в большом количестве (поэтому приходится обработчик этих кнопок выносить в отдельный модуль, разбивать на отдельные процедуры и т.д.).
Так вот, иногда нужно, чтобы при нажатии одной кнопки вызвался обработчик OnClick другой кнопки, которая может быть неактивна.
Т.е., мне важно не само событие нажатия кнопки, а алгоритм действий, который закреплен за этой кнопкой.


MBo   (2014-10-17 23:00:00) [39]

Для чего использовать? Вручную вызвать событие нажатия кнопки?


azl   (2014-10-17 22:53:00) [40]

Спасибо большое за ответ.
Т.е., лучше использовать Form1.Button2.Click; ?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо