delphimdimultiple-monitorssdi

How to pull a MDI child window out of the main form?


I want to create a MDI application with it's own task bar so the user can have fast access to the child windows he/she wants to bring to front. Then I had the idea that an user who works with two or more monitors could drag on of the child windows from inside the main form of my application into outside of it, into another monitor for example.

How can it be done?


Solution

  • Maybe this example MDI client form code serves inspiration:

    unit Unit3;
    
    interface
    
    uses
      Windows, Messages, Controls, Forms;
    
    type
      TForm3 = class(TForm)
      private
        FSizing: Boolean;
        procedure WMNCMouseLeave(var Message: TMessage);
          message WM_NCMOUSELEAVE;
        procedure WMWindowPosChanged(var Message: TWMWindowPosChanged);
          message WM_WINDOWPOSCHANGED;
      protected
        procedure CreateParams(var Params: TCreateParams); override;
        procedure Resize; override;
      end;
    
    implementation
    
    {$R *.dfm}
    
    { TForm3 }
    
    var
      FDragging: Boolean = False;
    
    procedure TForm3.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      if FormStyle = fsNormal then
        Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW
      else
        Params.ExStyle := Params.ExStyle and not WS_EX_APPWINDOW;
    end;
    
    procedure TForm3.Resize;
    begin
      inherited Resize;
      FSizing := True;
    end;
    
    procedure TForm3.WMNCMouseLeave(var Message: TMessage);
    begin
      inherited;
      FDragging := False;
    end;
    
    procedure TForm3.WMWindowPosChanged(var Message: TWMWindowPosChanged);
    var
      P: TPoint;
      F: TCustomForm;
      R: TRect;
    begin
      inherited;
      if not FDragging and not FSizing and not (fsShowing in FormState) and
        (WindowState = wsNormal) then
      begin
        F := Application.MainForm;
        P := F.ScreenToClient(Mouse.CursorPos);
        R := F.ClientRect;
        InflateRect(R, -5, -5);
        if not PtInRect(R, P) and (FormStyle = fsMDIChild) then
        begin
          FDragging := True;
          FormStyle := fsNormal;
          Top := Top + F.Top;
          Left := Left + F.Left;
        end
        else if PtInRect(R, P) and (FormStyle = fsNormal) then
        begin
          FDragging := True;
          FormStyle := fsMDIChild;
        end;
      end;
      FSizing := False;
    end;
    
    end.