2

我正在尝试显示一组 TPANEL 供用户用作菜单系统。一切似乎都很好,但这是问题所在。

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

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

一旦程序停止,我会在调试器的历史记录窗口中看到以下内容。 在此处输入图像描述

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

我正在使用带有 Lazarus 1.0.10 的 Ubuntu 12.04。我使用的方法必须适用于WINDOWS 和LINUX。

提前感谢您的帮助!

4

2 回答 2

4

通常,要捕获异常,有try..except块。当然,您的目标不是捕获异常并忽略它,而是在您的代码中找到它并修复问题的根源。当然,可能存在异常风险很高或预期的情况,因此需要使用try..except块。我们以这种方式封装的那些代码块:

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;

您的问题将出现在OnMouseUp某些控件的事件处理程序中,并且是由访问内存引起的,CPU 无法物理解决。例如,当您访问尚未创建或已释放的对象时,可能会发生这种情况,但也有许多不同的方式导致访问冲突。

于 2013-08-12T06:42:32.630 回答
2

首先,非常感谢TLama的所有解释和指导。我必须接受他的回答,因为我已经在此基础上构建了我的答案。我只是将其发布为答案,以便另一个 Lazarus 初学者可能会发现这很有用。无论如何,我并不是说这是最好的事情,但这是我现在想做的事情。也就是当某个异常发生时,我想捕获它并处理它。

鉴于,

  1. 我正在动态创建一组 TPanel 看起来像按钮
  2. 每个 TPanel 都为其分配了一个 mouseclick 事件

假设有 10 个这样的“按钮”(实际上是 TPanel)。

问题:当我第一次单击第一个按钮时,我可以单击另一个(例如:第 5 个)。但是,如果我首先单击第 5 个或第一个以外的任何其他内容,则程序会引发“访问冲突”错误。但是请注意,尽管关于数据损坏和其他东西的丑陋警告,该程序不会崩溃。所以用户可以简单地点击确定并继续。奇怪的是,随着随后的点击,这个问题减少了!我知道这很有趣。

现在,正如 TLama 所解释的,在单击按钮后释放鼠标时会发生错误。

但这是我的问题......我没有 mouseup 事件。这是帕斯卡的一部分。

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

但还有另一个问题。我不能忽视我没有的!而且我没有 mouseup 事件。所以我最终决定在应用程序级别捕获这个错误,如下所示:

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

procedure TfrmMainForm.CatchErr(Sender: TObject; e:exception);
begin
  if e.Message <> 'Access violation' then ShowMessage('MOL: ' + e.Message);
end; 

然后在创建表单时,我输入了这个:

Application.OnException:=@CatchErr;

而且(现在)我可以绕过这个问题。

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

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

再次感谢特拉玛!

于 2013-08-12T12:15:19.697 回答