5

フォームをボーダレス フォームに変更しました。BorderStyleプロパティをbsNoneに変更しただけですが、アプリケーションで Windows アンカーと次のようなコマンドが失われました。

WIN + ↑ (クライアントのフォームを整列)
WIN + ↓ (フォームを最小化)
WIN + → (フォームを右に整列)
WIN + ← (フォームを左に整列)

BorderStyle: bsSizeable内で以下のコードを設定して使用しようとしましFormCreateたが、これは機能しません。

procedure TfrmBase.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle
               ,GWL_STYLE
               ,GetWindowLong(Handle, GWL_STYLE)
                AND (NOT WS_CAPTION)
                AND (NOT WS_THICKFRAME)
               );


  Refresh;
  FormColor := oLauncher.oCor;
end;

これにより、次の結果が得られます。

私のフォーム

上の画像は私が望むものですが、既に言及した Windows コマンドは機能しません。

これらのコマンドを設定してBorderStyle: bsNone失わない方法はありますか?

編集済み

私のフォームを使用するWS_THICKFRAMEと、少し上の境界線が返され、Windows コマンドはうまく機能しますが、その上の境界線は必要ありません。

私のフォーム2

編集済み 2

期待した結果に非常に近い結果になりましたが、まだ少し問題があります...

これを身につけましたFormCreate

SetWindowLong(Handle
             ,GWL_STYLE
             ,GetWindowLong(Handle, GWL_STYLE)
              AND (NOT WS_CAPTION)
              );

そして、私はメソッドを作成します

private
   procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;

その後

procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
begin
  inherited;
  if Msg.CalcValidRects then
  begin
    InflateRect(Msg.CalcSize_Params.rgrc[0], 0, 6);
    Msg.Result := 0;
  end;
end;

ここでこのメソッドを取得しました

境界線が消えましたが、フォームがフォーカスを失うと、上/下の境界線が再び表示されます....

どうすればこれを回避できますか?

ここに画像の説明を入力


解決した

境界線をそのままにしてBorderStyle: bsSizeable、次のようにしました。

private
  procedure WmNCCalcSize(var Msg: TWMNCCalcSize); message WM_NCCALCSIZE;
[...]
procedure TfrmBase.WmNCCalcSize(var Msg: TWMNCCalcSize);
var
  R: TRect;
begin
  if not Msg.CalcValidRects then
    R := PRect(Msg.CalcSize_Params)^;
  inherited;
  if Msg.CalcValidRects then
    Msg.CalcSize_Params.rgrc0 := Msg.CalcSize_Params.rgrc1
  else
    PRect(Msg.CalcSize_Params)^ := R;

  Msg.Result := 0;
end;

procedure TfrmBase.FormCreate(Sender: TObject);
begin
  BorderStyle := bsNone;
  SetWindowLong(Handle
               ,GWL_STYLE
               ,WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW
               );
end;

procedure TfrmBase.FormShow(Sender: TObject);
begin
  Width := (Width - 1);
end;

GitHUB でのソリューション

ここにリポジトリを作成しました

4

1 に答える 1

2

参照するコマンドの一部は、ウィンドウのサイズ変更に関連するシステム コマンドです。それには太いフレームが必要で、これがないと「WIN+右」「WIN+左」が動きません。さらに、WIN + アップ/ダウン コマンドが機能するには、最小化ボックスと最大化ボックスが必要です。

最善の方法は、ゼロから始めて、必要なスタイルを含めることです。そうしないと、VCL が干渉する可能性があります。フォームが再作成される可能性がある場合は、スタイリングをCreateWndオーバーライドしてください。

procedure TForm1.FormCreate(Sender: TObject);
begin
  BorderStyle := bsNone;
  SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;


次に、不要なフレームがあります。質問の編集では、クライアントの四角形を膨らませてそれを取り除きます。フレームの幅/高さを推測しないでください。以下のようにしてください。

procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
  R: TRect;
begin
  if not Message.CalcValidRects then
    R := PRect(Message.CalcSize_Params)^;
  inherited;
  if Message.CalcValidRects then
    Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
  else
    PRect(Message.CalcSize_Params)^ := R;
  Message.Result := 0;
end;

この時点でメッセージのドキュメントを読むことは必須であり、パラメーターはステージごとに異なる意味を持ちます。


上記は、非クライアント領域がまったくないウィンドウを残します。クライアントの四角形は、ウィンドウの四角形と同じです。キャプションは表示されませんが、Alt+Space を押してシステム メニューをアクティブにすることができます。問題は、システムが描画のアクティブ化状態を主張することです。これで、クライアント領域にフレームが描画されます!!

を傍受してそれを取り除きWM_NCACTIVATEます。アクティベーション ステータスに従ってタイトルを描画するためにも必要です。

procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
  if Message.Active then
    // draw active caption
  else
    // draw incactive caption

  // don't call inherited
end;


いくつかのグリッチに対処しなければならない場合があり、ウィンドウを台無しにすると結果が生じます。私のテストでは、最小化されたフォームには、たとえば alt+tab ダイアログに関連付けられたアイコンがありません。



以下は完全な私のテストユニットです。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  protected
    procedure WMNCActivate(var Message: TWMNCActivate); message WM_NCACTIVATE;
    procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  BorderStyle := bsNone;
  SetWindowLong(Handle, GWL_STYLE, WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW);
end;

procedure TForm1.WMNCActivate(var Message: TWMNCActivate);
begin
  if Message.Active then
    // draw active caption
  else
    // draw incactive caption

  // don't call inherited
end;

procedure TForm1.WMNCCalcSize(var Message: TWMNCCalcSize);
var
  R: TRect;
begin
  if not Message.CalcValidRects then
    R := PRect(Message.CalcSize_Params)^;
  inherited;
  if Message.CalcValidRects then
    Message.CalcSize_Params.rgrc0 := Message.CalcSize_Params.rgrc1
  else
    PRect(Message.CalcSize_Params)^ := R;
  Message.Result := 0;
end;

end.
于 2019-02-13T15:39:13.950 に答える