Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Обработка ошибки! try...except


Автор: Susel 13.1.2006, 17:04
Есть 2-а собственных компонента TMyPanel и TMyExtLookupEdit - наследники TPanel и TdxInplaceExtLookupEdit соответственно.
TMyPanel - связанные панели, т.е. есть ссылка (свойство такого же типа TMyPanel) на предыдущую панель PrevPanel и на следующую NextPanel.

Для TMyPanel определена процедура:
Код

    procedure CMVisibleChanged(var Message: TMessage);message CM_VISIBLECHANGED;
    ...
      if Visible and Assigned(FPrevPanel) then
        FPrevPanel.Enabled:=false; 
    ....


Для TMyExtLookupEdit переопределена процедура DoExit таким образом, что в случае неверного ввода генерируется ошибка:
Код
 raise Exception.Create... 


Есть форма содержащая MyPanel1 и MyPanel2. MyPanel1 содержит MyExtLookupEdit1. Форма имеет следующий код:
Код

      try
        curPanel.ShowNext;
      except
        curPanel.HideNext;
        raise;
      end;


ShowNext и HideNext равносильны curPanel.NextPanel.Visible:=true и curPanel.NextPanel.Visible:=false соответственно.

Проблема в том, что при возникновении ошибки (введено неверное значение в MyExtLookupEdit1) ошибка генерируется и сообщение об ошибке появляется, но управление не передается в блок except и следующая панель остается видимой.

Автор: _hunter 13.1.2006, 17:14
значит исключение бросает не curPanel.ShowNext

Автор: Susel 13.1.2006, 17:23
В режиме трассировки ставлю точку остановки на curPanel.ShowNext в блоке try, нажимаю F8 - получаю ошибку, но управление блоку except не передается.... smile

Автор: Alexeis 13.1.2006, 17:32
В режиме трасировки и при запуске из delpi исключения вызываются всегда - это не значит что програма работает с ошибками.

Автор: Susel 13.1.2006, 17:40
alexeis1
Чёт не понял к чему это!?
При запуске exe - ошибка также успешно генерируется, но следующая панель не исчезает!

Автор: ShadeSt 13.1.2006, 17:43
может быть такое что ты уже обрабатываешь эту ошибку..
Код

Procedure DoSome;
Begin
  Try
     что то с ошибкой
  Except
  End;
End;


Procedure ShowNext
Begin
  Try
    DoSome
  Except
    ShowMessage(...);
  End
End;


Получается что у тебя есть ошибка при вызове DoSome, но в процедуре ShowNext ты не попадешь в блок Except.

Автор: Susel 13.1.2006, 17:49
ShadeSt
Проверял, нет такого.....
Да и как правило, если обрабатываю ошибки - ставлю raise, т.е. не подавляю сообщение об ошибке, как в твоем примере...

Автор: _hunter 13.1.2006, 17:54
Цитата(Susel @ 13.1.2006, 16:23 Найти цитируемый пост)

но управление блоку except не передается

а куда передается?

Автор: ShadeSt 13.1.2006, 17:59
Тогда интересно в обработчике какого события ошибка и где ты ее потом хочешь поймать?
Вне этого обработчика что ли?

Автор: Susel 13.1.2006, 18:00
_hunter
Передается следующей за блоком try...except инструкции.......

Автор: ShadeSt 13.1.2006, 18:03
Код

      try    
        curPanel.ShowNext;    
      except    
        curPanel.HideNext;    
        raise;    
      end;


Если ты хочешь поймать тут ошибку, то надо чтобы она была в процедуре ShowNext.
А исключение при неверном вводе, у тебя где?? в TEdit.OnExit?

Автор: _hunter 13.1.2006, 18:15
создай тестовый проект в котором просто кинь исключение и попробуй его поймать.
потом перенеси код в этот проект -- посмотри что будет.
может ты обработку исключений отключил...

Автор: Susel 13.1.2006, 18:21
Да, исключение можно сказать в OnExit (на самом деле в DoExit), но DoExit фактически вызывается в ShowNext, хотя и через сообщение винды......
Добавлено @ 18:34
_hunter
В блоке try сгенерировал деление на 0 - except отработал, однако если деление на ноль генерирую в DoExit - управление блоку except не передается......

Автор: _hunter 13.1.2006, 18:55
значит где-то в ShowNext стоит свой обработчик.

Автор: Susel 13.1.2006, 19:04
Ну нет там обработчика....нет..... smile
Добавлено @ 19:16
Приведу больше кода:

Код

procedure TTrxSQLPanel.ShowNext;
begin
  if NextPanel<>nil then
    NextPanel.Show;
end;


Код

procedure TTrxSQLPanel.CMVisibleChanged(var Message: TMessage); \\Обработчик сообщения CM_VISIBLECHANGED
begin
... \\никаких обработчиков ошибок тут тоже нет
  if Visible then
  begin
  ...
        FPrevPanel.Enabled:=false;
        GetFirstCanFocus.SetFocus;
  ...
  end
...
end;



Код

procedure TTrxOraCustomExtLookupEdit.DoExit;
begin
...
        raise Exception.Create('Ошибка!');
...
  inherited;
end;

Автор: _hunter 13.1.2006, 19:30
так обработка сообщений идет в совсем другом контексте.
т.е. что происходит:
вызываем curPanel.ShowNext, она шлет сообщение, происходит выход из блока try ( потому как исключений нет ) курсор становится на строку за блоком и в это время сообщение доходит до адресата -- появляется исключение. ну а дальше все понятно smile

Автор: Susel 13.1.2006, 19:37
_hunter
Т.е. исключение на ShowNext происходит только лишь в режиме трассировки!? На самом деле отрабатывают все инструкции после блока try...except, и только потом возникает ошибка!?
Добавлено @ 19:39
Где же её тогда перехватывать!?

Автор: _hunter 13.1.2006, 19:47
нет, в режиме "без отладки" это исключение тоже появится и тоже проскочи мимо.
ловить его нужно там, где оно бросается. т.е. на самом высоком уровне приемника сообщений.
в данном случае в CMVisibleChanged(

Автор: Susel 14.1.2006, 11:23
Попробовал отловить в CMVisibleChanged - результат тот же.....при возникновении ошибки выполняется инструция следующая за блоком try...except... smile

Вот:
Код

procedure TTrxSQLPanel.CMVisibleChanged(var Message: TMessage);
begin
  try
  ...
          FPrevPanel.Enabled:=false;
  ...
  except
    raise;
  end;
  showmessage('Тест');
end;


Сначала появляется сообщение об ошибке, а затем появляется сообщение "Тест"...

Автор: Alex 14.1.2006, 11:30
Выложи здесть или пришли на почту, тестовый проект и свои компоненты

Автор: Susel 14.1.2006, 14:14
Выкладываю тестовый пример с тестовыми компонентами. Расширение pas нужно изменить на rar.....

Автор: Alex 15.1.2006, 03:01
Твое сообщение перехватывают в модуле Controls
Код

procedure TWinControl.MainWndProc(var Message: TMessage);
begin
  try
    try
      WindowProc(Message);
    finally
      FreeDeviceContexts;
      FreeMemoryContexts;
    end;
  except
    Application.HandleException(Self);
  end;
end;

Автор: Susel 16.1.2006, 10:47
А как же мне его отловить!?

Автор: _hunter 16.1.2006, 12:49
замени оконную процедуру...

Автор: Alex 16.1.2006, 12:53
Можно конечно и заменить оконную процедуру, но может стоит подумать "стоит ли игра свечь?" Может проще поделиться с людьми идеей, которую хочешь сделать и они предложат вариант при котором не нужно будет переписывать все компоненты, которые хочется положить на эту панель...

Автор: Susel 16.1.2006, 17:22
Да идея то прозрачна из примера, на форме есть набор связанных панелей, которые должны появляться друг за другом по нажатию определённой клавиши, при этом предыдущая панель не должна быть доступна для редактирования. Есть комбобокс, на который вешается некоторое условие проверки (на основе информации из БД) и в случае неудовлетворительной проверки комбобокс не должен терять фокуса, т.е. из него не возможно выйти, а следовательно и следующая панель не должна появиться.

Вот в общем то в кратце и вся идея (правда кроме перечисленного и панель и комбобокс обладают ещё рядом дополнительных возможностей, не относящихся к вопросу)

Автор: Alex 16.1.2006, 18:10
По мне проще проверку качества заполнения данных вынести из компонентов и делать ее перед созданием новой панели. Или кто мешает Вызвать OnExit у компонентов до создания новой панели?

Автор: Susel 16.1.2006, 18:54
Цитата

По мне проще проверку качества заполнения данных вынести из компонентов и делать ее перед созданием новой панели.


Дело в том, что проверка содержимого производится при помощи SQL запроса, в качестве параметра используюещего введённое значение. Причем запрос для проверки настраивается (хранится в одной из системных таблиц).

Цитата

Или кто мешает Вызвать OnExit у компонентов до создания новой панели?


События OnExit для компонентов могут быть и не определены, а проверку делать нужно.....
Допустим что вызвали OnExit для всех компонентов, но в случае ошибки как я понял опять же ошибка будет перехвачена оконной процедурой!

Автор: Susel 18.1.2006, 16:12
Неужели данную проблему таки можно решить, только переписав оконную процедуру!? smile

Автор: _hunter 18.1.2006, 16:32
учитывая что это проблема места обработки...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)