powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / закрытие нескольких форм
25 сообщений из 59, страница 2 из 3
закрытие нескольких форм
    #35486019
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дело в том, что у формы должен быть свой собственный метод, который обеспечивает коррекное закрытие этой и именно этой формы. Ну, например, при закрытии некоторой формы возникает дополнительный запрос на какие-либо дополнительные модификации.

При этом, есть различие "штатного" закрытия (самим пользователем) и "аварийного" (по нажатию на крестик в правом верхнем углу приложения).

Лично у меня, вызов этого метода по закрытию формы происходит из штатного метода Form.QueryUnload.

Например, на форме есть кнопка "Выход" в событии Click() которой и прописано закрытие формы (после соответсвующих проверок дается команда ThisForm.Release()). Тогда в событии Form.QueryUnload() будет примерно такой код

Код: plaintext
1.
2.
3.
*Form.QueryUnload()
NODEFAULT
ThisForm.CmdExit.Click()

Соответственно, метод по закрытию всех открытых форм заключается не в вызове события Release() форм, а в вызове события QueryUnload() которое и берет на себя всю работу по корректному закрытию формы.

При этом надо учитывать последовательность форм. Т.е. закрывать формы в "правильном" порядке. Начиная с самой последней. В коллекции _SCREEN.Forms() самая последняя открытая форма имеет индекс 1, предпоследняя - 2 и т.д. Т.е. закрывать надо всегда 1 форму, поскольку после закрытия первой формы индекс 1 получит та, которая была второй.

Код: plaintext
1.
2.
3.
4.
FOR lnI =  1  TO _SCREEN.FormCount
	* Индекс ВСЕГДА  1 , а не значение счетчика
	_SCREEN.Forms( 1 ).QueryUnload()
ENDFOR

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

В общем, вот один из вариантов, который, впрочем, тоже ничего не гарантирует

Код: 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.
* Данный метод предпринимает попытку закрыть ВСЕ формы текущего проект
* В случае успеха возвращает .T. и .F. в случае неудачи.

LOCAL IsDoing, loForm, lnHideForms, lnFormSet, lcOnError
*!* Для отладки
*!*	lcOnError = ON("ERROR")
*!*	ON ERROR *		&& подавляю выдачу сообщений об ошибках
IsDoing = .T.
lnHideForms =  0 
lnFormSet =  0 
DO WHILE _SCREEN.FormCount>m.lnHideForms AND m.IsDoing=.T.
	lnCount=_SCREEN.FormCount		&& запоминаю количество существующих форм
	loForm=_SCREEN.Forms( 1 +m.lnHideForms+m.lnFormSet)
	
	* В моих проектах закрытию ЛЮБОЙ формы можно вызвать из метода QueryUnload
	m.loForm.QueryUnload()

	* Если форма успешно удалилась, то переменная loForm должна принять значение NULL
	IF TYPE('m.loForm')='O' AND IsNull(m.loForm)=.F. 
		* Т.е. форма не удалилась
		IF loForm.Visible=.T.
			* Если форма не удалилась и осталась видимой - это значит
			* что в результате диалога с пользователем было решено прервать выход
			IsDoing=.F.
		ELSE
			* Это на случай существования FormSet, когда дочернии
			* формы не удаляются, а лишь делаются невидимыми
			DEACTIVATE WINDOW (m.loForm.Name)
			lnFormSet = m.lnFormSet +  1 
		ENDIF
	ELSE
		lnFormSet =  0 
		IF m.lnCount = _SCREEN.FormCount
			* т.е. это как раз тот случай, когда форма хотя и удалилась,
			* но осталась в памяти из-за не завершенного метода
			lnHideForms = m.lnHideForms+ 1 
		ENDIF
	ENDIF

ENDDO

*!*	ON ERROR &lcOnError

RETURN (_SCREEN.FormCount=m.lnHideForms)
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35486597
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ

спасибо большое за участие. Я попробовала сделать как Вы написали, но, к сожалению, все тоже самое: форма2 закрывается, проходит unload, а на форме1 нет. :(
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35486616
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может я не права, но мне вот еще что не понятно: ведь в последней форме (форма2) отрабатывает закрытие формы по всем правилам (т.е. release, unload), значит вводе как мы должны вернуться в метод откуда было открытие формы (например, клик по кнопке) и закончить его, а потом уже все остальные действия (если таковые имеются). Разве нет?
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35486926
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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(), а через методы, которые прежде, чем дать команду на закрытие проверят, а можно ли вообще закрыть форму.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35486964
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ

Да я в этом уже убедилась. Я пробовала сделать как Вы рекомендовали, через QueryUnload(), но получила тотже результат. Я уже просто и не знаю что можно с этим сделать!?! И вообще можно ли с этим как-то бороться?
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487028
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
QueryUnload() - это один из вариантов. Смысл-то не в каком-то методе, а в его НАПОЛНЕНИИ. Что там внутри записано.

Как один из вариантов решения - запустить процесс самозакрытия форм через объекты-таймеры.

Т.е. на каждой форме есть объект-таймер. Который с некоторой периодичностью просматривает содержимое некой служебной таблички. Если в этой табличке выставлен некий флаг (значение поля), то этот таймер дает команду на закрытие данной, текущей формы. "По быстрому" это можно сделать не через поле таблицы, а через глобальную переменную. Хотя таблица рано или поздно все-равно понадобиться.

Если из метода формы вызывается модальная форма, то перед вызовом модальной формы этот таймер отключается и включается только после закрытия модальной формы. Ну, примерно так:

Код: plaintext
1.
2.
3.
ThisForm.TmrAutoClose.Enabled = .F.
DO FORM ChildModalForm.scx
ThisForm.TmrAutoClose.Enabled = .T.

Объект TmrAutoClose - это как раз этот таймер автозакрытия.

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

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

Да, разумеется, выставление флага блокирует открытие новых форм.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487183
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да это же УЖАС! В каждой форме писать обработку по таймеру, организация таблиц... а если форм в проекте десятки??? К тому же насколько я в курсе таймер "не очень хорошо" ладит с модальными формами, а в моем случае формы модальные. Замкнутый круг какой-то.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487235
Фотография Анатолий Широков
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AnnaSPBда это же УЖАС! В каждой форме писать обработку по таймеру, организация таблиц... а если форм в проекте десятки??? К тому же насколько я в курсе таймер "не очень хорошо" ладит с модальными формами, а в моем случае формы модальные. Замкнутый круг какой-то.

Для этого надо наследовать свою форму от некоторого базового класса, в которую и поместить всю общую для всех форм функциональность.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487633
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробовала закрыть формы с использованием таймеров.
На двух формах, последовательно вызываемых друг из друга поместила таймеры, которые следять за переменной lCloseFormAll, и если она равна true, закрывают форму.
На внешней кнопке такой код:
For x = _SCREEN.FORMCOUNT to 1 step -1
IF !(ALLTRIM(UPPER(_SCREEN.FORMS(x).NAME))=="BUTTONS")
lCloseFormAll = .T.
ENDIF
EndFor

* выполнение неких действий
...
...
...

Результаты аналогичные: первая форма закрывается, вторая нет.
В общем то это и логично, управление в первую форму не возвращается. Продолжают выполняться действия на внешней кнопке (при этом форма 1 не закрыта). А вот после выполнения всех действий на внешней кнопке, возвращается управление на форму 1, срабатывает таймер и форма закрывается.
Но задача стоит перед выполнением действий на форме предварительно закрыть ВСЕ открытые формы.
Посоветуйте пожалуйста как можно этого добиться?
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487712
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
proc Кнопка.Click()
lCloseFormAll = .T.
Timer.Interval =  10 
return

proc Timer.Timer()
this.Interval =  0 
For x = _SCREEN.FORMCOUNT to  1  step - 1 
   IF !(ALLTRIM(UPPER(_SCREEN.FORMS(x).NAME))=="BUTTONS")
      * Есть еще формы, ждем дальше
      this.Interval =  10 
      return
   ENDIF
EndFor

* выполнение неких действий
...
...
...
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487723
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если формы хоть по одной но закрываются, то можно одним таймером попробовать обойтись. Там же где и кнопка:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
proc Кнопка.Click()
Timer.Interval =  10 
return

proc Timer.Timer()
this.Interval =  0 
llFormOpen = .F.
For x = _SCREEN.FORMCOUNT to  1  step - 1 
   IF !(ALLTRIM(UPPER(_SCREEN.FORMS(x).NAME))=="BUTTONS")
      * Есть еще формы, ждем дальше
      llFormOpen = .T.
      _SCREEN.FORMS(x).Hide()
      _SCREEN.FORMS(x).Release()
   ENDIF
EndFor

if llFormOpen
      this.Interval =  10 
      return
endif
* выполнение неких действий
...
...
...
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487731
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
кнопка находится не на форме, это тулбар с несколькими кнопками
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35487826
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
кнопка находится не на форме, это тулбар с несколькими кнопками
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35488211
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во-первых, таймеры должны быть привязаны к формам. Каждой отдельно взятой форме соответствует свой собственный таймер. Через классы это легко делается. Никакого ужаса.

Т.е. открытие каждой формы сопровождается запуском таймера, расположенного на этой форме.

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

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

Выставили флаг и ждем. Через некоторое время проверям - есть флаг? Формы закрыты? Если флаг есть, а формы не закрыты, опять ждем. Через некоторое время опять проверяем - есть флаг? Формы закрыты? ...

И так до тех пор пока флаг не окажется сброшенным или все формы не окажутся закрытыми.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35488328
Galyamov Rinat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimaT, а зачем каждый раз передергиваешь свойство таймера this.Interval = 10


Это лишнее.

PS для запуска таймера надо использовать его свойство enabled


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35488396
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Посмотри простой пример во вложении. Я поставил интервал в 5 секунд. Запускаешь main.prg и открываешь несколько вложенных модальных форм. Для закрытия всех форм нажимаешь кнопку Close в ToolBar и ждешь 5..10 секунд пока не появится сообщение о том, что все формы закрыты.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35488444
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Galyamov Rinat
DimaT, а зачем каждый раз передергиваешь свойство таймера this.Interval = 10
Это лишнее.

PS для запуска таймера надо использовать его свойство enabled

Не знал что enabled у таймера есть и работает, при Interval = 0 таймер не работает. По большому счету оба способа запуска/остановки равнозначны - объем кода одинаковый.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35488845
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал с одним таймером на тулбаре. Вроде работает.
Только еще надо проверять лишние срабатывания таймера, а то полезный код может дважды отработать.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35489754
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо большое всем за участие.

но, честно говоря, задача так до конча и не решена.
Как я уже не однократно писала, проблема в том, что помимо закрытия предыдущих форм, на этом тулбаре прописаны некие действия (это не кнопка закрыть), там может идти вызов какой-нибудь программы или формы и т.д. Так вот проблема заключается в том, что все формы кроме последней не МОГУТ быть закрыты пока не выполняться все действия на кнопке тулбара. А нужно перед выполнением этих действий сначало закрыть всё, что открыто к этому моменту, а потом выполнять некие действия.
Например, открываем форму1, из нее форму2 и кликаем по кнопке тулбара, на которой прописано закрытие всех открытых к этому моменту форм и открытие некой формы3. И получается, что форма2 (последняя из двух открытых) закрывается корректно, а форма1 не может быть закрыта, т.к. выполняется код на кнопке тулбара и мы не можем завершить клик, на котором прописано открытие формы2. Т.е. открывается форма3 (поверх формы1), там что-то делается и когда мы закрываем форму3, происходит unload формы3, далее завершение действий на клике в форме1 и unload формы1.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35489859
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AnnaSPBно, честно говоря, задача так до конча и не решена.

Нами задача решена до конца и полностью :)

Внимательно перечитай что я и ВладимирМ предлагали и приложенные файлы позапускай.

Прилагаю еще один пример (запускать main.prg). Добавил MessageBox() в Unload() чтобы понятно было что нужный код выполнится ПОСЛЕ закрытия всех форм. Смотри на порядок мессаджбоксов.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35489918
AnnaSPB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T

СПАСИБО! все понятно, это я уже туплю. работает все супер!

Спасибо большое :)
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35520697
MikhailB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Жалко что закончисля этот флейм, но хочется всетаки добавить свои пять копеек...


Эту проблему можно решить еще вот так, используя простые немодальные формы:

1.Запуская новую "модальную" форму устанавливаешь ей свойство AlwaysOnTop=.T., а у элементов запущеной до этого "модальной" формы ты просто выставляешь свойство Enabled=.F.
и выключаешь свойство формы AlwaysOnTop=.F.

2.Перед запуском новой "модальной" формы нужна процедурка, которая бы искала предыдущию "модальную" форму и запоминала бы куда-нибудь ее имя

3.Когда ты закрываешь текущую "модальную" форму, ты востанавливаешь для запомненной предыдущей "модальной" формы свойство AlwaysOnTop=.T.


Закрыть ты эти формы можешь в любое время простым скриптом

FOR i01=1 TO _SCREEN.FORMCOUNT
_SCREEN.FORMS(1).Release
next i01

Как все это реализовать уже дело техники...
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35520903
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MikhailB

Вы бы сначала данную тему почитали. Проблема именно в том, что закрытие перебором массива _SCREEN.Forms для более чем 2 одновременно открытых модальных форм - не всегда работает.

Запоминать предыдущую форму нет никакой необходимости, поскольку индекс активной в данный момент формы автоматически устанавливается равным 1, а индексы всех прочих формы также автоматически "сдвигаются".

Другими словами, активная в данный момент модальная форма всегда будет иметь индекс 1, а та модальная форма из которой ее вызвали всегда будет иметь индекс 2 в массиве _SCREEN.Forms. Разумеется, если вызов происходит из событий формы, а не через пункты меню или ToolBar.

"Игры" с AlwaysOnTop в отношении модальных форм просто опасны. Вы можете получить "мертвое" зависание случайно вытащив на верх предыдущую форму. Переключится на активную модальную форму невозможно и закрыть вытащенную форму - тоже.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35522570
MikhailB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, тему прочитал и ничего противоречивого ей в своем посте не нашел.

Хочу только поправиться от вероятно возникшего недопонимания...

В моем предыдущем сообщении под "модальной" формой, имется в виду простая немодальная форма.
То есть при запуске новой формы которая должна быть якобы модальной, но таковой не является необходимо определить ей свойство AlwaysOnTop=.T., а у предыдущей "модальной" формы его сбросить AlwaysOnTop=.F. и установить Enabled=.F.

Для того чтобы избежать коллизий для всех прочих запущеных "модальных" и немодальных форм мы должны каким-то образом установить их свойство Enabled=.F. тоже.

В данном случае нет никакой опасности в "играх" с AlwaysOnTop, так как нет модальных форм.
...
Рейтинг: 0 / 0
закрытие нескольких форм
    #35522669
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MikhailBСпасибо, тему прочитал и ничего противоречивого ей в своем посте не нашел.

...так как нет модальных форм.

Читай самый первый пост:
AnnaSPB... последовательно одна из другой открываются формы ( все модальные )...

Если уж хочется доказать свою правоту - возьми выше пример (мой или Владимира), замени код в кнопке на тулбаре на свой и продемонстрируй что все у тебя отлично работает.
...
Рейтинг: 0 / 0
25 сообщений из 59, страница 2 из 3
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / закрытие нескольких форм
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]