-
Возникла потребность разрушить визуальный объект, когда на нём сделали двойной щелчок. Пытаюсь разрушать в обработчике OnDblClick - ничего хорошего из этого не получается. Как такое поведение можно корректно реализовать?
-
По двойному щелчку меняешь флаг.
В событии "смена флага" дестроишь объект.
:)))
Тупо, но сработает, наверное.
-
Лучше так не делать.
-
>В событии "смена флага" дестроишь объект.
Понятно, что на худой конец можно и таймер повесить. Но - опять же - лучше так не делать. Пока не могу придумать как по-другому.
-
> Как такое поведение можно корректно реализовать?
через PostMessage послать сообщение владельцу объекта - разрушь меня
-
> через PostMessage послать сообщение владельцу объекта -
> разрушь меня
Вот это интересно. Спасибо, попробую.
-
It works :) Спасибо еще раз.
-
> Дмитрий Белькевич (15.02.10 19:02) [6]
>
> It works :)
Сей способ должен был быть выучен ещё в детском саду. Ибо он - единственный способ "разрушить" объект из метода "этого самого объекта".
-
Токмо в [4] есть маленькая ошибка. В терминологии.
Примите и прочь. :)
-
Странно. Я в обработчике OnExit объекта успешно разрушаю этот объект.
-
> Германн © (16.02.10 02:16) [7]
>
>
> Ибо он - единственный способ "разрушить" объект из метода
> "этого самого объекта".
Да ладно. Как насчет метода Free ?
-
> Вася (17.02.10 13:59) [10]
> Да ладно. Как насчет метода Free ?
Не с каждым объектом прокатит.
-
Этот вопрос описан в книге Григорьева. Всё очень просто.
const WM_HARAKIRI = WM_USER + 1; //Определили новое сообщение.
А у окна, которому принадлежит Ваш объект, определяем обработчик сообщений, который и будет убивать объект.
procedure WMHarakiri(var Msg: TMessage); message WM_HARAKIRI;
procedure TMainForm.WMHarakiri(var Msg: TMessage);
var
HappilessObj: THappilessObj; //Переменная типа убиваемого объекта
begin
HappilessObj := THappilessObj(Msg.wParam); //Привели тип
HappilessObj.Free; //И убили
end;
//А теперь в обработчике двойного щелчка пишем
SendMessage(
Handle, //Handle окна, которое и убъёт компонент
WM_HARAKIRI, //Само сообщение
Integer(Sender), //Указатель на убиваемый объект
0
);
Этот способ хорош по двум причинам:
1) Он "взрослый", а не с таймером.
2) Можно убивать не один, а много объектов одного класса или даже разных классов, во втором случае вместо нуля передавать число, идентифицируещее класс.
-
> SendMessage(
PostMessage
-
> TStas (17.02.10 17:25) [12]
> Этот вопрос описан в книге Григорьева. Всё очень просто.
>
> const WM_HARAKIRI = WM_USER + 1; //Определили новое сообщение.
>
>
> А у окна, которому принадлежит Ваш объект, определяем обработчик
> сообщений, который и будет убивать объект.
Этот способ не является стопроцентным решением. Несложно написать контрпример, в котором этот пример даст сбой.
Например достаточно просто перекрыть Tobject.Dispatch в наследнике котором дополнительно логировать часть сообщений после обработки сообщений.
Или создать каскад обработчиков сообщений в котором после обработки идет обращение к объекту.
Местом где нет сообщений и они находятся не в каскаде является onIdle.
Я бы предложил зацепиться за Application.OnIdle
-
oxffff © (17.02.10 21:40) [14]
Несложно сделать веревку достаточной длины, чтобы выстрелить себе в ногу. Только зачем ?
-
> Игорь Шевченко © (17.02.10 21:42) [15]
> oxffff © (17.02.10 21:40) [14]
>
> Несложно сделать веревку достаточной длины, чтобы выстрелить
> себе в ногу. Только зачем ?
Вечер добрый.
У решения есть очевидные недостатки, почему нельзя просто указать на них?
И тем более предложив более безопасное решение, но возможно не окончательное?
Что плохого в поиске самого refine решения?
-
oxffff © (17.02.10 21:52) [16]
Добрый вечер. В случае необходимости уничтожения объекта из собственного обработчика идеального решения не существует, существует только тот или иной набор костылей. Я не вижу смысла расширять этот набор костылей сверх необходимости, и, соответственно, усложнять процедуру уничтожения объекта иначе как попросить владельца уничтожить объект. Если у кого-то что-то перекрыто, то не обращаться в перекрытом к уничтоженному объекту будет гораздо проще.
-
> Игорь Шевченко © (17.02.10 22:21) [17]
Так и с Вами согласен.
Собственно я и сам не всегда стремлюсь к идеалам и в местах где запас не нужен обхожусь без него. Я так понимаю участники форума предлагают решения а уж задача вопрошающего выбрать себе нужный размер. :))
Собственно если и в предложенном мною решении кто-то найдет ошибку.
Я только рад буду, поскольку буду знать где он не сработает и будет предложено(возможно найдено сообща) более refine решение. От этого все выграют. Одна голова хорошо, а две лучше.
-
> Вася (17.02.10 13:59) [10]
> Как насчет метода Free ?
Ответ приведён в сообщении автора [0]
-
> oxffff © (17.02.10 21:52) [16]
>
>
> > Игорь Шевченко © (17.02.10 21:42) [15]
> > oxffff © (17.02.10 21:40) [14]
> >
> > Несложно сделать веревку достаточной длины, чтобы выстрелить
> > себе в ногу. Только зачем ?
>
>
> Вечер добрый.
> У решения есть очевидные недостатки, почему нельзя просто
> указать на них?
> И тем более предложив более безопасное решение, но возможно
> не окончательное?
Зачем в ответе на простой вопрос искать слишком сложное решение, если есть решение простое, пригодное в большинстве случаев?
-
> Германн © (18.02.10 01:29) [20]
Попробую ответить :)
Если бы Вы заметили дефект, который может привести к сложностям у невнимательных(не утруждающих себя деталями) потребителей(но эти потребители "ездят" на одной с Вами марки средства) Вы бы промолчали? Это человечно? :)
-
> oxffff © (18.02.10 01:41) [21]
>
>
> > Германн © (18.02.10 01:29) [20]
>
>
> Попробую ответить :)
> но эти потребители "ездят" на одной с Вами марки средства
Попробуй.
Я "езжу" на марке, в которой ничего не "перекрыто". То бишь (в рамках форума), стандартные компоненты Дельфи. И большинство тоже ездят на ней.
-
> Германн © (18.02.10 01:49) [22]
>
> > oxffff © (18.02.10 01:41) [21]
> >
> >
> > > Германн © (18.02.10 01:29) [20]
> >
> >
> > Попробую ответить :)
>
>
> > но эти потребители "ездят" на одной с Вами марки средства
>
> Попробуй.
> Я "езжу" на марке, в которой ничего не "перекрыто". То бишь
> (в рамках форума), стандартные компоненты Дельфи. И большинство
> тоже ездят на ней.
Отлично. Но Вас это обяжет описать обработку сообщения по удалению корректным образом у наследников ваших компонентов и может сильно стеснять их. И грубо говоря можете зависить от версий библиотеки. Поскольку потенциально никто не запрещает изменить библиотеку VCL под новые возможности внутреннего устройства языка(хотя по возможности они этого избегают).То есть вынудить совершать Вам излишние дополнительные усилия. Зачем?
Если вы просто скрываете объект и добавляете его в очередь на удаление, а объект фактически удаляется в момент простоя приложения. Вы можете удалять из очереди частями размазав на больший интервал времени. И отдать приложению драгоценные такты(ведь компоненты разные бывают в общем виде).
-
> Отлично. Но Вас это обяжет описать обработку сообщения по
> удалению корректным образом у наследников ваших компонентов
Ну не обяжет это меня! Ну как ты не понимаешь!
Какие наследники?
См. Игорь Шевченко © (17.02.10 22:21) [17]
Пусть ИШ отдувается. :)
-
> Германн © (18.02.10 02:15) [24]
>
> > Отлично. Но Вас это обяжет описать обработку сообщения
> по
> > удалению корректным образом у наследников ваших компонентов
>
> Ну не обяжет это меня! Ну как ты не понимаешь!
> Какие наследники?
> См. Игорь Шевченко © (17.02.10 22:21) [17]
> Пусть ИШ отдувается. :)
Классы наследники Ваших компонентов, а не Ваши наследники. :)
ИШ отдуваться не в чем. Представлено два решения.
Посетители сами определятся с решением, а может предложат свое.
-
> Классы наследники Ваших компонентов, а не Ваши наследники.
> :)
Ух её моё. А в где в сабже речь шла о наследниках каких-то компонент?
Я не в праве отнять значек (голубой).
Но ты рискуешь его потерять!
-
> Германн © (18.02.10 02:46) [26]
>
> > Классы наследники Ваших компонентов, а не Ваши наследники.
>
> > :)
>
> Ух её моё. А в где в сабже речь шла о наследниках каких-
> то компонент?
Может внимательнее посмотреть мой пост [14].
P.S.
Я собственно слежу за этой темой давно (как и за многими другими мне потенциально интересными) и специально не высказывался поскольку автора темы устроил вариант решения.
Но позже была приведена ссылка на решение из книге в общем виде.
На нее я и отреагировал указав на возможные проблемы.
По остальной части поста [25] без комментариев.
-
> ffff © (18.02.10 03:04) [27]
>
>
> > Германн © (18.02.10 02:46) [26]
> >
> > > Классы наследники Ваших компонентов, а не Ваши наследники.
>
> >
> > > :)
> >
> > Ух её моё. А в где в сабже речь шла о наследниках каких-
>
> > то компонент?
>
>
> Может внимательнее посмотреть мой пост [14].
>
> P.S.
>
> Я собственно слежу за этой темой давно (как и за многими
> другими мне потенциально интересными) и специально не высказывался
> поскольку автора темы устроил вариант решения.
> Но позже была приведена ссылка на решение из книге в общем
> виде.
Ну и зря отреагировал. :)
Кстати. Могу процитировать советского классика журналистики.
-
> Германн © (18.02.10 03:19) [28]
Есть общие решения одни, а есть общие решения корректные.
-
> Германн ©
Обычно людям проще применить доступное им решение.
И потом невдумываясь в различия применять это решение налево и направо(как повторно используемый код). Это мина замедленного действия.
Я не упрекаю ИШ и АГ (более того я не совмеваюсь в их профессионализме при решении с теми подводными камнями).
Но форум читают(и студенты бездумно берут решения налево и направо, потом вырастают и тиражируют себе подобных). Потом идут работать.
Я с этим сталкиваюсь постоянно, и понимаю что люди поверхностно представляют себе вообще что происходит в их программе или более того вообще не правильно представляют. И от этого становится грустно.
Но это пройдет.
-
> Я с этим сталкиваюсь постоянно, и понимаю что люди поверхностно
> представляют себе вообще что происходит в их программе или более того
> вообще не правильно представляют. И от этого становится грустно.
+1
-
> Плохиш © (18.02.10 00:54) [19]
> DVM © (17.02.10 15:02) [11]
>
>
Я имел в виду, что если мы посмотрим реализацию метода Free, мы увидим ,что оказывается можно разрушить объект, находясь внутри его метода непосредственно вызовом деструктора.
А Германн утверждает в [7], что единственный способ - через PostMessage
-
> Вася (18.02.10 10:36) [32]
> Я имел в виду, что если мы посмотрим реализацию метода Free,
> мы увидим ,что оказывается можно разрушить объект, находясь
> внутри его метода
Вообще-то здесь речь идёт о разрущении объекта в обработчике его событий.
-
oxffff © (18.02.10 03:48) [30]
> Я с этим сталкиваюсь постоянно, и понимаю что люди поверхностно
> представляют себе вообще что происходит в их программе
> или более того вообще не правильно представляют. И от этого
> становится грустно.
Поддерживаю.
Но может пусть пока начнут представлять с относительно простых вещей (типа нотификации через PostMessage), а после уже и до перекрытых методов Dispatch (if any) дойдут.
И кстати, вопрос к владельцам книги Антона Григорьева - там действительно написано так, как в посте [12] ?
-
> [34] Игорь Шевченко © (18.02.10 12:11)
> И кстати, вопрос к владельцам книги Антона Григорьева - там действительно написано так, как в посте [12] ?
Если я нашла именно то место, что имеется ввиду, то нет.
Основные отличия:
1. PostMessge, а не SendMessage (с подробным объяснением почему именно так, кстати)
2. Большое дополнение, обясняющее в каких случаях данный метод не работает,
вместе с резюме "Общих решений таких проблем, по видимому не существует"
-
> [35] Riply © (18.02.10 13:17)
> Если я нашла именно то место, что имеется ввиду, то нет.
Глава 1.2.6 Листинг 1.33
-
> Riply © (18.02.10 13:21) [36]
А объяснения с Application.ProcessMessages и/или диалогом есть?
--
Regards, LVT.
-
> [37] Leonid Troyanovsky © (18.02.10 13:26)
> А объяснения с Application.ProcessMessages и/или диалогом есть?
С Application.ProcessMessages есть.
Там много (более трех страниц посвещено этому вопросу) - долго все перепечатывать.
Sorry.
-
> Riply © (18.02.10 13:34) [38]
> Sorry.
Да чего там :)
В свое время наобсуждались.
--
Regards, LVT.
-
> Riply © (18.02.10 13:17) [35]
> вместе с резюме "Общих решений таких проблем, по видимому
> не существует"
Мы тут как-то не очень давно с ИШ обсуждали похожую тему,
и я предлагал примерно такой вариант, во многом свободный от
недостатков PostMessage:
type
EForceFreeException = class(Exception)
private
DestroyedObject: TObject;
function This: EForceFreeException;
end;
function EForceFreeException.This;
begin
Result := Self;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
with EForceFreeException.Create('Free: '+(Sender as TButton).Caption) do
begin
DestroyedObject := Sender;
raise This;
end;
Application.ProcessMessages;
end;
procedure TForm1.ApplicationEvents1Exception(Sender: TObject;
E: Exception);
begin
if E is EForceFreeException then
begin
EForceFreeException(E).DestroyedObject.Free;
Application.ShowException(E);
end;
end;
Про не гуевы приложения особо не задумывался.
--
Regards, LVT.
-
> procedure TForm1.Button1Click(Sender: TObject);
> begin
> with EForceFreeException.Create('Free: '+(Sender as TButton).
> Caption) do
> begin
> DestroyedObject := Sender;
> raise This;
> end;
> Application.ProcessMessages;
> end;
Что это?
Назначение строчки не раскрыто.
-
> oxffff © (18.02.10 15:09) [41]
> Назначение строчки не раскрыто.
У Post*Message/Release на этом месте возникают проблемы.
А, во-ще, что там стоит уже не важно.
Вот и то обсуждение:
http://www.delphimaster.net/view/2-1192180654/40-79Как оказалось, что кроме ИШ там многие поучаствовали ;)
--
Regards, LVT.
-
> Leonid Troyanovsky © (18.02.10 15:20) [42]
>
> > oxffff © (18.02.10 15:09) [41]
>
> > Назначение строчки не раскрыто.
>
> У Post*Message/Release на этом месте возникают проблемы.
>
Я не понял о каких проблемах. Ведь это недостижимый код.
>А, во-ще, что там стоит уже не важно.
И я про это. :)
-
> oxffff © (18.02.10 15:28) [43]
> Я не понял о каких проблемах. Ведь это недостижимый код.
Ну, чего там непонятного. Сначало было
procedure TForm1.Button1Click(Sender: TObject);
begin
Release;
Application.ProcessMessages;
end;
Потом я вспоминал, что должно быть вместо Release.
А строчка так и осталась. Считай, для сравнения.
--
Regards, LVT.
-
> oxffff © (18.02.10 15:28) [43]
> И я про это. :)
А..вот, еще кое-что вспомнил.
Чтобы корректно обработать еще пару объектов:
procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
begin
if E is EForceFreeException then
with EForceFreeException(E) do
if (DestroyedObject = Application.MainForm) or
(DestroyedObject = Application) then
Application.Terminate
else
DestroyedObject.Free;
Application.ShowException(E);
end;
--
Regards, LVT.