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

Вниз

Вызов функции из функции   Найти похожие ветки 

 
Сергей   (2011-01-14 22:08) [0]

Вызов функции из функции

Код такой:

type
 TGetMy = procedure() of object;

function MyFunc1(OnGetMy : TGetMy = nil): Boolean;

 procedure EvOnChange(Self, Sender: TObject);
 begin
   if Assigned(OnGetMy) then OnGetMy(); // Âòîðîé âûçîâ.
 end;

var
 Form : TForm;
 EvChange : TMethod;
begin
 if Assigned(OnGetMy) then OnGetMy(); // Ïåðâûé âûçîâ.
 Form := TForm.Create(Application);
 with Form do begin
   with TEdit.Create(Form) do begin
     Parent := Form;
     EvChange.Code := @EvOnChange;
     OnChange := TNotifyEvent(EvChange);
   end;
   // ...
 end;
end;


Проблема в том, что первый вызов OnGetMy проходит, а второй из функции EvOnChange вызывает ошибку Дельфи. Вопрос, как сделать вызов правильно, чтобы ошибки не возникало?


 
Сергей М. ©   (2011-01-14 22:33) [1]


> procedure EvOnChange(Self, Sender: TObject);


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


 
Сергей   (2011-01-14 23:39) [2]


> Сергей М. ©   (14.01.11 22:33) [1]
>
> > procedure EvOnChange(Self, Sender: TObject);
>
> А это к чему такие выкрутасы с попыткой выдать регул.процедуру
> за метод класса ?


Знаете другой способ сделать то же самое?


 
sniknik ©   (2011-01-15 00:15) [3]

> сделать то же самое?
сильно сомневаюсь в необходимости этого (задачи как таковой кроме "сделать изврат" нет), но например ...
type
 TMyClass = class
   procedure Change(Sender: TObject);
 end;

procedure TMyClass.Change(Sender: TObject);
begin
 ShowMessage("Event Change");
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Form: TForm;
begin
 Form:= TForm.Create(Application);
 with TEdit.Create(Form) do begin
   Parent  := Form;
   OnChange:= TMyClass(nil).Change;
 end;
 Form.ShowModal;
end;


 
sniknik ©   (2011-01-15 00:19) [4]

или (чтобы не смущать народ странными привидениями типов) так -
type
 TMyEdit = class(TEdit)
   procedure Change(Sender: TObject);
 end;

procedure TMyEdit.Change(Sender: TObject);
begin
 ShowMessage("Event Change");
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Form: TForm;
begin
 Form:= TForm.Create(Application);
 with TMyEdit.Create(Form) do begin
   Parent  := Form;
   OnChange:= Change;
 end;
 Form.ShowModal;
end;


 
Сергей   (2011-01-15 00:33) [5]


> <Цитата>
>
> sniknik ©   (15.01.11 00:15) [3]
>
> > сделать то же самое?
> сильно сомневаюсь в необходимости этого (задачи как таковой
> кроме "сделать изврат" нет), но например ...
> type
>  TMyClass = class
>  
>  procedure TForm1.Button1Click(Sender: TObject);


Если бы у бабушки была TForm1, то она была бы дедушкой.

Впрочем это всё оффтоп.

Может ли кто-нибудь ответить на вопрос из первого постинга?


 
sniknik ©   (2011-01-15 00:42) [6]

> была TForm1
ну так убери, к коду тут оно никакого отношения не имеет. считай, что не кнопка не нажимается, а делается вызов регулярной процедуры.
код читать то умеешь?

> ответить на вопрос из первого постинга?
ну, как бы отвечено уже, ошибок не возникает.


 
sniknik ©   (2011-01-15 00:50) [7]

> код читать то умеешь?
чтобы не напрягать твой ум....  TForm1 нет.
program Izvrat;

{$APPTYPE CONSOLE}

uses
 SysUtils, Dialogs, Forms, StdCtrls;

type
 TMyClass = class
   procedure Change(Sender: TObject);
 end;

procedure TMyClass.Change(Sender: TObject);
begin
 ShowMessage("Event Change");
end;

var
 Form: TForm;
begin
 Form:= TForm.Create(Application);
 with TEdit.Create(Form) do begin
   Parent  := Form;
   OnChange:= TMyClass(nil).Change;
 end;
 Form.ShowModal;
end.


 
Сергей   (2011-01-15 01:05) [8]


> sniknik ©   (15.01.11 00:50) [7]
>
> > код читать то умеешь?
> чтобы не напрягать твой ум....  TForm1 нет.


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


> sniknik ©   (15.01.11 00:50) [7]
>  TMyClass = class
>    procedure Change(Sender: TObject);
>  end;


Меня НЕ интересует TMyClass.

Меня НЕ интересует вопрос как наплодить не нужные мне классы. Также как и вопрос о том, сколько будет один плюс один, два плюс два и тому подобные.


> procedure TForm1.Button1Click(Sender: TObject);


Меня НЕ интересует никакая TForm1. А равно и все другие формы.

Меня НЕ интересует миллион других вопросов.

На данный момент интересует только один вопрос, как правильно осуществить вызов из примера в первом постинге.


 
Германн ©   (2011-01-15 01:30) [9]


> чтобы не смущать народ странными привидениями

Да. Не надо смущать народ привидениями. К тому же они и не так страшны, как их малюют. :)


> Сергей   (14.01.11 22:08)  

Тёзка, читай эту основополагающую статью до полного просветления!
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=342
И тогда никаких извратов не потребуется.


 
sniknik ©   (2011-01-15 02:04) [10]

> как наплодить не нужные мне классы.
описание типа это не класс... в смысле, не физический объект занимающий место. наплодить описаниями нельзя, зато, описанием можно представить одни и те же данные в разной интерпретации, что позволяет избежать бессмысленного перекладывания этих самых данных с места на место, только ради того, чтобы чему то что то присвоить (к тому же проигнорировав "лишнее").

> Меня НЕ интересует никакая TForm1. А равно и все другие формы.
как же так, а твой пример в [0]? без "других форм" не потребовалось бы "присобачивать" регулярную процедуру методу класса.
т.е. это твое утверждение лишает последнего смысла сам вопрос.

> как правильно осуществить вызов из примера в первом постинге.
легко, честное слово легко, но хотелось бы знать цель, а не исправлять бредовый способ под "неведому зверушку"...


 
Amoeba_   (2011-01-15 02:09) [11]

Автору вопроса:
http://www.gunsmoker.ru/2008/10/x-y-z.html

P.S. Тонкий намек на толстые обстоятельства.


 
sniknik ©   (2011-01-15 02:13) [12]

> Тёзка, читай эту основополагающую статью до полного просветления!
просветление вряд ли наступит, ведь там нет ответа "как сделать вызов правильно" в его коде... а все остальное, в том числе и относительно правильный код, его не интересует.


 
Германн ©   (2011-01-15 02:22) [13]


> sniknik ©   (15.01.11 02:13) [12]
>
> > Тёзка, читай эту основополагающую статью до полного просветления!
>
> просветление вряд ли наступит, ведь там нет ответа "как
> сделать вызов правильно" в его коде... а все остальное,
> в том числе и относительно правильный код, его не интересует.
>

Ну "Надежда" всегда остаётся последней. Так может быть автор всё-таки просветлеет?


 
Сергей   (2011-01-15 16:52) [14]

Похоже непреодолимый смысловой преобразователь продолжает работать, работать, работать ...


> Amoeba_   (15.01.11 02:09) [11]
>
> Автору вопроса:
> http://www.gunsmoker.ru/2008/10/x-y-z.html


В ход пошли саги. Пытаясь осуществить обратное смысловое преобразование, сея сага означает, что ответа на вопрос из первого постинга, как осуществить нужный вызов у вас нету. :)


> Германн ©   (15.01.11 01:30) [9]
>
> > Сергей   (14.01.11 22:08)  
>
> Тёзка, читай эту основополагающую статью до полного просветления!
>
> http://www.delphikingdom.com/asp/viewitem.asp?catalogid=342


Опять TForm1, TForm1, TForm1.
В постинге [8], тёзка, я сообщил, что меня не интересует TForm1, а также никакие лишние классы. Сколько можно вываливать эти детсадовские примеры как создать TButton или TMyClass?

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

Это вам не TButton на TForm1 создавать.


 
sniknik ©   (2011-01-15 17:07) [15]

> как осуществить нужный вызов у вас нету. :)
зато есть сомнения в нужности самого "нужного вызова".

> эти детсадовские примеры как создать TButton или TMyClass?
эти детсадовские примеры - основа ООП. либо следуй либо не используй.

> в данной конкретной ситуации
в данной конкретной ситуации способ простой, не использовать локальную (стековую) переменную при вызове ее в кода в другом месте. а сохранить ее где нибудь в доступном из обоих мест месте, например.
(говорил же просто)

> а не в миллионе других ситуаций
т.е. зацикливаться на кривом методе решения, вместо того чтобы достичь цели миллионом других методов? цель подменена средством.

> Это вам не TButton на TForm1 создавать.
а ты так нифига и не понял.


 
имя   (2011-01-15 20:00) [16]

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


 
sniknik ©   (2011-01-15 20:50) [17]

> (если же параметров будет больше, или спецификация вызова будет другой, параметры могут передаваться через стек
все правильно, но не смертельно... в дельфи в процедурах делается восстановление состояния указателей, и потому параметром больше параметром меньше, "ерунда, дело житейское" (© Карлсон который живет на крыше)... а иначе бы были невозможны процедуры с открытым списком.
т.е. если к нему не обращаться то неважно, что он "мусорный" (кусок Data метода у него не инициализирован, но и обращения к self нет).

но вот то, что адрес/параметр остались в стеке, т.е. суть локальные, а вызов внешний по отношению к ним,  вот это уже гарантированное AV.

насчет спецификаций ... + похоже параллельный ответ "делающему монстра", ну пофиг.
возьми его код, и замени  
 EvChange.Code := @EvOnChange;
 OnChange := TNotifyEvent(EvChange);
на
 OnChange := TNotifyEvent(OnGetMy); (сохраним переменную собственно в объекте)
и все будет работать (если конечно OnGetMy передана извне, и это адрес "внешней" процедуры, а не такой же локальной).
работает, хотя, при вызове метода 2 параметра Self, Sender, а процедуры объекта только 1 Self. (т.е. лишний не мешает)

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

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


 
DiamondShark ©   (2011-01-15 23:50) [18]

Поциэнт хочет вызвать вложенную процедуру как процедуру верхнего уровня?
При этом стучит ложкой и огрызается на медперс-анал?
Вколите ему кто-нибудь два кубика эвтаназепама.


 
Германн ©   (2011-01-16 04:07) [19]


> В постинге [8], тёзка, я сообщил, что меня не интересует
> TForm1, а также никакие лишние классы. Сколько можно вываливать
> эти детсадовские примеры как создать TButton или TMyClass?
>
>

В постинге [8] кроме очевидного бреда "недоучки" ничего нет!

Но в посте [0] присутствует Form : TForm;
И на этой форме создаются компоненты типа TEdit. Создаются в рантайме, очевидно. Но без всякого понимания что и как нужно делать! А статьи читать - не барское дело!
P.S. Троешники идут лесом!


 
Юрий Зотов ©   (2011-01-16 08:46) [20]

А ответ на вопрос "как правильно осуществить вызов из примера в первом постинге" все же имеется.

Отвечаю: правильно - никак. Правильно - переработать структуру кода так, чтобы не приходилось делать неправильное.


 
Юрий Зотов ©   (2011-01-16 09:06) [21]

Но если уж очень сильно хочется, то:
1. Вложенную процедуру сделать внешней.
2. Назначить EvChange.Data (ссылка на объект, чье событие надо назначить).

Только это все равно неправильно. Правильно - так не делать.


 
Юрий Зотов ©   (2011-01-16 09:55) [22]


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

var
 M: TMethod;

procedure TForm1.FormCreate(Sender: TObject);
var
 Edit: TEdit;
begin
 Edit := TEdit.Create(Self);
 Edit.Parent := Self;
 M.Code := @Proc;
 M.Data := Edit;
 Edit.OnChange := TNotifyEvent(M)
end;


 
DiamondShark ©   (2011-01-16 19:04) [23]


> Юрий Зотов ©   (16.01.11 09:55) [22]

Вы сами свой пример не запускали.


 
sniknik ©   (2011-01-16 19:30) [24]

> Вы сами свой пример не запускали.
почитай выше, о разнице между 1 и 2мя  переменными ([17]). + подумай, какая разница как переменную обозвать. не, конечно неплохо называть однотипно, но для компа это просто адрес в памяти, а название self или sender он не разбирает (если его не "обучить" конечно, типа RTTI).

кстати сам попробуй, а после того как сработает убери значение из M.Data := Edit;. поставь там nil, и вот тогда... бяда бяда. ;)


 
DiamondShark ©   (2011-01-16 20:04) [25]


> подумай, какая разница как переменную обозвать.

Подумай, какая разница, дать корректный код, или глюкопотенциальную фигню.

Если прототип "procedure Proc" написать корректно, то код будет просто работать корректно всегда.
А так надо помнить, что, благодаря модели "register", вызов с неправильной сигнатурой не портит стек.
Ну, по крайней мере, при двух аргументах не портит.
Ну, в текущей версии компилятора, точняк не портит.
Ну, в том объекте, кому мы делегат навешиваем, точно нет фигни, вроде

property OnChange : TNotifyEvent; read GetOnChange; write SetOnChange;

function TMyCrazyObject.GetOnChange
begin
 Result := FInnerObject.OnChange;
end;

procedure TMyCrazyObject.SetOnChange
begin
 FInnerObject.OnChange := value;
end;


 
Юрий Зотов ©   (2011-01-16 20:08) [26]


> DiamondShark ©   (16.01.11 19:04) [23]

О, великий Гуру, вот здесь:
http://webfile.ru/5056135
Вы найдете исходник, экзешник и скриншот.

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

LOL


 
DiamondShark ©   (2011-01-16 20:15) [27]


> Юрий Зотов ©   (16.01.11 20:08) [26]

Да в пень мне тот исходник, экзешник и скриншот.

Вы лучше объясните, из каких побуждений вы использовали некорректную сигнатуру процедуры?
Хотели отучить ТС от копипасты (еретической мысли, что забыли про селф, я разумеется, не допускаю)?


 
Ega23 ©   (2011-01-16 20:31) [28]


> из каких побуждений вы использовали некорректную сигнатуру
> процедуры?

Сфигали она некорректная?
З.Ы. У тебя точно перманентный ПМС.


 
DiamondShark ©   (2011-01-16 20:51) [29]


> Ega23 ©   (16.01.11 20:31) [28]
> Сфигали она некорректная?

С того, что type TNotifyEvent = procedure (Sender: TObject) of object
У этой сигнатуры два параметра: неявный Self и явный Sender.

З.Ы. У тебя перманентный ФГМ.


 
Ega23 ©   (2011-01-17 00:18) [30]


> У этой сигнатуры два параметра: неявный Self и явный Sender.

M.Code := @Proc;
M.Data := Edit;


З.Ы. ЛМД.


 
DiamondShark ©   (2011-01-17 00:30) [31]


> Ega23 ©   (17.01.11 00:18) [30]

Ты пьян, что-ли?
Попробуй сформулировать по-русски, что за мысль ты собирался донести своей многозначительной копипастой?


 
Servy ©   (2011-01-17 00:40) [32]

По-моему, DiamondShark вполне резонно отмечает, что если код из [22] дополнить например таким образом:


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

var
M: TMethod;

procedure TForm1.FormCreate(Sender: TObject);
var
 Edit: TEdit;
 Memo: TMemo;
 Button: TButton;
begin
 Edit := TEdit.Create(Self);
 Edit.Parent := Self;
 M.Code := @Proc;
 M.Data := Edit;
 Edit.OnChange := TNotifyEvent(M);

 Memo := TMemo.Create(Self);
 Memo.Parent := Self;
 Memo.Top := 30;
 Memo.OnChange := TNotifyEvent(M);
end;


То он будет показывать "TEdit" для обоих компонентов, тогда как, по всей видимости Sender"ом у второго компонента должно быть TMemo. Засим, код из [22] видимо очень неправильный :).

Единственный вопрос в том, специально ли Юрий Зотов поставил вместо Self - Sender и опустил второй параметр, или это была трагическая случайность, сделавшая код из [22] еще неправильнее, чем планировалось им изначально.


 
Ega23 ©   (2011-01-17 01:10) [33]


> То он будет показывать "TEdit" для обоих компонентов, тогда
> как, по всей видимости Sender"ом у второго компонента должно
> быть TMemo.

Он будет показывать ровно то, что должен показывать. Задачи, чтобы это был полноценный TNotifyEvent не было.
Не далее как в четверг как раз такую штуку реализовывал. Но с процедурой мне не понравилось, сделал тупо

TDummyClass = class (TObject)  
public
 class procedure Proc(Sender: TObject);
end;


 
DiamondShark ©   (2011-01-17 01:26) [34]


> Он будет показывать ровно то, что должен показывать.

Может ты расскажешь, что он должен показывать? Ну, т.е. как ты задачу понял?


 
sniknik ©   (2011-01-17 01:37) [35]

> То он будет показывать "TEdit" для обоих компонентов, тогда как, по всей видимости Sender"ом
> у второго компонента должно быть TMemo. Засим, код из [22] видимо очень неправильный :).
вообще то он не правильный вовсе не поэтому. а потому, что у метода обычно 2 параметра, и описывать регулярку под метод стоило бы не так
procedure Proc(Sender: TObject);
а так
procedure Proc(Self, Sender: TObject);
и все. ничего более.
что "сдвигает" параметр, а не меняет их местами из-за имени. т.е. ну, чтобы вам было привычнее напишите так
procedure Proc(Self: TObject);
а, второй там просто не используется, и возможности его вызвать с ним тоже нет (без извращений с приведением типа). т.е. ошибок из-за этого тоже не будет.

т.что то, что ты инкриминируешь "у второго компонента должно быть TMemo" неверно, не должен, а есть и будет именно TMemo, но только "за кадром" во втором не присутствующем, а в Self передается из Data куда мы/ты его сам поместил. т.е. ССЗБ в этом случае.

ты что думаешь, ты тут воздухом дышишь? © Морфей из матрицы.
вы как начинающий Нео, привязываетесь к именам... а они не существенны. компьютеру на них начхать, они только для нас.


 
DiamondShark ©   (2011-01-17 01:51) [36]


> sniknik ©   (17.01.11 01:37) [35]

Вообще-то, если решать задачу замены метода на регулярную процедуру, то логично было бы терять/игнорировать именно Self, а не явные параметры.

Но, поскольку Self первый, то "красиво" потерять его не получится. Остаётся только описать и проигнорировать.
Ну и для чистоты концепции неплохо бы передавать в Self именно nil, а не бессмысленную ссылку на объект, Self-ом не являющийся.


 
Германн ©   (2011-01-17 01:58) [37]


> Вообще-то, если решать задачу

А нужно ли решать эту задачу в "Начинающим"?
Да ещё и разводить теоретический спор на тему этой задачи?
Сам сабж - бредовый. X-Y-Z


 
Servy ©   (2011-01-17 02:02) [38]


> что "сдвигает" параметр, а не меняет их местами из-за имени.
>  т.е. ну, чтобы вам было привычнее напишите так
> procedure Proc(Self: TObject);


Я бы и написал Self, и второй параметр там оставил. Но Юрий Зотов написал там именно Sender. Таким образом, новичок бы логично предположил, что туда передается именно Sender. В коде [22] разницы нет, так как Sender = Self, поэтому я привел другой пример в [32], где Sender и Self различаются. Соответственно, возникает вопрос, намеренно ли в [22] написан Sender (и если так, то зачем, ветка то для начинающих), или это ошибка, которую следует поправить.

Злобный буратино то не я, а автор кода. Я лишь продемонстрировал, что в Sender"е оказывается совсем не Sender, что должно было навести на некоторые мысли доблестного защитника кода из [22], который уверен, что в никаких проблем с сим кодом не наблюдается.

Ваши объяснения того, что происходит мне не были нужны, однако надеюсь пригодятся кому-нибудь из начинающих.


 
sniknik ©   (2011-01-17 02:06) [39]

> если решать задачу замены метода на регулярную процедуру
я вообще то изначально был против ее решать... проще/лучше описать типом/классом (что ни добавляет ни байта к коду), чем составлять "вручную" в коде, и утяжелять его.
посмотри примеры [3], [4].
> Ну и для чистоты концепции неплохо бы передавать в Self именно nil, а не бессмысленную ссылку на объект, Self-ом не являющийся.
почему это она бессмысленная? раз объект существует (обьект Edit создали? создали) то есть (должна быть раз предусмотрена) и ссылка на него, но если хочешь добавь в любой пример ([3], [4])  слово class перед procedure и "цель" достигнута.


 
sniknik ©   (2011-01-17 02:09) [40]

> Self-ом не являющийся.
или имеется в виду второй случай с Memo? ну так бысмысленным сделал его тот кто вручную составлял и составил неправильно, дал Mem-У Edit. ССЗБ.



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

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

Наверх





Память: 0.58 MB
Время: 0.004 c
15-1294912978
Андрей123
2011-01-13 13:02
2011.04.24
Подключение IP-камеры к телевизору


15-1292834915
12
2010-12-20 11:48
2011.04.24
Как существует Антиматерия or Где хранить всепрожигающую киcлоту?


15-1294596688
@!!ex
2011-01-09 21:11
2011.04.24
PropSheet не работает под Win 7 x64


6-1191246733
__Unnamed__
2007-10-01 17:52
2011.04.24
Вопрос про сокеты, а точнее про FD_CLOSE и FD_READ


2-1295032117
Сергей
2011-01-14 22:08
2011.04.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
Английский Французский Немецкий Итальянский Португальский Русский Испанский