16

Windows 98 時代以降、一部のダイアログで Z オーダーが失われ、以前の形式に戻ることが何度もありました。

例えば:

Dialog1.ShowModal;

Dialog1.OnClickButton() : ShowMessage('anything');

MessageBox が表示されると、フォーカスがなく、Dialog1 の下に移動することがあります。ユーザーはそれについて混乱しています。ただし、Alt+Tab を使用して別のアプリに移動して戻ると、フォーカスが MessageBox に戻り、それがフォアグラウンド ウィンドウになります。

これは、ShowMessage、MessageBox、通常のフォーム、および QuickReport フォームで経験しています。

誰もこれについて知っていますか?Windowsのバグですか?どうすればそれを防ぐことができますか? これをどう捉えるか?

助けてくれてありがとう: dd


Win98 以降とは本当に言ったので、すべての OS (Win7 も) がこの問題の影響を受けます。Delphi 6 Prof を使用したため、プロパティはデフォルト フォームでは機能しません。

メッセージ ダイアログは MessageBox + MB_APPLMODAL で制御できると誰かが言っていました。これは朗報ですが、多くの古いフォームやコンポーネント、サード パーティ ツールがあります。

そのため、フォームを差し替えてまったく新しい申請書を作成するのは大変な作業です。

しかし、これをやってみます。

答えは、これはアプリケーションの問題と Windows の問題の半分だということだと思います。Windows がこれを処理する場合と処理しない場合がある場合、それは Windows のバグのようです。しかし、適切なモーダル ウィンドウの作成を強制できる場合、それはプログラミングのバグです。

誰かが WS_POPUP フラグの意味を説明できますか? それは何らかの副作用がありますか、それともありませんか?

ありがとう: dd

4

4 に答える 4

16

それがPopupModePopupParentプロパティの目的です。

たとえば、次のことができます。

Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;

これにより、Windowsに正しいZオーダーが通知されます。

于 2010-06-08T13:09:23.887 に答える
7

古いバージョンのdelphi(Delphi 2007より前)の場合、メインフォーム以外のフォーム:

interface
  TMyForm = Class(TForm)
  protected
    procedure CreateParams(var Para: TCreateParams); override;
  end;
...
implementation
...
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
  inherited;
  Para.Style := Para.Style or WS_POPUP;
  { WinXP Window manager requires this for proper Z-Ordering }
  // Para.WndParent:=GetActiveWindow;
  Para.WndParent := Application.MainForm.Handle;
end;

メッセージボックスの場合、フラグにMB_TOPMOSTを含めます。

Application.MessageBox(PChar(amessage), PChar(atitle),    otherflags or MB_TOPMOST);
于 2010-06-08T17:29:14.470 に答える
0

私が最近使用したトリックは、各フォームの作成中に次の 2 行のコードを適用することでした。

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
  WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);

ハンドルは、フォームのハンドル (Form1.Handle) です。WS_EX_APPWINDOW 部分は、各ウィンドウをタスク バーに表示します。追加の効果が必要ない場合は削除してください。

私のメイン フォームでは、次の行を使用します。

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
  WS_EX_TOPMOST);

また、この関数を使用してカスタム ダイアログを作成します (エラー、確認など、ダイアログのスタイルごとに新しい関数を作成しました)。

function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
  const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
begin
  Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
  with Result do
    begin
      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
        WS_EX_APPWINDOW or WS_EX_TOPMOST);
      SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
      FormStyle := fsStayOnTop;
      BringToFront;
    end;
end;

もちろん、このFormStyle := fsStayOnTop;部分はオプションですが、確認ダイアログとエラー ダイアログが常にユーザーに表示されるようにするために使用しています。

少し手間がかかるように思えますが、最終的な効果として、フォームが誤って他のフォームの背後に隠れてしまうことを心配する必要がなくなりました。

于 2011-08-31T11:24:27.810 に答える
0

このページと FAQ を 30 分間見ましたが、まだコメントを投稿する方法が見つかりません。このプロトコル違反をお許しください。

まず第一に、ポスターの IMHO が Windows 98 を使用していないことを明確にしたいと思います。彼は「Windows 98 時代以降」と書いていますが、これは、98 以降の Windows バージョンでこの問題が発生していることを意味していると理解しています。

私もこの問題 (CB2009) を抱えているので、ポスターの質問「それは Windows のバグですか?」を強調したいと思います。Delphi/Builder のバグである場合、回避する方法はありますか? すべての潜在的なダイアログをインターセプトすることが実行可能な解決策であることがわかりません。また、fsStayOnTop の使用を避けることもできません。メインフォームの上に置く必要がある設定フォームがありますが、設定フォームは、特定の条件下で設定フォームの下に消えるダイアログをポップアップすることができます。

zオーダーのサポートがどこでうまくいかないかを理解できれば、それを回避する方法の手がかりが得られる可能性があるため、非常に役立ちます。

于 2010-06-09T10:49:45.200 に答える