|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Дело в том, что у формы должен быть свой собственный метод, который обеспечивает коррекное закрытие этой и именно этой формы. Ну, например, при закрытии некоторой формы возникает дополнительный запрос на какие-либо дополнительные модификации. При этом, есть различие "штатного" закрытия (самим пользователем) и "аварийного" (по нажатию на крестик в правом верхнем углу приложения). Лично у меня, вызов этого метода по закрытию формы происходит из штатного метода Form.QueryUnload. Например, на форме есть кнопка "Выход" в событии Click() которой и прописано закрытие формы (после соответсвующих проверок дается команда ThisForm.Release()). Тогда в событии Form.QueryUnload() будет примерно такой код Код: plaintext 1. 2. 3.
Соответственно, метод по закрытию всех открытых форм заключается не в вызове события Release() форм, а в вызове события QueryUnload() которое и берет на себя всю работу по корректному закрытию формы. При этом надо учитывать последовательность форм. Т.е. закрывать формы в "правильном" порядке. Начиная с самой последней. В коллекции _SCREEN.Forms() самая последняя открытая форма имеет индекс 1, предпоследняя - 2 и т.д. Т.е. закрывать надо всегда 1 форму, поскольку после закрытия первой формы индекс 1 получит та, которая была второй. Код: plaintext 1. 2. 3. 4.
Но в этом случае есть опасность зацикливания, если форма по каким-то причинам не может быть закрыта. Точнее, не зацикливания, а нескольких попыток закрытия только одной формы, не закрывая все остальные. В общем, вот один из вариантов, который, впрочем, тоже ничего не гарантирует Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44.
... |
|||
:
Нравится:
Не нравится:
|
|||
13.08.2008, 17:48 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
ВладимирМ спасибо большое за участие. Я попробовала сделать как Вы написали, но, к сожалению, все тоже самое: форма2 закрывается, проходит unload, а на форме1 нет. :( ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 09:36 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Может я не права, но мне вот еще что не понятно: ведь в последней форме (форма2) отрабатывает закрытие формы по всем правилам (т.е. release, unload), значит вводе как мы должны вернуться в метод откуда было открытие формы (например, клик по кнопке) и закончить его, а потом уже все остальные действия (если таковые имеются). Разве нет? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 09:47 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
AnnaSPBМожет я не права, но мне вот еще что не понятно: ведь в последней форме (форма2) отрабатывает закрытие формы по всем правилам (т.е. release, unload), значит вводе как мы должны вернуться в метод откуда было открытие формы (например, клик по кнопке) и закончить его, а потом уже все остальные действия (если таковые имеются). Разве нет? FoxPro - это однопоточное приложение. Вернуться-то он должен. Весь вопрос в том КОГДА. Он не может прервать выполнение текущей процедуры, чтобы обработать закрытие формы "по всем правилам". Т.е. завершение обработки клика кнопки произойдет только после того, как будет закончена процедура закрытия всех открытых форм. А к этому моменту эта форма уже может быть безнадежно испорчена попытками ее закрыть. И завершение события Click() кнопки уже ничего не исправит. У нас есть программа (инструкция) соержащая примерно такую последовательность команд: Инструкция 1 1. Закрыть форму 1 2. Закрыть Форму 2 Вот он ее "тупо" и выполняет. От начала и до конца. То, что после выполнения команды "Закрыть форму 1" теоретически должна выполнится еще одна инструкция вида Инструкция 2 1. Завершить событие Click() кнопки на форме 2 Вовсе не означает, что "Инструкция 2" будет выполнена сразу после команды "Закрыть форму 1". Эта инструкция будет поставлена в очередь инструкций. В данном случае сразу за "Инструкцией 1". В результате получаем такой список: Инструкция 1 1. Закрыть форму 1 (выполнено) 2. Закрыть Форму 2 Инструкция 2 1. Завершить событие Click() кнопки на форме 2 Получаем неразрешимое противоречие. В данный конкретный момент времени выполняется вторая команда Инструкции 1 (закрыть Форму 2), а в очереди процессов ждет своего часа еще одна инструкция на завершение метода этой закрываемой формы. Хуже всего то, что FoxPro может "частично" закрыть Форму 2 в такой ситуации. Т.е. уничтожить часть объектов свойств и методов этой формы. И последующее выполнение Инструкции 2 уже ничего не рашает. Форма 2 оказывается в таком состоянии, что ее невозможно уничтожить уже никакими способами. Именно поэтому, закрытие формы должно выполняться не через прямые команды ThisForm.Release(), а через методы, которые прежде, чем дать команду на закрытие проверят, а можно ли вообще закрыть форму. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 11:36 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
ВладимирМ Да я в этом уже убедилась. Я пробовала сделать как Вы рекомендовали, через QueryUnload(), но получила тотже результат. Я уже просто и не знаю что можно с этим сделать!?! И вообще можно ли с этим как-то бороться? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 11:47 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
QueryUnload() - это один из вариантов. Смысл-то не в каком-то методе, а в его НАПОЛНЕНИИ. Что там внутри записано. Как один из вариантов решения - запустить процесс самозакрытия форм через объекты-таймеры. Т.е. на каждой форме есть объект-таймер. Который с некоторой периодичностью просматривает содержимое некой служебной таблички. Если в этой табличке выставлен некий флаг (значение поля), то этот таймер дает команду на закрытие данной, текущей формы. "По быстрому" это можно сделать не через поле таблицы, а через глобальную переменную. Хотя таблица рано или поздно все-равно понадобиться. Если из метода формы вызывается модальная форма, то перед вызовом модальной формы этот таймер отключается и включается только после закрытия модальной формы. Ну, примерно так: Код: plaintext 1. 2. 3.
Объект TmrAutoClose - это как раз этот таймер автозакрытия. Тогда процесс закрытия всех открытых форм будет заключаться просто в установке флага в этой служебной таблице (или изменение занчения глобальной переменной) и запуск другого таймера, который периодически будет проверять есть ли сейчас открытые формы. Если ни одной открытой формы не осталось, то этот таймер закрывает приложение. Обработка выполняется через таймеры именно для того, чтобы все процессы по автозакрытию форм отработали в нужной последовательности. Чтобы не возникло проблем с очередями процессов. Да, разумеется, выставление флага блокирует открытие новых форм. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 12:03 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
да это же УЖАС! В каждой форме писать обработку по таймеру, организация таблиц... а если форм в проекте десятки??? К тому же насколько я в курсе таймер "не очень хорошо" ладит с модальными формами, а в моем случае формы модальные. Замкнутый круг какой-то. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 12:31 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
AnnaSPBда это же УЖАС! В каждой форме писать обработку по таймеру, организация таблиц... а если форм в проекте десятки??? К тому же насколько я в курсе таймер "не очень хорошо" ладит с модальными формами, а в моем случае формы модальные. Замкнутый круг какой-то. Для этого надо наследовать свою форму от некоторого базового класса, в которую и поместить всю общую для всех форм функциональность. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 12:40 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Попробовала закрыть формы с использованием таймеров. На двух формах, последовательно вызываемых друг из друга поместила таймеры, которые следять за переменной lCloseFormAll, и если она равна true, закрывают форму. На внешней кнопке такой код: For x = _SCREEN.FORMCOUNT to 1 step -1 IF !(ALLTRIM(UPPER(_SCREEN.FORMS(x).NAME))=="BUTTONS") lCloseFormAll = .T. ENDIF EndFor * выполнение неких действий ... ... ... Результаты аналогичные: первая форма закрывается, вторая нет. В общем то это и логично, управление в первую форму не возвращается. Продолжают выполняться действия на внешней кнопке (при этом форма 1 не закрыта). А вот после выполнения всех действий на внешней кнопке, возвращается управление на форму 1, срабатывает таймер и форма закрывается. Но задача стоит перед выполнением действий на форме предварительно закрыть ВСЕ открытые формы. Посоветуйте пожалуйста как можно этого добиться? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 14:26 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
AnnaSPBНа внешней кнопке такой код А кнопка где расположена? Если формы модальные, то на верхней форме должна быть, т.к. все остальное недоступно. AnnaSPBFor x = _SCREEN.FORMCOUNT to 1 step -1 IF !(ALLTRIM(UPPER(_SCREEN.FORMS(x).NAME))=="BUTTONS") lCloseFormAll = .T. ENDIF EndFor * выполнение неких действий ... ... ... Сделай таймер там же где кнопка. Для ожидания отработки остальных таймеров :) Код раздели так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 14:49 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Если формы хоть по одной но закрываются, то можно одним таймером попробовать обойтись. Там же где и кнопка: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 14:53 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
кнопка находится не на форме, это тулбар с несколькими кнопками ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 14:56 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
кнопка находится не на форме, это тулбар с несколькими кнопками ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 15:18 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Во-первых, таймеры должны быть привязаны к формам. Каждой отдельно взятой форме соответствует свой собственный таймер. Через классы это легко делается. Никакого ужаса. Т.е. открытие каждой формы сопровождается запуском таймера, расположенного на этой форме. Во-вторых, запуск процесса закрытия всех открытых форм сам по себе ничего не удаляет. Он только выставляет флаг - закрыть формы. Затем запускается таймер, который анализирует, во-первых, состояние флага (он может быть отменен в процессе закрытия какой-либо формы), а, во-вторых, количество открытых форм. Другими словами, невозможно сделать процесс закрытия всех форм "одноразовым" . Т.е. дать команду и тут же все закроется. Необходимо периодически проверять процесс закрытия. Выставили флаг и ждем. Через некоторое время проверям - есть флаг? Формы закрыты? Если флаг есть, а формы не закрыты, опять ждем. Через некоторое время опять проверяем - есть флаг? Формы закрыты? ... И так до тех пор пока флаг не окажется сброшенным или все формы не окажутся закрытыми. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 17:26 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
DimaT, а зачем каждый раз передергиваешь свойство таймера this.Interval = 10 Это лишнее. PS для запуска таймера надо использовать его свойство enabled Posted via ActualForum NNTP Server 1.4 ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 18:02 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Посмотри простой пример во вложении. Я поставил интервал в 5 секунд. Запускаешь main.prg и открываешь несколько вложенных модальных форм. Для закрытия всех форм нажимаешь кнопку Close в ToolBar и ждешь 5..10 секунд пока не появится сообщение о том, что все формы закрыты. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 18:27 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Galyamov Rinat DimaT, а зачем каждый раз передергиваешь свойство таймера this.Interval = 10 Это лишнее. PS для запуска таймера надо использовать его свойство enabled Не знал что enabled у таймера есть и работает, при Interval = 0 таймер не работает. По большому счету оба способа запуска/остановки равнозначны - объем кода одинаковый. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2008, 18:53 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Попробовал с одним таймером на тулбаре. Вроде работает. Только еще надо проверять лишние срабатывания таймера, а то полезный код может дважды отработать. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2008, 09:04 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
спасибо большое всем за участие. но, честно говоря, задача так до конча и не решена. Как я уже не однократно писала, проблема в том, что помимо закрытия предыдущих форм, на этом тулбаре прописаны некие действия (это не кнопка закрыть), там может идти вызов какой-нибудь программы или формы и т.д. Так вот проблема заключается в том, что все формы кроме последней не МОГУТ быть закрыты пока не выполняться все действия на кнопке тулбара. А нужно перед выполнением этих действий сначало закрыть всё, что открыто к этому моменту, а потом выполнять некие действия. Например, открываем форму1, из нее форму2 и кликаем по кнопке тулбара, на которой прописано закрытие всех открытых к этому моменту форм и открытие некой формы3. И получается, что форма2 (последняя из двух открытых) закрывается корректно, а форма1 не может быть закрыта, т.к. выполняется код на кнопке тулбара и мы не можем завершить клик, на котором прописано открытие формы2. Т.е. открывается форма3 (поверх формы1), там что-то делается и когда мы закрываем форму3, происходит unload формы3, далее завершение действий на клике в форме1 и unload формы1. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2008, 13:58 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
AnnaSPBно, честно говоря, задача так до конча и не решена. Нами задача решена до конца и полностью :) Внимательно перечитай что я и ВладимирМ предлагали и приложенные файлы позапускай. Прилагаю еще один пример (запускать main.prg). Добавил MessageBox() в Unload() чтобы понятно было что нужный код выполнится ПОСЛЕ закрытия всех форм. Смотри на порядок мессаджбоксов. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2008, 14:26 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Dima T СПАСИБО! все понятно, это я уже туплю. работает все супер! Спасибо большое :) ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2008, 14:43 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Жалко что закончисля этот флейм, но хочется всетаки добавить свои пять копеек... Эту проблему можно решить еще вот так, используя простые немодальные формы: 1.Запуская новую "модальную" форму устанавливаешь ей свойство AlwaysOnTop=.T., а у элементов запущеной до этого "модальной" формы ты просто выставляешь свойство Enabled=.F. и выключаешь свойство формы AlwaysOnTop=.F. 2.Перед запуском новой "модальной" формы нужна процедурка, которая бы искала предыдущию "модальную" форму и запоминала бы куда-нибудь ее имя 3.Когда ты закрываешь текущую "модальную" форму, ты востанавливаешь для запомненной предыдущей "модальной" формы свойство AlwaysOnTop=.T. Закрыть ты эти формы можешь в любое время простым скриптом FOR i01=1 TO _SCREEN.FORMCOUNT _SCREEN.FORMS(1).Release next i01 Как все это реализовать уже дело техники... ... |
|||
:
Нравится:
Не нравится:
|
|||
03.09.2008, 15:52 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
MikhailB Вы бы сначала данную тему почитали. Проблема именно в том, что закрытие перебором массива _SCREEN.Forms для более чем 2 одновременно открытых модальных форм - не всегда работает. Запоминать предыдущую форму нет никакой необходимости, поскольку индекс активной в данный момент формы автоматически устанавливается равным 1, а индексы всех прочих формы также автоматически "сдвигаются". Другими словами, активная в данный момент модальная форма всегда будет иметь индекс 1, а та модальная форма из которой ее вызвали всегда будет иметь индекс 2 в массиве _SCREEN.Forms. Разумеется, если вызов происходит из событий формы, а не через пункты меню или ToolBar. "Игры" с AlwaysOnTop в отношении модальных форм просто опасны. Вы можете получить "мертвое" зависание случайно вытащив на верх предыдущую форму. Переключится на активную модальную форму невозможно и закрыть вытащенную форму - тоже. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.09.2008, 16:49 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
Спасибо, тему прочитал и ничего противоречивого ей в своем посте не нашел. Хочу только поправиться от вероятно возникшего недопонимания... В моем предыдущем сообщении под "модальной" формой, имется в виду простая немодальная форма. То есть при запуске новой формы которая должна быть якобы модальной, но таковой не является необходимо определить ей свойство AlwaysOnTop=.T., а у предыдущей "модальной" формы его сбросить AlwaysOnTop=.F. и установить Enabled=.F. Для того чтобы избежать коллизий для всех прочих запущеных "модальных" и немодальных форм мы должны каким-то образом установить их свойство Enabled=.F. тоже. В данном случае нет никакой опасности в "играх" с AlwaysOnTop, так как нет модальных форм. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2008, 14:35 |
|
закрытие нескольких форм
|
|||
---|---|---|---|
#18+
MikhailBСпасибо, тему прочитал и ничего противоречивого ей в своем посте не нашел. ...так как нет модальных форм. Читай самый первый пост: AnnaSPB... последовательно одна из другой открываются формы ( все модальные )... Если уж хочется доказать свою правоту - возьми выше пример (мой или Владимира), замени код в кнопке на тулбаре на свой и продемонстрируй что все у тебя отлично работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.09.2008, 14:54 |
|
|
start [/forum/topic.php?fid=41&msg=35486597&tid=1586371]: |
0ms |
get settings: |
10ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
97ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
64ms |
get tp. blocked users: |
2ms |
others: | 12ms |
total: | 216ms |
0 / 0 |