5

いくつかの複雑なデータを操作できるフォーム (以下の例では TBigForm) があり、追加情報を表示する必要があります。この情報を fsStayOnTop フォーム (例では OnTopForm) に入れて、常に表示されるようにしますが、必要に応じて移動できるようにします。現在、TBigForm の一部のユーザー アクションがモーダル フォームを表示すると、これは多くの場合、OnTopForm の背後に隠れてしまい、アプリがフリーズしているように見えます。どうすればこれを回避できますか? (検索すると非常に多くのヒットが得られますが、それらから解決策を抽出することはできませんでした。)

私の実際のアプリでは、モーダル フォームが表示される場所がたくさんあるので、これらの呼び出しをすべて変更することは避けたいと思います。

: 新しい VCL アプリケーションを作成し、TButton を Form1 にドロップし、ボタンをダブルクリックして、生成された Button1Click 実装スタブを次のように置き換えます。

type
  TBigForm = class(TForm)
  strict private
    OnTopForm: TForm;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  protected
    procedure DoHide; override;
    procedure DoShow; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

{ TBigForm }

procedure TBigForm.Button1Click(Sender: TObject);
begin
  ShowMessage('Test');
end;

constructor TBigForm.Create(AOwner: TComponent);
begin
  inherited CreateNew(AOwner);

  Caption := 'Big form';
  WindowState := wsMaximized;

  Button1 := TButton.Create(Self);
  Button1.Parent := Self;
  Button1.Caption := 'Freeze!';
  Button1.SetBounds(10, 10, 100, 100);
  Button1.OnClick := Button1Click;
end;

procedure TBigForm.DoHide;
begin
  OnTopForm.Free;
  inherited DoHide;
end;

procedure TBigForm.DoShow;
begin
  inherited DoShow;
  OnTopForm := TForm.Create(Self);
  OnTopForm.Caption := 'Important information';
  OnTopForm.BorderStyle := bsToolWindow;
  OnTopForm.FormStyle := fsStayOnTop;
  OnTopForm.Position := poScreenCenter;
  OnTopForm.Show;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  f: TBigForm;
begin
  f := TBigForm.Create(nil);
  try
    f.ShowModal;
  finally
    f.Free;
  end;
end;

アプリを起動し、「Button1」をクリックしてから「Freeze!」をクリックします。

(ところで: D2007 を使用します。)

4

4 に答える 4

2

ShowModal() を呼び出す前に、モーダル フォームの PopupParent プロパティを StayOnTop フォームに設定するか、Application.ModalPopupMode プロパティを pmNone 以外に設定してみてください。

于 2010-08-04T19:30:22.140 に答える
2

別のフォームをモーダルとして表示する前に、OnTopform の FormStyle を一時的に変更します。

procedure TBigForm.Button1Click(Sender: TObject);
begin
  OnTopForm.FormStyle := fsNormal;
  ShowMessage('Test');
  OnTopForm.FormStyle := fsStayOnTop;
end;

それはあなたが望むもののために働くはずです...

于 2010-08-04T19:16:20.357 に答える
0

ここであなたのグッズ

Create an global TApplicationEvents
Declare an global var to keep track of modal form count
Hookup the OnMessage

var
  Ctrl: TControl;

if Msg.hwnd <> 0 then
  case Msg.message of
    CM_ACTIVATE,
    CM_DEACTIVATE:
    begin
      Ctrl := FindControl(Msg.hwnd);
      if Ctrl is TForm then
        if fsModal in TForm(Ctrl).FormState then
        begin  
          if Msg.message = CM_ACTIVATE then
            Inc(Modal form count var)
          else
            Dec(Modal form count var);

          add more logic based on Modal form count var
        end;
    end;
  end;

楽しむ

于 2010-08-04T21:29:17.407 に答える
0
procedure TForm1.ScreenOnActiveFormChange(Sender: TObject);
begin
  if (Screen.ActiveForm <> nil) then
  begin
    if (Screen.ActiveForm.Handle <> Application.MainForm.Handle) then
      with Screen.ActiveForm do
        SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
    Windows.SetForeGroundWindow(Screen.ActiveForm.Handle);
  end;
end;

これはうまくいくはずです。

于 2010-08-05T18:15:54.603 に答える