Delphi 错误:“无法聚焦禁用或不可见的窗口”

问题描述 投票:0回答:4

我在运行编译的程序时遇到错误。我已采取一切我能想到的预防措施来防止错误,例如在隐藏或聚焦表单之前启用表单。应用程序会显示一个

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;
delphi delphi-xe2
4个回答
6
投票

通常,您将焦点调用到尚未创建的内容(在您正在创建的表单上),请尝试将一些 onCreate 代码移至 onShow。如果没有更多细节,很难判断发生了什么,但试试这个。


0
投票

有时此错误是由 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;

-1
投票

解决方案在 Arioch 'The

发表的评论中给出

您还可以启用“使用调试 DCU”[...]


-1
投票

我下面的回答并没有直接回答您的问题,但它仍然相关,因为您依赖 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”子句中的单元顺序决定了将应用哪个助手。我不喜欢编程语言中如此多的随机性。

© www.soinside.com 2019 - 2024. All rights reserved.