Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Общие вопросы по программированию, компьютерный форум
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.08.2015, 10:54   #1
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию Помогите обойти рекурсию, чтобы правильно закрыть форму

Доброе время суток форумчане

Приложение работает с БД. Есть 2 сценария работы программы: первый режим (в свернутом виде - работает), с вторым режимом (немного отличается от первого) у меня возникла проблема.
Есть DataSet с данными, в котором первая строка, позволяет открыть «Form2», т.е. LRemains = 0 (см. код), вторая строка, НЕ разрешает открыть «Form2», т.е. LRemains <> 0 (см. код),
Проблема в том что, после ухода с первой строки, «Form2» - не закрывается

Если кратко то дело обстоит так:
Код:
procedure Form1.Database.AfterScroll
var
  LRemains: integer;
begin
    LRemains := DataSet.FieldByName('RIGHT_INPUT').AsInteger mod PuNumberCombineRepeat;
    if LRemains = 0 then
      Form1.TimerRepeatTimer(Sender: TObject);  
End
Я вызываю событие «TimerRepeatTimer», т.к. это осталось с первого сценария.
Код:
procedure Form1.TimerRepeatTimer(Sender: TObject);
begin
  TimerRepeat.Enabled := false;
  Form2:= Form2.Create(self);
  Form2.ShowModal;
  Form2.Free;
 end;
Код:
procedure Form2.BitBtnClick(Sender: TObject);
begin
  if MessageDlg(Format(C_Translate, [LWords]), mtConfirmation, [mbYes, mbNo], 0) = mrNo then
    begin //первый сценарий (рабочий)
      Form1.MESSAGE_APPLICATION(2, FMain.rgDirectionRepeat.ItemIndex, 0);
      Form1.DataSet.Next;
      Form1.TimerRepeat.Enabled := true; // Form2 закрывается
    end
  else  //второй сценарий (не рабочий)
  Form1.MESSAGE_APPLICATION(2, FMain.rgDirectionRepeat.ItemIndex, 1);
end;
Код:
procedure Form1.MESSAGE_APPLICATION(AKey, ASelect, ASwitch: integer);
begin
   if MessageDlg(Format(C_Translate, [LWords]), mtConfirmation, [mbYes, mbNo], 0) = mrNo then
   begin
       //первый сценарий (имеет окончание выполнения)
   end;
   else //второй сценарий
       Form1.edCheckWord.Text := Form1.DataSet.FieldByName('EW1').AsString;
end

procedure Form1.edCheckWordChange(Sender: TObject);
begin
  ...
  Form1.DataSet.Next;
end;
В результате этого всего, у меня не выполняется "Form2.Free;" и "Form2" – не закрыта.
В первом сценарии форма закрывается где я указал.
Но 2-ой сценарии – у меня какой-то замкнутый цикл.
А если в «Form1.MESSAGE_APPLICATION», явно грохнуть «Form2», тогда
«Project PEng_gDB.exe raised exception class EAccessViolation with message 'Access violation at address 0000001B. Read of address 0000001B'. Process stopped. Use Step or Run to continue.» и "Project D:\Prog\Eng_gdb\PEng_gDB.exe faulted with message: 'application-defined exception (code 0xc000041d) at 0x76e80309'. Process Stopped. Use Step or Run to continue."

Мне нужно каким-то образом выйти на "FRepeat.Free;" перед "Form1.ibdsWord.Next;". И закрыть «Form2».

Заранее спасибо

Последний раз редактировалось KBO; 21.08.2015 в 11:05.
KBO вне форума Ответить с цитированием
Старый 21.08.2015, 11:35   #2
GreenWizard
мальчик-помогай =)
Форумчанин
 
Регистрация: 16.09.2010
Сообщений: 522
По умолчанию

Сложно что-то конкретно советовать, не знаю весь проект (а он явно сложнее, чем обычная писанина студентов), но:
1) Show/Hide вместо постоянного Create/Free
2) не совсем отдельное от п.1, но очень плохая идея в таймере создавать окна
-----------------------------
да, таймер совсем тут не нужен.. я бы заменил его на пользовательское сообщение, если уж очень нужно показывать/скрывать форму 2 после окончания кода обработки события

простейший вариант:
Код:
procedure Form1.Database.AfterScroll
var
  LRemains: integer;
begin
    LRemains := DataSet.FieldByName('RIGHT_INPUT').AsInteger mod PuNumberCombineRepeat;
    Form2.Visible := LRemains <> 0;
End
если Форма 2 динамическая, то меняем на типа "setVisibleForm2(LRemains <> 0)", a внутри синглтон делаем из Формы 2

Последний раз редактировалось GreenWizard; 21.08.2015 в 11:49. Причина: не проснулся, блин, и торможу
GreenWizard вне форума Ответить с цитированием
Старый 21.08.2015, 12:01   #3
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Цитата:
Сообщение от GreenWizard Посмотреть сообщение
2) не совсем отдельное от п.1, но очень плохая идея в таймере создавать окна
Эта программа для учебы англ. слов.
Как я выше писал (про один из сценариев ее работы), при работе в скрытом режиме, она может через заданный промежуток времени, показывать небольшое окно с разными англ.словами, чтоб пользователь мог, их вспоминать (кнопки "да", "нет"), а потом опять закрываться. и опять открываться и т.д.
Т.е. без таймера тут ни как.

А на счет "Show/Hide" - спасибо - это вариант, я как-то о "Hide" - забыл. нужно тогда будет немного событие «TimerRepeatTimer» переделать, т.е сделать 2 ветки: одна на "create/free", другая на "Show/Hide"

Последний раз редактировалось KBO; 21.08.2015 в 12:09.
KBO вне форума Ответить с цитированием
Старый 21.08.2015, 12:40   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Код:
procedure Form2.BitBtnClick(Sender: TObject);
begin
  if MessageDlg(Format(C_Translate, [LWords]), mtConfirmation, [mbYes, mbNo], 0) = mrNo then
    begin //первый сценарий (рабочий)
      Form1.MESSAGE_APPLICATION(2, FMain.rgDirectionRepeat.ItemIndex, 0);
=============
      Form1.DataSet.Next;
      Form1.TimerRepeat.Enabled := true; // Form2 закрывается

Этому ЗДЕСЬ не место.
=============
    end
  else  //второй сценарий (не рабочий)
  Form1.MESSAGE_APPLICATION(2, FMain.rgDirectionRepeat.ItemIndex, 1);
end;
From2 не должна УПРАВЛЯТЬ работой главной формы.
Она должна сообщить о своих результатах и все.
----------------
Это ДОЛЖНО быть в Form1OnTimer ПОСЛЕ showModal.
(получили результат и принимаем решение о дальнейших действиях)

после перемещения видно что ontimer и AfterScroll имеют неуправляемую рекурсию.
afterScroll вызвает Ontimer где идет перемещение (Next) что приводит к AfterScroll и ....
----------------
И ПОСКОЛЬКУ это(Next) ни в коем разе не ДОЛЖНО быть вызвано при Scroll, то
НЕ ДЕЛАТЬ там (AfterScroll) вызов обработки, а просто НАПИСАТЬ второй код создания (показа) form2.
===============
по поводу второго кода (и "левого"вызова обработчика события)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 21.08.2015 в 12:52.
evg_m вне форума Ответить с цитированием
Старый 21.08.2015, 14:03   #5
GreenWizard
мальчик-помогай =)
Форумчанин
 
Регистрация: 16.09.2010
Сообщений: 522
По умолчанию

Цитата:
Сообщение от KBO Посмотреть сообщение
Эта программа для учебы англ. слов.
Как я выше писал (про один из сценариев ее работы), при работе в скрытом режиме, она может через заданный промежуток времени, показывать небольшое окно с разными англ.словами, чтоб пользователь мог, их вспоминать (кнопки "да", "нет"), а потом опять закрываться. и опять открываться и т.д.
Т.е. без таймера тут ни как.

А на счет "Show/Hide" - спасибо - это вариант, я как-то о "Hide" - забыл. нужно тогда будет немного событие «TimerRepeatTimer» переделать, т.е сделать 2 ветки: одна на "create/free", другая на "Show/Hide"
Не совсем так всё однозначно с таймером)))
во-первых, таймер не должен знать о Form2 т. е. в OnTimer мы должны только проверить пришло ли время показа (если интервал таймера = периодичности показа, то проверка не нужна, она внутри таймера) и вызвать уже некий showForm2()
во-вторых, во втором сценарии (или первом, не помню) должен быть именно вызов showForm2(), а не обработчика таймера
showForm2() я бы сделал методом главной формы и поручил бы ему создание/показ Form2 + работу с БД, а в Form2 оставил самый минимум, например, оповещение Form1 об ответе пользователя и таймер скрытия формы (скажем, 30 сек на ответ отводим пользователю)

AfterScroll я бы вовсе выпилил т. к. он явно не для этого и могут быть проблемы... как-то так:
Код:
procedure Form1.TimerRepeatTimer(Sender: TObject);
begin
	if not Form1.Visible then // если видна главная форма, то не показывать
		showForm2();
end;

procedure Form1.BitBtnClick(Sender: TObject);
begin
	showForm2();
end;

procedure Form1.BtnHideMode(Sender: TObject);
begin
	RepeatTimer.Enabled := true;
end;

procedure Form1.showForm2();
begin
	Form2.Show;
	// получаем данные с БД ПОЛНОЦЕННЫМ ЗАПРОСОВ... те же LWords
	// SELECT-ом с рандомом или ещё как-то, но точно не в AfterScroll
	////////////////////////////////////////////////// 
	Form2.Run(LWords);
end;

.................................................................
procedure Form2.Run(const LWords: array of string);
begin
	// заполняем форму данными 
	// запускаем TimerHide
end;

procedure Form2.TimerHide(Sender: TObject);
begin
	Hide;
end;

procedure Form2.btnAnswer(Sender: TObject);
begin
	// оповещение об ответе пользователя
end;

Последний раз редактировалось GreenWizard; 21.08.2015 в 14:07.
GreenWizard вне форума Ответить с цитированием
Старый 21.08.2015, 15:15   #6
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Сделал до завтра пока, так

Код:
procedure TForm1.COMBINE_CHECK_FORM;
var
  LRemains: integer;
begin
  if PuNumberCombineRepeat > 0 then
  begin
    if FRepeat <> nil then
    begin
      FRepeat.Hide;
      Enabled := true;
      BringWindowToTop(Form1.Handle);
    end;
    LRemains := ibdsWord.FieldByName('RIGHT_INPUT').AsInteger mod PuNumberCombineRepeat;
    if LRemains = 0 then
    begin
      sbHideEng.Down := false;
      sbHideEng.Click;
      sbHideRus.Down := true;
      sbHideRus.Click;
      if Form2 = nil then
      begin
        Form2 := TForm2.Create(self);
        Form2.Show;
      end
      else Form2.Show;
      Enabled := false;   //
    end;
  end;
end;
И еще такой вопрос:
только из-за
"Enabled := false;" пришлось вставить "BringWindowToTop(FMain.Handle) ;" - т.к. Form1, после того как "LRemains <> 0" - прячется на задний план почему-то.
Хотя на форуме
встретилось, что на это вроде "grid" влияет, хотя не сказано почему???

Но потом - правильно сказал evg_m нужно правильно оформить результат "Form2"
KBO вне форума Ответить с цитированием
Старый 21.08.2015, 15:21   #7
GreenWizard
мальчик-помогай =)
Форумчанин
 
Регистрация: 16.09.2010
Сообщений: 522
По умолчанию

ну, вполне логично: окно создали/показали - сделать его активным
сам в одном проекте писал подобный код т. к. окно новостей захватывало фокус
GreenWizard вне форума Ответить с цитированием
Старый 21.08.2015, 15:37   #8
KBO
Форумчанин
 
Регистрация: 11.06.2010
Сообщений: 525
По умолчанию

Так почему "Enabled := false;", после закрытия "Form2", переводит "Form1" на задний план?
Я взял и такое же сделал на простеньком приложении (в котором одни формы). Так такого не было... Это в общем-то не так нужно, но хотелось бы узнать


Еще немножко полохо, когда "Form2" закрывается и опять открывается, то вся "Form1" перерисовывается (вот бы от этого избавиться, совсем классно было бы!!! :-))

Последний раз редактировалось KBO; 21.08.2015 в 15:45.
KBO вне форума Ответить с цитированием
Старый 22.08.2015, 11:42   #9
GreenWizard
мальчик-помогай =)
Форумчанин
 
Регистрация: 16.09.2010
Сообщений: 522
По умолчанию

Цитата:
Сообщение от KBO Посмотреть сообщение
Так почему "Enabled := false;", после закрытия "Form2", переводит "Form1" на задний план?
Я взял и такое же сделал на простеньком приложении (в котором одни формы). Так такого не было... Это в общем-то не так нужно, но хотелось бы узнать


Еще немножко полохо, когда "Form2" закрывается и опять открывается, то вся "Form1" перерисовывается (вот бы от этого избавиться, совсем классно было бы!!! :-))
Пфф, это ещё фигня, а не причуды! В одном крупном проекте я использовал AlphaControls, которые "супер-пупер и стопиццом працентаф не глючат", и меня чуть ли не до бешенства довёл "баг Delphi"..... я реально думал на Delphi и пол года мирился, писал костыли, а потом мне надоело, начал копать и оказалось, что это из-за устаревшего скина для AlphaControls..... а глюки были огого, оно нифига не хотело корректно менять размеры и рисовать элементы, что выглядело внешне как случайные чёрные/белые области и/или исчезновение кнопок

По теме: это нужно смотреть весь проект, может ты как-то не там окна показываешь и оно моргает
GreenWizard вне форума Ответить с цитированием
Старый 22.08.2015, 12:16   #10
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Такое пишешь, автор?

п.с Советую прислушаться к товарищу evg_m, начиная отсюда
Цитата:
From2 не должна ...
и ниже. Он дело советует
Вложения
Тип файла: zip английский.zip (215.1 Кб, 8 просмотров)
95% сбоев и ошибок приложений, находится в полу метрах от монитора

Последний раз редактировалось JUDAS; 22.08.2015 в 12:21.
JUDAS вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как закрыть форму? MIKE11IPME Windows Forms 8 11.08.2013 02:07
Закрыть вторую форму WhiteForge Общие вопросы Delphi 19 03.11.2012 22:04
Закрыть форму по команде TsaveDialog kta87 Общие вопросы Delphi 10 21.05.2012 20:10
Закрыть и открыть форму Swatch Microsoft Office Access 1 31.05.2010 23:04
Как закрыть форму при показе RIO Общие вопросы Delphi 4 28.08.2009 07:54