Exception handling Lazarus(FreePascal):如何捕获系统错误并抛出异常?

Exception handling Lazarus(FreePascal):如何捕获系统错误并抛出异常?,exception-handling,lazarus,Exception Handling,Lazarus,我试图显示一组Tpanel,供用户用作菜单系统。这一切似乎都很好,但问题是 如果我总是单击第一个项目(即TPanel),那么我也可以单击其他项目。但是,如果我从单击最后一个项目开始,它会在显示项目后显示错误“访问冲突” 奇怪的是,尽管出现了错误,但系统并没有崩溃。所以我启用了调试器(DBG)。现在它崩溃了,错误如下: 一旦程序停止,我会在调试器的历史窗口中看到以下内容。 请注意,我现在并不热衷于修复这个错误,因为我认为这是微不足道的。但是我希望能够在错误发生时捕获它并做一些事情(现在我想忽略

我试图显示一组Tpanel,供用户用作菜单系统。这一切似乎都很好,但问题是

如果我总是单击第一个项目(即TPanel),那么我也可以单击其他项目。但是,如果我从单击最后一个项目开始,它会在显示项目后显示错误“访问冲突”

奇怪的是,尽管出现了错误,但系统并没有崩溃。所以我启用了调试器(DBG)。现在它崩溃了,错误如下:

一旦程序停止,我会在调试器的历史窗口中看到以下内容。

请注意,我现在并不热衷于修复这个错误,因为我认为这是微不足道的。但是我希望能够在错误发生时捕获它并做一些事情(现在我想忽略它)

我正在使用Ubuntu12.04和Lazarus 1.0.10。 我使用的方法必须适用于WINDOWS和LINUX


提前感谢您的帮助

通常,要捕获异常,有一个块。当然,您的目标不是捕获异常并忽略它,而是在代码中找到它并修复问题的根源。当然,在某些情况下,异常的风险很高或是预期的,因此有必要使用块。我们以这种方式附上的代码块:

procedure TForm1.Button1Click(Sender: TObject);
var
  NotExistingPanel: TPanel;
begin
  try
    NotExistingPanel.Caption := ''; // <- this will raise an access violation
  except
    on E: Exception do
      ShowMessage('An exception was raised: ' + E.Message);
  end;
end;
procedure TForm1.按钮1点击(发送方:TObject);
变量
注现有面板:TPanel;
开始
尝试

NoteExistingPanel.标题:='';// 首先,非常感谢TLama提供的所有解释和指导。我不得不接受他的回答,因为我的答案是建立在这个基础上的。我只是将此作为一个答案发布,以便另一个Lazarus的初学者可能会发现这很有用。我不是在暗示这是最好的事情,但这是我现在想要做的。也就是说,当某个异常发生时,我希望捕获它并处理它

鉴于此,

  • 我正在动态创建一组看起来像按钮的Tpanel
  • 每个TPanel都指定了一个鼠标单击事件
  • 让我们假设有10个这样的“按钮”(实际上是Tpanel)

    问题是: 当我第一次点击第一个按钮时,我可以点击另一个按钮(例如:第五个)。但是,如果我第一次单击第五个或第一个以外的任何内容,程序将抛出“访问冲突”错误。然而,请注意,尽管有关于数据损坏和其他问题的可怕警告,程序不会崩溃。因此,用户只需单击ok并继续。奇怪的是,随着随后的点击,这个问题减少了!我知道这很有趣

    现在,正如TLama所解释的,当鼠标在点击按钮后被释放时,就会发生错误

    但这是我的问题。。。我没有鼠标移动事件。这是帕斯卡的一部分

    现在,我想忽略mouseup事件(至少现在是这样)。一定有更好的办法

    但还有另一个问题。我不能忽视我没有的东西!而且我没有鼠标移动事件。因此,我最终决定在应用程序级别捕获此错误,如下所示:

    在主窗体上,我输入以下代码:

    procedure TfrmMainForm.CatchErr(Sender: TObject; e:exception);
    begin
      if e.Message <> 'Access violation' then ShowMessage('MOL: ' + e.Message);
    end; 
    
    (目前)我可以绕过这个问题

    正如特拉马所指出的,这再次不是一个好建议。尽管如此,这是我想要做的

    更难的是,错误发生在control.inc.的mouseup中。这不是我的档案。而是拉撒路的一部分。我认为如果我们有办法告诉Lazarus删除代码中TPanels的事件会更好。我认为这涉及到为它重新编写一个派生类,我现在看不出这对我有什么好处:)


    再次感谢特拉玛

    是的,你说得对。在MouseUp上触发访问冲突错误。虽然我没有,但它是Pascal系统的一部分。i、 例如,当我点击某个按钮(面板)时,显然会有一个鼠标。我想鼠标是在按钮被移除后启动的。所以没有真正的解决方案,只有通过一个异常来逃避。但我只想忽略这种情况。因此,需要通过一些错误代码捕获异常。好吧,如果我能避免错误,那就太好了,但我首先需要检测这个特定的错误。访问冲突很难跟踪。理想情况下,使用调试器通过设置断点和步进程序流来跟踪它。我几乎可以肯定地告诉您,它发生在
    OnMouseUp
    事件中(因为调试器历史记录报告的
    DoMouseUp
    方法刚刚触发
    OnMouseUp
    事件)。但是我不能在没有看到代码的情况下为您提供更多帮助…错误可能是因为您正在删除它自己的click或MouseDown事件中的面板。您可以通过使用计时器执行面板删除来轻松避免此问题(创建延迟为1的禁用计时器,并在需要删除面板时启用它)。@VitaliyG是的,您非常正确。事实上,如果我在每个按钮出现后放置一个消息框,这会导致延迟,并且我永远不会得到错误。但我并不完全赞成人为拖延。来自VB6背景(用于视觉编码),我们使用了这些技巧,但来吧,我们在这里使用Pascal:)无论如何,谢谢你,我认为你的技术现在应该很好。
    Application.OnException:=@CatchErr;