0

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

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

但是,每当表单FormShow()由于任何特定原因在事件期间显示消息框(这里要注意的事情;formShow事件执行尚未完全完成)并且用户决定不单击对话框的确定​​按钮时某个时间,安全码会启动并尝试隐藏所有表单,以便提示密码。这种情况会触发异常"Cannot change Visible in OnShow or OnHide"

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

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

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

我需要一个我所问问题的答案,我需要一个需要在安全代码中实现的通用解决方案,我无法通过我们在这个巨大的应用程序中拥有的一千多个表格并单独尝试找到任何解决方案这些表单中存在验证/警告逻辑。

谢谢

4

2 回答 2

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;
于 2014-01-30T17:24:12.050 回答
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;
于 2014-01-30T20:16:50.263 回答