Форум: "Начинающим";
Текущий архив: 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