我在运行编译的程序时遇到错误。我已采取一切我能想到的预防措施来防止错误,例如在隐藏或聚焦表单之前启用表单。应用程序会显示一个
DimmerForm
(灰色淡入淡出叠加层),然后在叠加层顶部显示一个 NewFileForm
。 NewFileForm
执行其任务并确定要创建的文件,并在 tabsheet
上的页面控件中创建新的 MainForm
并显示新创建的选项卡表。到目前为止,所有这些都有效(我可以在 NewFileForm
关闭之前中断并发生任何错误,并看到选项卡已成功创建并显示)。然后 NewFileForm
关闭,再次正常工作。
当任何东西试图将焦点设置回
MainForm
时,就会发生错误。隐藏 DimmerForm
,或者点击 MainForm
,或者通过代码将焦点设置到 MainForm
都会导致出现错误消息。将代码放在 {try
, except
, end
} 中也不会阻止错误消息。我已经搜索了代码中可能由 MainForm
聚焦触发的所有其他方法,并且在错误发生之前没有输入任何方法(因此不会导致错误)。
我在应用程序的先前版本中编写了几乎完全相同的代码,然后决定从头开始重组它。该应用程序的先前版本在表单聚焦方面运行顺利。
这是打开
NewFileForm
的代码:
procedure TMainForm.NewFilesToolButtonClick(Sender: TObject);
begin
ShowDimmer;
NewFileForm.ShowModal;
HideDimmer;
end;
这里是显示调光器形式的代码:
procedure ShowDimmer;
begin
// Enable to prevent errors
DimmerForm.Enabled := true;
// Hide dimmer form and show mainform
DimmerForm.Show;
end;
以下是隐藏调光器表单的代码:
procedure HideDimmer;
begin
// Enable to prevent errors
DimmerForm.Enabled := true;
MainForm.Enabled := true;
// Hide dimmer form and show mainform
DimmerForm.Hide;
MainForm.SetFocus;
end;
通常,您将焦点调用到尚未创建的内容(在您正在创建的表单上),请尝试将一些 onCreate 代码移至 onShow。如果没有更多细节,很难判断发生了什么,但试试这个。
有时此错误是由 Post 事件期间数据库组件的某种活动引起的... 如果您尝试了其他所有方法,您可以尝试这个快速解决方案:将连接到数据集的数据源设置为 NIL,然后在 Post 事件完成后将其设置回来。
类似这样的:
Try
Datasource1.DataSet := NIL;
Try
Query1.Post;
Except
On E: Exception Do
Begin
ShowMessage('Post error!' + #13#10 + #13#10 + E.Message);
Exit;
End;
End;
Finally
Datasource1.DataSet := Query1;
End;
解决方案在 Arioch 'The
发表的评论中给出您还可以启用“使用调试 DCU”[...]
我下面的回答并没有直接回答您的问题,但它仍然相关,因为您依赖 CanFocus。 CanFocus 撒了谎。你不应该依赖它。文档也是错误的。更准确地说,即使控件不可聚焦,CanFocus 也可以返回 True。在这种情况下,将会引发异常。
所以,用这个代替:
function CanFocus(Control: TWinControl): Boolean;
begin
Result:= Control.CanFocus AND Control.Enabled AND Control.Visible;
if Result
AND NOT Control.InheritsFrom(TForm)
then
{ Recursive call:
This control might be hosted by a panel, which could be also invisible/disabled.
So, we need to check all the parents down the road, until we encounter the parent Form.
Also see: GetParentForm }
Result:= CanFocus(Control.Parent); { Parent of a control could be nil, but in this case Control.CanFocus will deal with that.}
end;
procedure SetFocus(Control: TWinControl);
begin
if CanFocus(Control)
then Control.SetFocus;
end;
PS:在Lazarus下CanFocus工作正常。
2023 年更新
请参阅这篇有关 CanFocus 的新文章以及如何修复它。 您甚至可以找到一个工具,可以用固定函数 SetFocus() 替换所有 Control.SetFocus 方法。
理由:
我不喜欢类助手,因为如果同一类有多个类助手,则将使用唯一的一个。这个过程几乎是“掷骰子”:“uses”子句中的单元顺序决定了将应用哪个助手。我不喜欢编程语言中如此多的随机性。