[Решено] ОбработкаПодбора() в лазарусе
Модератор: Модераторы
[Решено] ОбработкаПодбора() в лазарусе
Добрый день.
Перечитал кучу форумов но таки не нашел простого ответа.
Рассмотрим ситуацию:
Есть главная форма, на нее выведена кнопка, по которой создается и открывается форма подбора по справочнику. Доступ ко всем свойствам и методам "дочерней" формы естественно есть. А вот как мне дать понять главной форме, что в дочерней работа завершена, можно забрать результат (Ид выбранного элемента, например) и дочернюю форму прибить?
Модальный способ не подходит. Не красиво это.
В 1С есть процедура ОбработкаПодбора(<Элемент>,<КонтФормы>) (Обработка подбора значения при нажатия кнопки Выбрать в Форме Подбора значения). И все в общем то очевидно.
Есть ли что-то подобное в Lazaruse? Если нет, как это сделать?
Перечитал кучу форумов но таки не нашел простого ответа.
Рассмотрим ситуацию:
Есть главная форма, на нее выведена кнопка, по которой создается и открывается форма подбора по справочнику. Доступ ко всем свойствам и методам "дочерней" формы естественно есть. А вот как мне дать понять главной форме, что в дочерней работа завершена, можно забрать результат (Ид выбранного элемента, например) и дочернюю форму прибить?
Модальный способ не подходит. Не красиво это.
В 1С есть процедура ОбработкаПодбора(<Элемент>,<КонтФормы>) (Обработка подбора значения при нажатия кнопки Выбрать в Форме Подбора значения). И все в общем то очевидно.
Есть ли что-то подобное в Lazaruse? Если нет, как это сделать?
Последний раз редактировалось yeger 15.11.2011 11:56:09, всего редактировалось 1 раз.
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
Обработать событие OnClose в дочерней форме и передать нужные параметры главной форме
- dunin
- энтузиаст
- Сообщения: 634
- Зарегистрирован: 02.05.2007 13:18:11
- Откуда: Тољя††и
- Контактная информация:
Код: Выделить всё
procedure DochernayaForma.BtnZabratClick(Sender: tobject);
begin
... // что-то делаем
GlavnayaForma.ZabratRezultat; // вызываем процедуру описанную в модуле главной формы
DochernayaForma.Close; // закрываем дочернюю
end;или как-то так или я вопроса не понял...
Код: Выделить всё
procedure DochernayaForma.BtnZabratClick(Sender: tobject);
begin
... // что-то делаем
GlavnayaForma.ZabratRezultat; // вызываем процедуру описанную в модуле главной формы
DochernayaForma.Close; // закрываем дочернюю
end;Вопрос понят правильно. А как дочерняя узнает что у главной есть метод "ZabratRezultat"? откуда вообще взялась переменная GlavnayaForma?
Если объявить модуль главной в дочерней будет "круговая" ссылка, что противоречит логике самого языка.
Думал о пользовательском событии (Отправлять родителю событие формы) но в описаниях и мнениях запутался...
"почему ей не красиво быть модальной" - потому что блокирует предыдущие окна. Открыл документ, в нем справочник, в нем подбор справочника и т.д. и все это модально....
- alexs
- долгожитель
- Сообщения: 4069
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
yeger писал(а):А как дочерняя узнает что у главной есть метод "ZabratRezultat"? откуда вообще взялась переменная GlavnayaForma?
Объяви у дочерней в приватной секции переменную типа "Главная Форма"
При создании дочерней прописывай туда ссылку на главную форму
Вот и все всё будут знать.
yeger писал(а):Если объявить модуль главной в дочерней будет "круговая" ссылка, что противоречит логике самого языка.
Противоречие возникает если ты объявляешь обоих подключение модулей в соответсующих секция интерфейса.
Но никто не мешает тебе объявить модуль дочерней формы в разделе реализации (implementation)
И всё будет работать правильно.
Ну а насчёт события когда надо передавать - ттебе уже указали - OnClose у дочерней формы.
Внимание!
В приведённом методе кроется одна засада - что будет, если закроют главную форму раньше, чем закроют дочернюю?
Решается просто:
- можно всем формам посылать уведомление через событие с кодом события "Закрытие моей любимой главной формы" и указыват экземпляр этйо формы.
- можно в главной форме сразу объявить коллекцию указателей на её дочернии формы (тут надо будет не забыть убирать дочернюю из коллекции при закрытии дочерней)
Можно ещё чего придуматью.
Также вопрос - что ты будешь делать с дочерними - если закрыли главную?
Все прелисти многодокументного неблокирующего интерфейса для программера. Но с другой стороны, обычно такая метода более удобная для пользователя.
Вопрос ведь не звучал "когда", а "как".
Не красивое решение же. Придется добавлять каждый из возможных родителей в implementation.
Есть мысль: сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм.
Для "TFormWithEventSelect" определить событие, назовем "OnSelectInChild", для которого в свою очередь передавать, положим имя подчиненной формы.
Такой вариант реализуем средствами lazarus?
Если да, прошу поделиться ссылками на справку по теме или примером.
Не красивое решение же. Придется добавлять каждый из возможных родителей в implementation.
Есть мысль: сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм.
Для "TFormWithEventSelect" определить событие, назовем "OnSelectInChild", для которого в свою очередь передавать, положим имя подчиненной формы.
Такой вариант реализуем средствами lazarus?
Если да, прошу поделиться ссылками на справку по теме или примером.
Есть мысль: сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм.
Можно и не делать компонент, а просто Файл\Создать\Унаследованный элемент.
- alexs
- долгожитель
- Сообщения: 4069
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
yeger писал(а):Придется добавлять каждый из возможных родителей в implementation.
Коков был вопрос - таков и ответ.
Я привёл только 2 способа решения. Можно ещё напридумывать кучу.
yeger писал(а):сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм
Визуальное наследвание.
Можно использоват интерфейсы.
Добавлено спустя 5 минут 24 секунды:
kipar писал(а):Можно и не делать компонент, а просто Файл\Создать\Унаследованный элемент.
Вместе ответили
yeger
Ещё раз повторюсь - всё зависит от вашей проблемы. Мы тут предлагаем общие пути решения. только специфика вашей задачи определит тот путь (может единственный, может несколько альтернатив), который необходимо использовать.
P.S.
Я в своих проектах для многодокументального интерфейса использую в основном 2-й метод из своего 1-го ответа. Там именно основной список документов и из него создание/открытие существующего документа. После изменения/закрытия документа основной список пересчитывается по необходимости. Хотя в некоторых местах используются и 1-й пример, и события-сообщения, и интерфейсы...
Не прошло и пол года, как ответ был найден. Основная проблема для аналога "ОбработкаПодбора()" это тот факт, что дочернее окно "ничего не знает" о главном.
Не буду "растекаться мыслею", а перейду к сути:
- в главной форме определяем в "published" секции процедуру обработки подбора. Пусть так:
Вызов подчиненной формы оригинальностью не отличается
Пусть эта процедура пока вернет нам лишь имя класса её вызвавшего:
В модуле подчиненной формы объявляем тип реализующий процедуру главной формы (т.к. подчиненная не знает о функциях главной) и собственно подчиненную форму:
И, собственно реализуем вызов процедуры главной формы:
"Прибивание" подчиненных окон хорошо описал alexs выше.
Еще пример вызова метода по наименованию тут: http://www.kansoftware.ru/?tid=468
Не буду "растекаться мыслею", а перейду к сути:
- в главной форме определяем в "published" секции процедуру обработки подбора. Пусть так:
Код: Выделить всё
TFrmRefCur = class(TForm)
procedure OpenChild(Sender: TObject);// <- Вызов подчиненной формы
private
{ private declarations }
public
{ public declarations }
published
{ much public declarations }
procedure ItWasMade(ByForm:TForm); // <- А вот и обработка подбора
end;
Вызов подчиненной формы оригинальностью не отличается
Код: Выделить всё
procedure TFrmRefCur.OpenChild(Sender: TObject);
var
FCurrecy: TFrmEditRefCur;//класс наследник TForm описан в другом модуле указанном в uses
begin
FCurrecy:=TFrmEditRefCur.Create(Self);
FCurrecy.Show;
end;
Пусть эта процедура пока вернет нам лишь имя класса её вызвавшего:
Код: Выделить всё
procedure TFrmRefCur.ItWasMade(ByForm:TForm);
begin
ShowMessage(ByForm.Name);
end;
В модуле подчиненной формы объявляем тип реализующий процедуру главной формы (т.к. подчиненная не знает о функциях главной) и собственно подчиненную форму:
Код: Выделить всё
type
TExecute = procedure(Who:TForm) of object; //<- тип реализующий процедуру главной формы
{ TFrmEditRefCur }
TFrmEditRefCur = class(TForm)
BtnOk: TBitBtn;
procedure BtnOkClick(Sender: TObject);//<- дескать выбираем что-то
private
{ private declarations }
public
{ public declarations }
procedure MakeIt (Who:TForm);//<- вот тут передадим в обработку подбора
end;
И, собственно реализуем вызов процедуры главной формы:
Код: Выделить всё
procedure TFrmEditRefCur.MakeIt (Who:TForm);
var
Routine: TMethod;
Execute: TExecute;
begin
Routine.Data := Pointer(Who.Owner);
// Returns the address of a published method.
Routine.Code := Who.Owner.MethodAddress(Utf8ToAnsi('ItWasMade'));
if Routine.Code <> nil then
begin
Execute := TExecute(Routine);
Execute(Who);
end;
end;
procedure TFrmEditRefCur.BtnOkClick(Sender: TObject);
begin
Close;
MakeIt(Self);
end;
"Прибивание" подчиненных окон хорошо описал alexs выше.
Еще пример вызова метода по наименованию тут: http://www.kansoftware.ru/?tid=468
