Search code examples
delphiresizevcl-stylesborderless

Resizing bsNone Form when Vcl Styles Enabled


I'm trying to resize a non borderless form (bsNone border style). It can be done with the following code, but it worked only when the application has no a VCL style enabled.

protected
   procedure WMNCHitTest(var message: TWMNCHitTest); message WM_NCHITTEST;
....

procedure TForm1.WMNCHitTest(var message: TWMNCHitTest);
const
  EDGEDETECT = 7;
var
  deltaRect: TRect;
begin
  inherited;
  if BorderStyle = bsNone then
    with Message, deltaRect do
    begin
      Left   := XPos - BoundsRect.Left;
      Right  := BoundsRect.Right - XPos;
      Top    := YPos - BoundsRect.Top;
      Bottom := BoundsRect.Bottom - YPos;
      if (Top < EDGEDETECT) and (Left < EDGEDETECT) then
        Result := HTTOPLEFT
      else if (Top < EDGEDETECT) and (Right < EDGEDETECT) then
        Result := HTTOPRIGHT
      else if (Bottom < EDGEDETECT) and (Left < EDGEDETECT) then
        Result := HTBOTTOMLEFT
      else if (Bottom < EDGEDETECT) and (Right < EDGEDETECT) then
        Result := HTBOTTOMRIGHT
      else if (Top < EDGEDETECT) then
        Result := HTTOP
      else if (Left < EDGEDETECT) then
        Result := HTLEFT
      else if (Bottom < EDGEDETECT) then
        Result := HTBOTTOM
      else if (Right < EDGEDETECT) then
        Result := HTRIGHT
    end;

I have also tried to do something like this and it's has the same result. Then how can i make it resizable when VCL style enabled?

Thank you very much.

procedure CreateParams(var params: TCreateParams); override;
    ...
    procedure TForm1.CreateParams(var params: TCreateParams);
          begin
            BorderStyle := bsNone;
            inherited;
            params.ExStyle := params.ExStyle or WS_EX_STATICEDGE;
            params.Style   := params.Style or WS_SIZEBOX;
          end;

Solution

  • The reason that VCL styles breaks your WM_NCHITTEST message handler is that the form's style hook handles WM_NCHITTEST directly. You can override that and regain control like this:

    protected
      function DoHandleStyleMessage(var Message: TMessage): Boolean; override;
    
    ....
    
    function TForm1.DoHandleStyleMessage(var Message: TMessage): Boolean;
    begin
      if Message.Msg=WM_NCHITTEST then begin
        Result := False;
      end else begin
        Result := inherited;
      end;
    end;
    

    Now your event handler for WM_NCHITTEST will be invoked again. Of course, you will lose any functionality that the VCL styles handler for WM_NCHITTEST provided, but I suspect that is exactly what you want.