无法隐藏尚未完全初始化的窗口

时间:2014-01-30 17:14:15

标签: delphi tform

我有这种尴尬的情况导致异常。我发现了这个问题,但解决方案对我来说实施起来非常棘手。

在我们的应用程序中,如果用户在一段时间内保持活动状态,则安全超时程序会启动用户提示密码输入框。

但是,每当表单在FormShow()事件期间因任何特定原因显示消息框时(此处需要注意的事项; formShow事件执行尚未完全完成)和用户决定不单击对话框的“确定”按钮一段时间,安全代码启动并尝试隐藏所有表单,以便提示输入密码。 此方案将触发异常“无法在OnShow或OnHide中更改Visible”

安全代码使用TScreen.FormCount循环所有表单,并分别使用TForm(TScreen.Forms[ii]).Hide隐藏它们。隐藏程序会导致异常,因为我觉得这个表单还没有完全完成它的加载程序。

我已经完成了测试,如果在执行FormShow()事件后显示一个消息框,则安全代码可以正常工作,并且可以毫无问题地隐藏所有窗口。

我已经尝试了几个属性和窗口消息检查,在隐藏表单之前执行“if check”,比如Screen.Forms [ii] .Visible,Screen.Forms [ii]。活跃但到目前为止没有运气。提到的表格将是可见的,并且不能保证它将处于活动状态,如果它处于活动状态,我将如何隐藏其他非活动表格。所以我的问题是,哪个属性或Windows消息表明表单已完全加载,或者至少它已超过FormShow中存在的任何给定表单的TScreen.Forms事件?

我需要回答我要问的问题,我需要一个需要在安全代码中实现的通用解决方案,我不能通过我们在这个巨大的应用程序中的一千多种形式,并单独尝试查找这些形式中存在任何验证/警告逻辑的解决方案。

谢谢

2 个答案:

答案 0 :(得分:3)

简单的答案是停止在所有者表单的OnShow中显示模式对话框。在显示模式对话框之前,请等待表单完成显示。如果您进行了更改,并且仅进行了更改,则现有代码将开始工作。

您选择的问题标题是:

  

无法隐藏尚未完全初始化的窗口

所以显而易见的解决方案是等到窗口完全初始化。

实现此目的的最简单方法是将当前在OnShow中运行的代码移动到CM_SHOWINGCHANGED的处理程序中:

procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;

像这样实施:

procedure TMyForm.CMShowingChanged(var Message: TMessage);
begin
  inherited; // this is what invokes OnShow
  if Visible then
  begin
    // do what you previously did in OnShow
  end;
end;

答案 1 :(得分:0)

David Heffernan的解决方案给了我一个想法,我在最后解决了这个问题。

我创建了以下内容;

const
  WM_SHOW_MESSAGE = WM_USER + 1;

private
  procedure WMShowMessage(var Msg: TMessage); message WM_SHOW_MESSAGE; 

内部构造函数;

PostMessage(Handle, WM_SHOW_MESSAGE, 0, 0); 

这将有消息框逻辑:

procedure MyMethod.WMShowMessage(var msg: TMessage); message WM_SHOW_MESSAGE;