unit UxForm;

interface

uses
  Windows, Messages, SysUtils, Types, Classes, Forms, Controls, StdCtrls,
  Graphics, UITypes, UxPanel, Menus, ExtCtrls;

type

  TUxForm0 = class(TForm)
  strict private type
    TUxPanelCT = class(TUxPanel)
    protected
      procedure WMNcHitTest(var Message: TWMNCHittest); message WM_NCHITTEST;
      procedure ModalBegin; override;
      procedure ModalEnd; override;
    end;
    TClientWindow = class(TCustomControl)
    end;
  var
    pn: TUxPanelCT;
    cpn: TClientWindow;
    pmWindow: TPopupMenu;
    procedure SysCmd(Sender: TObject);
    function GetParentWindow: TWinControl;
  protected
    procedure WMNCHitTest(var Message: TWMNCHittest); message WM_NCHITTEST;
    procedure WMNCMButtonUp(var Message: TWMNCMButtonUp); message WM_NCMBUTTONUP;
    procedure WMNCRButtonUp(var Message: TWMNCRButtonUp); message WM_NCRBUTTONUP;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
    procedure DoShow; override;
    procedure Activate; override;
  public
    constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
    function IsShortCut(var Message: TWMKey): Boolean; override;
    property ParentWindow: TWinControl read GetParentWindow;
    procedure SetClientSize(const ASize: TSize);
  end;

implementation

uses
  Math, StrUtils, Rux;

{ TUxForm0.TUxPanelCT }

procedure TUxForm0.TUxPanelCT.ModalBegin;
begin
end;

procedure TUxForm0.TUxPanelCT.ModalEnd;
begin
end;

procedure TUxForm0.TUxPanelCT.WMNcHitTest(var Message: TWMNCHittest);
begin
  Message.Result := HTTRANSPARENT;
end;

{ TUxForm0 }

procedure TUxForm0.Activate;
begin
  inherited;
  if Assigned(cpn) and cpn.CanFocus then
  begin
    if (cpn.ControlCount >= 1) and (cpn.Controls[0] is TWinControl) and TWinControl(cpn.Controls[0]).CanFocus then
      TWinControl(cpn.Controls[0]).SetFocus
    else
      cpn.SetFocus;
  end;
end;

procedure TUxForm0.CMTextChanged(var Message: TMessage);
begin
  pn.Caption := Caption;
end;

constructor TUxForm0.CreateNew(AOwner: TComponent; Dummy: Integer);
var
  mi: TMenuItem;
  OwnerForm: TCustomForm absolute AOwner;
begin

  inherited;

  if not (AOwner is TCustomForm) then
    raise Exception.Create('TUxForm0.CreateNew: Owner must be a TCustomForm.');

  Position := poOwnerFormCenter;
  DefaultMonitor := dmDesktop;
  BorderStyle := bsNone;
  Color := clWhite;
  Font.Assign(Application.MainForm.Font);
  Width := ScaleValue(500);
  Height := ScaleValue(400);
  Constraints.MinWidth := ScaleValue(200);
  Constraints.MinHeight := ScaleValue(100);

  pn := TUxPanelCT.Create(Self);
  pn.AlignWithMargins := True;
  pn.Margins.SetBounds(1, 1, 1, 1);
  pn.Parent := Self;
  pn.Align := alClient;
  pn.Caption := Caption;
  pn.BorderWidth := ScaleValue(4);
  pn.Alignment := taCenter;

  pmWindow := TPopupMenu.Create(Self);

  mi := TMenuItem.Create(pmWindow);
  mi.Caption := '&Move';
  mi.Hint := 'Moves this window using the arrow keys.';
  mi.Tag := SC_MOVE;
  mi.OnClick := SysCmd;
  pmWindow.Items.Add(mi);

  mi := TMenuItem.Create(pmWindow);
  mi.Caption := '&Size';
  mi.Hint := 'Resizes this window using the arrow keys.';
  mi.Tag := SC_SIZE;
  mi.OnClick := SysCmd;
  pmWindow.Items.Add(mi);

  mi := TMenuItem.Create(pmWindow);
  mi.Caption := '&Close';
  mi.Hint := 'Closes this window.';
  mi.Tag := SC_CLOSE;
  mi.OnClick := SysCmd;
  pmWindow.Items.Add(mi);
  pmWindow.Items.InsertNewLineBefore(mi);

  cpn := TClientWindow.Create(Self);
  cpn.Parent := pn;
  cpn.Align := alClient;
  cpn.ParentFont := False;
  cpn.Font.Assign(Application.MainForm.Font);

end;

procedure TUxForm0.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style := Params.Style or WS_MAXIMIZEBOX;
end;

procedure TUxForm0.DoShow;
begin
  inherited;
  for var i := 0 to ControlCount - 1 do
    if not (Controls[i] is TUxPanelCT) then
      Controls[i].Parent := cpn;
end;

function TUxForm0.GetParentWindow: TWinControl;
begin
  Result := cpn;
end;

function TUxForm0.IsShortCut(var Message: TWMKey): Boolean;
begin
  Result := False;
  if (Message.CharCode = 32) and (HiWord(Message.KeyData) and KF_ALTDOWN <> 0) then
  begin
    with ClientToScreen(Point(pn.Padding.Left, pn.Padding.Top)) do
      pmWindow.Popup(X, Y);
    Result := True;
  end;
end;

procedure TUxForm0.SetClientSize(const ASize: TSize);
var
  DX, DY: Integer;
begin
  DX := Width - ParentWindow.ClientWidth;
  DY := Height - ParentWindow.ClientHeight;
  SetBounds(Left, Top, ASize.cx + DX, ASize.cy + DY);
end;

procedure TUxForm0.SysCmd(Sender: TObject);
begin
  if Sender is TComponent then
    Perform(WM_SYSCOMMAND, TComponent(Sender).Tag, 0);
end;

procedure TUxForm0.WMNCHitTest(var Message: TWMNCHittest);
var
  P: TPoint;
begin
  inherited;
  P := ScreenToClient(Message.Pos);
  if (P.Y < 2*pn.BorderWidth) and (P.X < 2*pn.BorderWidth) then
    Message.Result := HTTOPLEFT
  else if (P.Y < 2*pn.BorderWidth) and (P.X > ClientWidth - 2*pn.BorderWidth) then
    Message.Result := HTTOPRIGHT
  else if (P.Y > ClientHeight - 2*pn.BorderWidth) and (P.X < 2*pn.BorderWidth) then
    Message.Result := HTBOTTOMLEFT
  else if (P.Y > ClientHeight - 2*pn.BorderWidth) and (P.X > ClientWidth - 2*pn.BorderWidth) then
    Message.Result := HTBOTTOMRIGHT
  else if P.Y < pn.BorderWidth then
    Message.Result := HTTOP
  else if P.Y < pn.CaptionRect.Height then
    Message.Result := HTCAPTION
  else if P.Y > ClientHeight - pn.BorderWidth then
    Message.Result := HTBOTTOM
  else if P.X < pn.BorderWidth then
    Message.Result := HTLEFT
  else if P.X > ClientWidth - pn.BorderWidth then
    Message.Result := HTRIGHT
  else
    Message.Result := HTCLIENT;
end;

procedure TUxForm0.WMNCMButtonUp(var Message: TWMNcMButtonUp);
begin
  inherited;
  if Message.HitTest = HTCAPTION then
  begin
    ModalResult := mrCancel;
    Message.Result := 0;
  end;
end;

procedure TUxForm0.WMNCRButtonUp(var Message: TWMNCRButtonUp);
begin
  inherited;
  if Message.HitTest = HTCAPTION then
  begin
    if Assigned(pmWindow) then
    begin
      pmWindow.Popup(Message.XCursor, Message.YCursor);
      Message.Result := 0;
    end;
  end;
end;

end.
