3

2 つのオプションを持つコンボボックスがあり、2 つのオプションがフォームのサイズ変更をトリガーしています。アイデアは、選択に基づいて追加のコントロールを非表示および表示することです。

フォームの幅を変更すると、サイズは希望どおりに変更されますが、フォームが画面の中央に表示されなくなりました。フォームの幅を変更しながら、フォームの XY 位置を前後に移動できますか?

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject);
begin
  if(SpecialFilesComboBox.ItemIndex = 0) then begin
    //No special files
    Width := 412;
    Height := 423;
    ...
  end
  else begin
    //Yes special files
    Width := 893;
    Height := 423;
    ...
  end;
end;
4

2 に答える 2

7

現在、マルチモニターシステムが一般的です。画面の中央に配置すると、フォームが複数のモニターに分散する場合があります。それは望ましくありません。

そのため、フォームをモニターの中央に配置します。

R := Form.Monitor.WorkAreaRect;
Form.Left := (R.Left+R.Right-Form.Width) div 2;
Form.Top := (R.Top+R.Bottom-Form.Height) div 2;

@bummiが指摘しているように、次のように書くことができます。

Form.Position := poScreenCenter;

これはほとんどあなたが望むように機能します。フォームを画面の中央に配置します。ただし、常にデフォルトのモニターが選択されます。そのため、そのコードを使用すると、フォームが別のモニターに移動する可能性がありますが、これは決して望ましくないと思います。

フォームを中央に強制するのではなく、代わりにすべての側面でフォームを拡大または縮小することを決定できます。

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject);
var
  NewLeft, NewTop, NewWidth, NewHeight: Integer;
begin
  if(SpecialFilesComboBox.ItemIndex = 0) then begin
    //No special files
    NewWidth := 412;
    NewHeight := 423;
    ...
  end
  else begin
    //Yes special files
    NewWidth := 893;
    NewHeight := 423;
    ...
  end;

  NewLeft := Left + (Width-NewWidth) div 2;
  NewTop := Top + (Top-NewHeight) div 2;
  NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight);
  BoundsRect := NewBoundsRect;
end;

そして、本当にかわいいものにしたい場合は、新しくサイズ設定して配置したフォームがモニターの端から外れないように、境界を調整します。

procedure MakeAppearOnScreen(var Rect: TRect);
const
  Padding = 24;
var
  Monitor: HMonitor;
  MonInfo: TMonitorInfo;
  Excess, Width, Height: Integer;
begin
  Monitor := MonitorFromPoint(Point((Rect.Left+Rect.Right) div 2, (Rect.Top+Rect.Bottom) div 2), MONITOR_DEFAULTTONEAREST);
  if Monitor=0 then begin
    exit;
  end;
  MonInfo.cbSize := SizeOf(MonInfo);
  if not GetMonitorInfo(Monitor, @MonInfo) then begin
    exit;
  end;
  Width := Rect.Right-Rect.Left;
  Height := Rect.Bottom-Rect.Top;

  Excess := Rect.Right+Padding-MonInfo.rcWork.Right;
  if Excess>0 then begin
    dec(Rect.Left, Excess);
  end;
  Excess := Rect.Bottom+Padding-MonInfo.rcWork.Bottom;
  if Excess>0 then begin
    dec(Rect.Top, Excess);
  end;
  Excess := MonInfo.rcWork.Left+Padding-Rect.Left;
  if Excess>0 then begin
    inc(Rect.Left, Excess);
  end;
  Excess := MonInfo.rcWork.Top+Padding-Rect.Top;
  if Excess>0 then begin
    inc(Rect.Top, Excess);
  end;
  Rect.Right := Rect.Left+Width;
  Rect.Bottom := Rect.Top+Height;
end;

次に、前のコードサンプルは次のように変更されます。

NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight);
MakeAppearOnScreen(NewBoundsRect);
BoundsRect := NewBoundsRect;
于 2013-03-07T07:39:54.187 に答える
6

非常に単純な ReCenter 関数は次のようになります。

procedure TReportFrm.ReCenter;
var
  LRect: TRect;
  X, Y: Integer;
begin
  LRect := Screen.WorkAreaRect;
  X := LRect.Left + (LRect.Right - LRect.Left - Width) div 2;
  Y := LRect.Top + (LRect.Bottom - LRect.Top - Height) div 2;
  SetBounds(X, Y, Width, Height);
end;

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject);
begin
  if(SpecialFilesComboBox.ItemIndex = 0) then begin
    //No special files
    Width := 412;
    Height := 423;
    ...
  end
  else begin
    //Yes special files
    Width := 893;
    Height := 423;
    ...
  end;
  ReCenter;
end;

ウィンドウを画面の WorkArea の中央に配置します。他の参照の中央に配置することもできます。その場合、意味のある四角形を決定するのはあなた次第です。

于 2013-03-07T06:47:24.907 に答える