Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2016.07.24;
Скачать: [xml.tar.bz2];

Вниз

Вызов процедуры OnClick из модуля   Найти похожие ветки 

 
azl   (2014-10-17 20:48) [0]

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

Есть форма 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)?

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

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


 
MBo ©   (2014-10-17 22:11) [1]

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


Вызовется метод-обработчик события OnClick, в который в качестве аргумента передаётся то, что в скобках

А зачем это нужно? Подобные ручные вызовы обработчиков - плохой код.

Form1.Button2.Click;
Вызовется метод Click, внутри которого, в частности, вызывается обработчик OnClick, если он был назначен, а аргументом обработчика будет экземпляр кнопки Button2


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

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


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

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


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

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


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

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

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

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

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


 
NoUser ©   (2014-10-18 02:26) [6]

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"?


 
DQ   (2014-10-18 10:31) [7]

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

An a Bad Idea.


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


> Это понятно? и решает твою задачу, или рассказывать про "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 13:48) [9]

Каюсь, в институте тоже так частенько делал. Но теперь понимаю что если "при нажатии одной кнопки вызвался обработчик 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.


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


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

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

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


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


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

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


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

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


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

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


 
azl   (2014-10-18 16:10) [12]


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


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

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


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


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

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


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


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

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

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

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


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

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


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

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


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

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


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

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


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

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


 
kilkennycat ©   (2014-10-19 12:07) [20]

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


 
azl   (2014-10-19 13:04) [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; По сути таймер вместо нас будет кликать эту кнопку.

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

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


 
azl   (2014-10-19 13:08) [22]


> kilkennycat ©

Золотые слова. Абсолютно со всем согласен и добавить нечего. Спасибо большое.

Тут вопрос был даже не в том, как лучше или как правильнее. Просто хотел услышать объяснение для полного понимания.


 
Inovet ©   (2014-10-19 14:14) [23]

Вопрос "что такое send"? Вот что туда поставишь, то и будет вызывателем события, а что с этим делать или не делать, уже решать в обработчике. Вообще Send как раз и нужен, чтобы можно было обратиться к объекту, независимо от текущих имён, от текущего количества объектов на форме и т.п..

Как там его использовать уже зависит от желаний. Может, мне надо просто определить кнопка это или кнопка_с_приделанной_мной_финтифлюшкой - это одно, а, может, я насоздавал динамически (в рантайм) 100 кнопок и присвоил один обработчик, тогда определять буду что за кнопка - это другое, а, може... и пятое, и десятое, и ещё много чего може.


 
Inovet ©   (2014-10-19 15:17) [24]

> [23] Inovet ©   (19.10.14 14:14)
> Send

Sender


 
Германн ©   (2014-10-20 01:44) [25]


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

Не совсем так или совсем не так. Но тут ещё читать и читать в т.ч. справку по TAction. Ибо этот метод появился только с появлением в Делфи акций.


 
azl   (2014-10-20 14:21) [26]


> Не совсем так или совсем не так.


http://delphimaster.net/view/2-1293352804/8

Не совсем так, согласен. Т.к., при неактивной кнопке мышкой ее нажать нельзя, а с помощью этого метода процедура OnClick все равно выполнится.


 
NoUser ©   (2014-10-20 16:10) [27]

> azl   (20.10.14 14:21) [26]

;))))

> Т.к., при неактивной кнопке мышкой ее нажать нельзя,

Вот-вот, именно этого наверное и хотел программист, когда в какой-то момент времени делал кнопку неактивной !

> а с помощью этого метода процедура OnClick все равно выполнится.

А это уже какой-то другой --буратино-- программист, все равно ищет способ проткнуть носом печку, - мол, есть же законный способ сделать это, а вы, господа Мастера, от меня его утаиваете...


 
kilkennycat ©   (2014-10-20 21:15) [28]

Глупости какие. Как может быть связан код внутри обработчика с такими теориямио желаниях программиста и буратинах?

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

И что, писать кучу одинакового, чтоб не быть буратиной?


 
Германн ©   (2014-10-21 02:34) [29]


> kilkennycat ©   (20.10.14 21:15) [28]
>
> Глупости какие. Как может быть связан код внутри обработчика
> с такими теориямио желаниях программиста и буратинах?
>
> Пример: есть некий регулятор температуры (код в обработчике),
>  занимающийся охрененной процедурой нагрева-охлаждения.
> Есть две кнопки, которыми можно вручную нагревать-охлаждать.
>  Они вызывают эту процедуру.
> Есть автоматический режим. Он выключает эти кнопки, но суть
> его действий, что он тоже то одну нажмет, то другую.
>
> И что, писать кучу одинакового, чтоб не быть буратиной?

А что в автоматическом режиме нельзя вызывать некую процедуру "нагрева-охлаждения", не связанную напрямую с нажатием кнопки? И ту же процедуру вызывать при нажатии кнопки?


 
Kilkennycat ©   (2014-10-21 10:58) [30]


> не связанную напрямую с нажатием кнопки? И ту же процедуру
> вызывать при нажатии кнопки?

конечно же можно. ненапрямую. написать функцию, весь смысл которой в вызове другой функции. вот уж не ожидал такого предложения от электронщика ;)


 
Inovet ©   (2014-10-21 11:18) [31]

> [30] Kilkennycat ©   (21.10.14 10:58)

Ну так это правильнее вообще-то, для читаемости.


 
Kilkennycat ©   (2014-10-21 11:55) [32]


> Inovet ©   (21.10.14 11:18) [31]

для читаемости кем? пользователем?


 
Inovet ©   (2014-10-21 17:01) [33]

> [32] Kilkennycat ©   (21.10.14 11:55)
> пользователем?

Собой


 
Kilkennycat ©   (2014-10-21 19:22) [34]

субъективно.


 
Inovet ©   (2014-10-21 20:52) [35]

Общие примеры можно привести. Тот же регулятор температуры.

Температура в баке 98Ц. Работа прораммы:

Ручной режим. Выводим рядом с копкой "+" красную надпись "Максимально допустимая температура". Запрещаем кнопку "+", или при попытке нажатия вежливым поставленным голосом сообщаем "Тепература достигла предела, в целях предотвращения взрывной аварии резервуара, дальнейшее увеличение не было произведено".

Автоматический режим. Выводим рядом с копкой "+" красную надпись "Максимально допустимая температура". При поступлении положительной разности от компаратора, вежливым поставленным голосом сообщаем "Внимание! Неполадки в системе. Возможные причины и способы их устранениня: утечка тепла в следствии открытых окон в зимний период - закройте окна, закрыты технологические вентили на радиаторах - откройте технологические вентили, неисправность предохранителя нагревателя - замените предохранитель, В остальных случаях обратитесь за помощью в авторизированный сервисный центр."

Несколько разные пути у обработчика кнопки и обработчика компаратора.


 
Inovet ©   (2014-10-21 20:55) [36]

> [35] Inovet ©   (21.10.14 20:52)
> неисправность предохранителя нагревателя

"нагреватель" заменить на "регулирующий вентиль".


 
Kilkennycat ©   (2014-10-21 22:05) [37]

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


 
Германн ©   (2014-10-22 01:39) [38]


>  Kilkennycat ©   (21.10.14 10:58) [30]
>
>
> > не связанную напрямую с нажатием кнопки? И ту же процедуру
> > вызывать при нажатии кнопки?
>
> конечно же можно. ненапрямую. написать функцию, весь смысл
> которой в вызове другой функции. вот уж не ожидал такого
> предложения от электронщика ;)

Боюсь ты меня не понял или понял с точностью до наоборот.


 
DQ   (2014-10-22 20:29) [39]

эх... В любом случае если "обработчик кнопок выносить в отдельный модуль, разбивать на отдельные процедуры" то дёргать оттуда обратно за интерфейс....


 
Плохиш ©   (2014-10-23 02:12) [40]

Не только поставить телегу впереди лошади, но ещë и придушить эту кобылу...

Предлагаю внедрить в поделку веб-сервисы, штук надцать, на каждоë дëрганье свой и датаснап, для кучи.


 
Германн ©   (2014-10-23 02:13) [41]


> Плохиш ©   (23.10.14 02:12) [40]

+1
Опоздал со своим ответом. Я хотел предложить несколько другой бред. :)



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2016.07.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.59 MB
Время: 0.007 c
2-1413197845
marlet
2014-10-13 14:57
2016.07.24
Кодировка текста


15-1442241297
timokhasarov
2015-09-14 17:34
2016.07.24
Access ошибка доступа к программе


15-1446150607
картман
2015-10-29 23:30
2016.07.24
сжатие строк


2-1415425555
Signal
2014-11-08 08:45
2016.07.24
Чтение почты через протокол с TLS порт 995


1-1333197347
lord827
2012-03-31 16:35
2016.07.24
как запретить создание файлов в русской раскладке





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский