Smooth resizing in a borderless form/window in Delphi

前端 未结 4 1941
难免孤独
难免孤独 2021-01-18 17:00

I am trying to resize a borderless form but when I increase the size using the right/bottom side, I get a gap between the border and the old client area that depends of the

4条回答
  •  南方客
    南方客 (楼主)
    2021-01-18 17:51

    I know this thread is fairly old, but it is one that people still struggle with.

    The answer is simple, though. The problem is that trying to do resize stuff makes you want to use the form you are resizing as a reference. Don't do that.

    Use another form.

    Here is the complete source for a TForm that can help you. Make sure that this form has BorderStyle = bsNone. You probably also want to make sure it is not visible.

    unit UResize;
    {
      Copyright 2014 Michael Thomas Greer
      Distributed under the Boost Software License, Version 1.0
      (See accompanying file LICENSE.txt or copy
       at http://www.boost.org/LICENSE_1_0.txt )
    }
    
    //////////////////////////////////////////////////////////////////////////////
    interface
    //////////////////////////////////////////////////////////////////////////////
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    
    const
      ResizeMaskLeft   = $1;
      ResizeMaskTop    = $2;
      ResizeMaskWidth  = $4;
      ResizeMaskHeight = $8;
    
    type
      TResizeForm = class( TForm )
        procedure FormMouseMove( Sender: TObject;      Shift: TShiftState; X, Y: Integer );
        procedure FormMouseUp(   Sender: TObject;
                                 Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
      private
        anchor_g: TRect;
        anchor_c: TPoint;
        form_ref: TForm;
        resize_m: cardinal;
    
      public
        procedure SetMouseDown( AForm: TForm; ResizeMask: cardinal );
      end;
    
    var
      ResizeForm: TResizeForm;
    
    
    //////////////////////////////////////////////////////////////////////////////
    implementation
    //////////////////////////////////////////////////////////////////////////////
    
    {$R *.DFM}
    
    //----------------------------------------------------------------------------
    procedure TResizeForm.SetMouseDown( AForm: TForm; ResizeMask: cardinal );
      begin
      anchor_g.Left   := AForm.Left;
      anchor_g.Top    := AForm.Top;
      anchor_g.Right  := AForm.Width;
      anchor_g.Bottom := AForm.Height;
      anchor_c        := Mouse.CursorPos;
      form_ref        := AForm;
      resize_m        := ResizeMask;
      SetCapture( Handle )
      end;
    
    //----------------------------------------------------------------------------
    procedure TResizeForm.FormMouseMove(
      Sender: TObject;
      Shift:  TShiftState;
      X, Y:   Integer
      );
      var
        p: TPoint;
        r: TRect;
      begin
      if Assigned( form_ref ) and (ssLeft in Shift)
        then begin
             p := Mouse.CursorPos;
             Dec( p.x, anchor_c.x );
             Dec( p.y, anchor_c.y );
    
             r.Left   := form_ref.Left;
             r.Top    := form_ref.Top;
             r.Right  := form_ref.Width;
             r.Bottom := form_ref.Height;
    
             if (resize_m and ResizeMaskLeft)   <> 0 then begin r.Left   := anchor_g.Left   + p.x;  p.x := -p.x end;
             if (resize_m and ResizeMaskTop)    <> 0 then begin r.Top    := anchor_g.Top    + p.y;  p.y := -p.y end;
             if (resize_m and ResizeMaskWidth)  <> 0 then       r.Right  := anchor_g.Right  + p.x;
             if (resize_m and ResizeMaskHeight) <> 0 then       r.Bottom := anchor_g.Bottom + p.y;
    
             with r do form_ref.SetBounds( Left, Top, Right, Bottom )
             end
      end;
    
    //----------------------------------------------------------------------------
    procedure TResizeForm.FormMouseUp(
      Sender: TObject;
      Button: TMouseButton;
      Shift:  TShiftState;
      X, Y:   Integer
      );
      begin
      ReleaseCapture;
      form_ref := nil
      end;
    
    end.
    

    Now any borderless form in your application can be smoothly resized by hooking into ResizeForm with a simple

    ResizeForm.SetMouseDown( self, (sender as TComponent).Tag );
    

    A good place to put that is in the MouseDown event of whatever component(s) you are using to track the edges of your borderless form(s). (Notice how the Tag property is used to indicate what edge of your form you wish to drag/resize).

    Oh, and set your form to DoubleBuffered = true to get rid of any remaining flicker.

    This is just a small happiness I can give to you.

提交回复
热议问题