在Delphi XE中“保持最佳”主窗体和模态对话框

时间:2011-09-22 16:02:30

标签: delphi modal-dialog stayontop

在Delphi XE Update 1中,如果父(主)表单的FormStyle设置为 fsStayOnTop ,我将获得模态表单的看似随机行为

1)使用MainFormOnTaskbar:= False(旧方法),一切都“正常”。使用新的MainFormOnTaskbar:= True,当主窗体设置为“保持在最顶层”时,模态窗体隐藏在主窗体后面。在大多数情况下说

modalForm.PopupParent := self;

在调用modalForm.ShowModal之前似乎有所帮助。 但并非总是如此。

2)我所有的模态形式都很简单,没有多余的装饰,定位在MainFormCenter,没有使用表单继承等。然而PopupParent修复仅适用于其中一半,而另一半仍然隐藏在主窗体后面。最奇怪的是,在一种情况下,不相关的代码行的排序会破坏或产生它。请参阅此代码中标记为(1)和(2)的行:

procedure TEchoMainForm.DBMaintenancePrompt( actions : TMaintenanceActions );
var
  frm : TDBMaintenanceForm;
begin
  frm := TDBMaintenanceForm.Create( self );
  try
    frm.Actions := actions; // (1)
    frm.PopupParent := self; // (2)
    frm.ShowModal;
  finally
    frm.Free;
  end;
end;

按此顺序执行时,模态窗体正确显示在主窗体的顶部。 但是当我反转这些线时,模态形式隐藏在main之后。标记为(1)的行设置了模态形式的属性,这导致在TRzCheckGroup中未选中的几个复选框被检查,坐在一个TRzPageControl(来自Raize组件)。这是上面第(1)行执行时运行的setter方法:

procedure TDBMaintenanceForm.SetActions(const Value: TMaintenanceActions);
var
  ma : TMaintenanceAction;
begin
  for ma := low( ma ) to high( ma ) do
    cgMaintActions.ItemChecked[ ord( ma )] := ( ma in Value );
  end;
end;

如果线条(1)和(2)的顺序相反,这足以使模式形式显示在主窗体后面。

这可能指向TRzCheckGroup(当setter代码运行时会被操纵),但我有两个其他形式显示相同的问题,并且不使用TRzCheckGroup(或TRzPageControl)。我无法使用Raize组件使用单独的示例应用程序重现问题。在setter的持续时间内禁用表单,pagecontrol或TRzCheckGroup无效。

它似乎不是一个计时问题,因为当模态表单显示隐藏一次时,它总是这样。行为的改变只来自重新排列代码行。

3)最后一次观察:我的模态形式相当简单,因此它们可以立即显示,没有明显的延迟。但是当主窗体是fsStayOnTop时,我常常会看到模态窗体显示在它上面,然后看到它被“推”到后面。然后,在击中Esc时,(不可见)模态形式显示在主窗体的顶部几分之一秒,然后关闭。

我不知道事后看来显而易见的东西,或者这是一个心理调试的呼唤,我不知道。有什么想法吗?


更新即可。我试图在另一种形式上追踪问题。它有几个按钮(Raize)和一个TSyntaxMemo(来自eControl.ru的增强备忘录组件)。这种形式与遇到问题的其他形式几乎没有任何共同之处。删除部分代码并进行测试后,我现在可以通过在为备忘录组件分配字符串的方法中进行微小更改来重现该问题:

这是我的原始代码,它使包含编辑器的表单隐藏在主表单后面:

procedure TEditorForm.SetAsText(const Value: string);
begin
  Editor.Text := Value;
end;

当我将分配更改为空字符串时,表单会正确显示:

procedure TEditorForm.SetAsText(const Value: string);
begin
  Editor.Text := ''; // CRAZY! Problem goes away
end;

当我将单个字符分配给编辑器时,表单会再次开始隐藏:

procedure TEditorForm.SetAsText(const Value: string);
begin
  Editor.Text := 'a'; // Problem is back
end;

当然,其他两个有问题的表单不使用此编辑器组件或其任何单元。

我尝试删除备忘录控件并再次添加(想想创建顺序等),但它没有效果。如果我在代码中创建备忘录也是如此。只要将非空字符串分配给备忘录的Text属性,表单就会隐藏。

2 个答案:

答案 0 :(得分:0)

我前段时间遇到过同样的问题。我的解决方案是在模态表单的Self.BringToFront;事件中添加OnShow

答案 1 :(得分:-1)

Windows不支持许多应用程序的最顶层表单。默认情况下,模态形式是最重要的。但是你有自己的风格。

一个决定:删除主要表单的最顶层(没有可见效果),调用模态表单,在模态完成时设置最顶层样式。