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;
この順序で実行すると、モーダル フォームがメイン フォームの上に正しく表示されます。しかし、行を逆にすると、モーダル フォームがメインの後ろに隠れてしまいます。(1) とマークされた行は、モーダル フォームのプロパティを設定します。これにより、TRzPageControl (Raize コンポーネントから) にある TRzCheckGroup でいくつかのチェックボックスがオンまたはオフになります。これは、上記の行 (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 (セッター コードの実行時に操作される) を指している可能性がありますが、同じ問題を示し、TRzCheckGroup (または TRzPageControl) を使用しない他の 2 つのフォームがあります。また、Raize コンポーネントを使用した別のサンプル アプリでは問題を再現できませんでした。セッターの期間中、フォーム、ページコントロール、または 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;
エディターに 1 文字を割り当てると、フォームが再び非表示になり始めます。
procedure TEditorForm.SetAsText(const Value: string);
begin
Editor.Text := 'a'; // Problem is back
end;
もちろん、他の 2 つの問題のあるフォームは、このエディター コンポーネントまたはそのユニットを使用していません。
メモコントロールを削除して再度追加しようとしましたが(作成順序などを考えてください)、効果はありませんでした。コードでメモを作成する場合も同様です。空でない文字列がメモの Text プロパティに割り当てられるとすぐに、フォームは非表示になります。