私のアプリケーションはモーダルフォームに基づいています。メインフォームはShowModalで1つのフォームを開き、このフォームはShowModalで別のフォームを開くので、モーダルフォームを積み重ねました。新しいフォームでShowModalを呼び出すと、上に表示されるのではなく、前のフォームの後ろに隠れてしまうという問題が発生することがあります。 Alt + Tabキーを押すと、フォームが一番上に戻りますが、これは適切な解決策ではありません。この問題に遭遇しましたか?また、どのように対処しましたか?
[〜#〜]編集[〜#〜]:
私はDelphi7を使用しています。
Delphiのどのバージョンについては言及していません...
新しいDelphiバージョンでは、TCustomFormにPopupModeとPopupParentという2つの新しいプロパティが追加されています。モーダルダイアログのPopupParentを、そのダイアログを作成しているフォームに設定すると、子フォームがその親の上にとどまるようになります。通常、説明している問題を修正します。
このプロパティのペアはDelphi2006で追加されたと思いますが、2005年であった可能性があります。Delphi2007以降では間違いなく存在します。
編集:Delphi 7を使用していることを確認した後、私が持っている唯一の提案は、モーダルフォームを表示するコードで、フォームの作成を無効にし、戻ったときに再度有効にすることです。これにより、作成ウィンドウが入力を受信できなくなり、Zオーダーを正しく保つことができます。
このようなものが機能する可能性があります(D7を使用しなくなったため、テストされていません)。
procedure TForm1.ShowForm2;
begin
Self.Enabled := False;
try
with TForm2.Create(nil) do
begin
try
if ShowModal = mrOk then
// Returned OK. Do something;
finally
Free;
end;
end;
finally
Self.Enabled := True;
end;
end;
Form2がモーダルウィンドウを作成する場合(前述のとおり)、プロセスを繰り返すだけです。Form2を無効にし、Form3を作成してモーダルで表示し、戻ってきたらForm2を再度有効にします。私が示したように、try..finallyを使用してください。これにより、モーダルフォームで問題が発生した場合、作成フォームが常に再度有効になります。
別の回答を追加して申し訳ありませんが、もう少し調査を行いました。その一部は、以前の回答(DisableProcessWindowsGhosting)が役に立たないことを示しています。この問題を常に再現できるとは限らないため、はっきりとは言えません。
適切と思われる解決策を見つけました。 CreateParamsメソッドのDelphi2007のコードを参照しましたが、かなり一致しています(PopupModeを処理する他のすべてのコードはありません)。
その下にTForm
をサブクラス化するユニットを作成しました。
_unit uModalForms;
interface
uses Forms, Controls, Windows;
type
TModalForm = class(TForm)
protected
procedure CreateParams(var params: TCreateParams); override;
end;
implementation
procedure TModalForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := Screen.ActiveForm.Handle;
if (params.WndParent <> 0) and (IsIconic(params.WndParent)
or not IsWindowVisible(params.WndParent)
or not IsWindowEnabled(params.WndParent)) then
params.WndParent := 0;
if params.WndParent = 0 then
params.WndParent := Application.Handle;
end;
_
次に、このユニットをフォームユニットに含めてから、フォームのクラス(.pasコードファイル内)をclass(TForm)
からclass(TModalForm)
に変更します。
それは私にとってはうまくいき、CodeGearのソリューションに近いようです。
このことから link 問題は2000/XPで導入された「ゴーストウィンドウ」にあるようです。起動時に次のコードを呼び出すことで、ゴースト機能を無効にできます。
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(
GetModuleHandle('user32.dll'),
'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
私が見ることができる唯一の問題は、ユーザーが 応答していないアプリケーションのメインウィンドウを最小化、移動、または閉じる を可能にする機能に問題が発生することです。ただし、この方法では、各呼び出しをSelf.Enabled := False
コードでカバーする必要はありません。
モーダルを開きたいフォームのVisible
プロパティをFalse
に設定するだけです。次に、.ShowModal();
で開くと、機能します。
onShowFormでお試しください:
PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);