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

Mar*_*ski 10 delphi modal-dialog stayontop

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

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

modalForm.PopupParent := self;
Run Code Online (Sandbox Code Playgroud)

就在调用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;
Run Code Online (Sandbox Code Playgroud)

按此顺序执行时,模态窗体正确显示在主窗体的顶部.但当我扭转线条时,模态形式隐藏在主线之后.标记为(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;
Run Code Online (Sandbox Code Playgroud)

如果线条(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;
Run Code Online (Sandbox Code Playgroud)

当我将赋值更改为空字符串时,表单显示正确:

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

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

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

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

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

小智 -1

Windows 不支持应用程序的许多最顶级表单。模态形式默认位于最上面。但你有适合你自己的形式的这种风格。

记住一个决定:删除主窗体的最上面(没有可见效果),调用模态窗体,在模态完成时设置回最上面的样式。