Recent

Author Topic: Full skin / Resizable bsNone  (Read 11182 times)

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Full skin / Resizable bsNone
« on: August 27, 2016, 09:54:21 pm »
Is it possible to create a form with no border bsNone that is still resizable?

I'm trying to create a form that is fully skinned - ie no border and my own title bar and close button.

My plan was to use BGRA Controls buttons with rounding and a transparent form to create something that looks good, but I've stumbled at the first step - as soon as I set bsNone the form cannot be resized - so is there another way to achieve the same thing, maybe by manipulating the form's border style directly rather than using the built in styles?

-FM

lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: Full skin / Resizable bsNone
« Reply #1 on: August 27, 2016, 10:08:12 pm »
See the demo bgracontrols\test\BGRA Ribbon Custom, it does what you want.

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #2 on: August 27, 2016, 10:31:05 pm »
I can't get to my dev machine right now to look at that demo, but from the description of the ribbon suggests that this might just do the title bar bit. Is that right?

Or does the ribbon demo also show me how I can have a none-square form that is resizable? (my plan was to use a rounded BGRA button or a shape anchored to the transparent form's edges as the background to the whole application)

Thanks,

FM

« Last Edit: August 27, 2016, 11:08:14 pm by fatmonk »

lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: Full skin / Resizable bsNone
« Reply #3 on: August 27, 2016, 10:40:59 pm »
It does the skin and the resize you need, but not the shape, it's square.

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #4 on: August 28, 2016, 07:25:16 pm »
Thanks lainz,

Nice demo, but I'm afraid it's not what I'm looking for.

The demo only allows resizing by dragging the image - I need to be able to resize by dragging any of the sides or corners of the form, as with a fsSizeable, even though there are no normal form edges.

I'll post a mock up of what I'm trying to do in a while...

-FM

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #5 on: August 28, 2016, 08:24:41 pm »
OK, it's a bit hacky (and I need to tweak the functions to make it a bit more logical in terms of what dragging each edge does), but taking ideas from BGRA Ribbon Custom example I've come up with the attcahed.

It uses BGRA Buttons and Shapes and some code I found on the web to make forms transparent by a particular colour (see here)...

It kind of works, and with a bit more work should give me a full skinned application, I think.

(Note that the title bar doesn't quite work as I wanted, so I will probably switch to just using more shapes to create the title and application icon.)

-FM


lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: Full skin / Resizable bsNone
« Reply #6 on: August 28, 2016, 09:35:33 pm »
Thanks lainz,

Nice demo, but I'm afraid it's not what I'm looking for.

The demo only allows resizing by dragging the image - I need to be able to resize by dragging any of the sides or corners of the form, as with a fsSizeable, even though there are no normal form edges.

I'll post a mock up of what I'm trying to do in a while...

-FM

It has an unit to resize from all sides, it's by default commented.

balazsszekely

  • Guest
Re: Full skin / Resizable bsNone
« Reply #7 on: August 29, 2016, 01:23:44 pm »
See attachment.
Code: Pascal  [Select][+][-]
  1. uses Windows, LCLType;
  2.  
  3. var
  4.   PrevWndProc: WNDPROC;
  5.  
  6. function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall;
  7. const
  8.   Margin = 5;
  9. var
  10.   Rect: TRect;
  11.   MouseX, MouseY: LongInt;
  12. begin
  13.   if uMsg = WM_NCHITTEST then
  14.   begin
  15.     Result := Windows.DefWindowProc(Ahwnd, uMsg, wParam, lParam);
  16.     MouseX := GET_X_LPARAM(lParam);
  17.     MouseY := GET_Y_LPARAM(lParam);
  18.     with Rect do
  19.     begin
  20.       Left := MouseX - Form1.BoundsRect.Left;
  21.       Right := Form1.BoundsRect.Right - MouseX;
  22.       Top := MouseY - Form1.BoundsRect.Top;
  23.       Bottom := Form1.BoundsRect.Bottom - MouseY;
  24.       if (Top < Margin) and (Left < Margin) then
  25.         Result := windows.HTTOPLEFT
  26.       else if (Top < Margin) and (Right < Margin) then
  27.         Result := windows.HTTOPRIGHT
  28.       else if (Bottom < Margin) and (Left < Margin) then
  29.         Result := windows.HTBOTTOMLEFT
  30.       else if (Bottom < Margin) and (Right < Margin) then
  31.         Result := windows.HTBOTTOMRIGHT
  32.       else if (Top < Margin) then
  33.         Result := windows.HTTOP
  34.       else if (Left < Margin) then
  35.         Result := windows.HTLEFT
  36.       else if (Bottom < Margin) then
  37.         Result := windows.HTBOTTOM
  38.       else if (Right < Margin) then
  39.         Result := windows.HTRIGHT;
  40.     end;
  41.     Exit;
  42.   end;
  43.   Result := CallWindowProc(PrevWndProc,Ahwnd, uMsg, WParam, LParam);
  44. end;
  45.  
  46. procedure TForm1.FormCreate(Sender: TObject);
  47. begin
  48.   PrevWndProc := Windows.WNDPROC(SetWindowLongPtr(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback)));
  49. end;
  50.  
  51. procedure TForm1.CreateParams(var Params: TCreateParams);
  52. begin
  53.   inherited CreateParams(Params);
  54.   Self.BorderStyle := bsNone;
  55. end

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #8 on: August 29, 2016, 03:39:35 pm »
@GetMem I wish I had the first clue what that code was doing !  :o

Will have a play with that to see if I can figure out out.

-FM

balazsszekely

  • Guest
Re: Full skin / Resizable bsNone
« Reply #9 on: August 30, 2016, 12:03:35 pm »
@fatmonk
You can also add the ability to move the form(BorderStyle --> bsNone), like you would move a form with caption(title) bar. Just add two lines to the function WndCallback:
Code: Pascal  [Select][+][-]
  1. function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall;
  2. const
  3.   Margin = 5;
  4.   Caption = 15; //add this
  5. var
  6.   Rect: TRect;
  7.   MouseX, MouseY: LongInt;
  8. begin
  9.   if uMsg = WM_NCHITTEST then
  10.   begin
  11.     Result := Windows.DefWindowProc(Ahwnd, uMsg, wParam, lParam);
  12.     MouseX := GET_X_LPARAM(lParam);
  13.     MouseY := GET_Y_LPARAM(lParam);
  14.     with Rect do
  15.     begin
  16.       Left := MouseX - Form1.BoundsRect.Left;
  17.       Right := Form1.BoundsRect.Right - MouseX;
  18.       Top := MouseY - Form1.BoundsRect.Top;
  19.       Bottom := Form1.BoundsRect.Bottom - MouseY;
  20.       if (Top < Margin) and (Left < Margin) then
  21.         Result := windows.HTTOPLEFT
  22.       else if (Top < Margin) and (Right < Margin) then
  23.         Result := windows.HTTOPRIGHT
  24.       else if (Bottom < Margin) and (Left < Margin) then
  25.         Result := windows.HTBOTTOMLEFT
  26.       else if (Bottom < Margin) and (Right < Margin) then
  27.         Result := windows.HTBOTTOMRIGHT
  28.       else if (Top < Margin) then
  29.         Result := windows.HTTOP
  30.       else if (Top > Margin) and (Top < Caption) then //add this line
  31.         Result := windows.HTCAPTION
  32.       else if (Left < Margin) then
  33.         Result := windows.HTLEFT
  34.       else if (Bottom < Margin) then
  35.         Result := windows.HTBOTTOM
  36.       else if (Right < Margin) then
  37.         Result := windows.HTRIGHT;
  38.  
  39.     end;
  40.     Exit;
  41.   end;
  42.   Result := CallWindowProc(PrevWndProc,Ahwnd, uMsg, WParam, LParam);
  43. end;                              

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #10 on: August 30, 2016, 04:59:12 pm »
@lainz

Where is that FormMouseMove procedure supposed to be called from?

I've tried is in the Form's onMouseMove event, but that's not working....

-FM

lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: Full skin / Resizable bsNone
« Reply #11 on: August 30, 2016, 06:14:33 pm »
@lainz

Where is that FormMouseMove procedure supposed to be called from?

I've tried is in the Form's onMouseMove event, but that's not working....

-FM

I don't really know, I'm not the author of that demo:
http://forum.lazarus-ide.org/index.php/topic,24176.msg208207.html#msg208207

BTW About licence if you read it, there are no issues, that unit can be used.

coasting

  • New member
  • *
  • Posts: 9
Re: Full skin / Resizable bsNone
« Reply #12 on: August 30, 2016, 10:09:50 pm »
@lainz

Where is that FormMouseMove procedure supposed to be called from?

I've tried is in the Form's onMouseMove event, but that's not working....

-FM

After my last text just got deleted by my browser, I keep my 2nd try a bit shorter now...

Please look here:

https://stackoverflow.com/questions/6652655/smooth-resizing-in-a-borderless-form-window-in-delphi

Last post on bottom of the page contains all you need to get uResize running. The idea of using a non-visible form is just brilliant!

Reason that's not working in BGRA Ribbon example is the design of my form. It just doesn't allow frmMain to see the mouse movements. The event frmMain.OnMouseMove isn't triggered as other controls are painted on top of frmMain. As I didn't find a way to pass through the mouse movements, I decided to resize the form by means of the imgResize image on bottom right of the form. That was quicker ;) to implement.

I have a basic window which does all this, i.e. borderless form, resizeable from all edges plus dropshadow ...but I strongly recommend to use uResize instead.

coasting


fatmonk

  • Sr. Member
  • ****
  • Posts: 252
Re: Full skin / Resizable bsNone
« Reply #13 on: September 01, 2016, 06:04:35 pm »
Still struggling I'm afraid...

I've tried adding the SetMouseDown event to the OnMouseDown event for my invisible shapes I have around the edges of my form but when that procedure is called I get an External SIGSEGV from the line:

Code: Pascal  [Select][+][-]
  1.   anchor_g.Left   := AForm.Left;

right at the start of that procedure.

I'm obviously doing something very wrong.

- I've added uResize to the first uses clause in my main form's unit.
- I've added invisible shapes to the top, left, right and bottom of my main form.
- I've added the same OnMouseDown event to each of those invisible shapes.

I'm guessing I'm missing something here...

-FM

coasting

  • New member
  • *
  • Posts: 9
Re: Full skin / Resizable bsNone
« Reply #14 on: September 01, 2016, 10:21:11 pm »
I copied some lines from an old project. Maybe its of help... Should I have some spare time over the weekend I can try to do a small demo...

Code: Pascal  [Select][+][-]
  1.  
  2. type
  3.  
  4.   TBorderPos = (bpTopLeft, bpTopRight, bpBottomLeft,
  5.                 bpBottomRight, bpTop, bpBottom,bpLeft,bpRight,bpnone);
  6.  
  7.   vsForm: TBGRAVirtualScreen;
  8.  
  9. .
  10. .
  11. implementation
  12.  
  13. uses
  14.   uResize;
  15. .
  16. .
  17.  
  18. procedure TForm1.FormCreate(Sender: TObject);
  19. begin
  20.   BorderStyle := bsNone;
  21.   {$ifdef Windows}
  22.   //  DropShadow(Handle); // Better to use SetClasslong() as follows (Windows OS only):
  23.   {Handle = all Forms, frmMain.Handle = only frmMain Form
  24.   SetClassLong(Handle, GCL_STYLE, GetClassLong(Handle, GCL_STYLE) or CS_DROPSHADOW);
  25.   }
  26.   SetClassLong(Form1.Handle, GCL_STYLE, GetClassLong(Form1.Handle, GCL_STYLE) or CS_DROPSHADOW);
  27.     SetWindowPos(Handle, HWND_TOP, Left, Top, Width, Height, SWP_FRAMECHANGED);
  28.   {$else}
  29.   // Something to be done for OS <> Windows?
  30.   {$endif}
  31.   DoubleBuffered := True;
  32. end;
  33. .
  34. .
  35. procedure TForm1.vsFormMouseDown(Sender: TObject; Button: TMouseButton;
  36.   Shift: TShiftState; X, Y: Integer);
  37. begin
  38.   MouseCapture := True;
  39. end;    
  40.  
  41. procedure TForm1.vsFormMouseMove(Sender: TObject;
  42.   Shift: TShiftState; X, Y: Integer);
  43.  
  44. var LeftEdge,RightEdge,TopEdge,BottomEdge: Boolean;
  45.       BorderPosition: TBorderPos;
  46.       BW: Integer;
  47.  
  48.   begin
  49.     BW := 8;
  50.     LeftEdge := False;
  51.     RightEdge := False;
  52.     TopEdge := False;
  53.     BottomEdge := False;
  54.     //Check if mouse cursor is on left or right edge
  55.     if X < BW then
  56.     begin
  57.       LeftEdge := True;
  58.     end
  59.     else if X > vsForm.Width-BW then
  60.     begin
  61.       RightEdge := True;
  62.     end;
  63.  
  64.     //Check if mouse cursor is on top or bottom edge
  65.     if Y < BW then
  66.     begin
  67.       TopEdge := True;
  68.     end
  69.     else if Y > vsForm.Height-BW then
  70.     begin
  71.       BottomEdge := True;
  72.     end;
  73.  
  74.     //Get border position by using if..else if..else clause in order for if block
  75.     //to break as soon as one of the conditions is met
  76.     //First check for corners
  77.     if TopEdge and LeftEdge then BorderPosition := bpTopLeft
  78.     else if TopEdge and RightEdge then BorderPosition := bpTopRight
  79.     else if BottomEdge and LeftEdge then BorderPosition := bpBottomLeft
  80.     else if BottomEdge and RightEdge then BorderPosition := bpBottomRight
  81.     //and only then check for individual edges
  82.     else if TopEdge then BorderPosition := bpTop
  83.     else if BottomEdge then BorderPosition := bpBottom
  84.     else if LeftEdge then BorderPosition := bpLeft
  85.     else if RightEdge then BorderPosition := bpRight
  86.     //mouse cursor is not on any border edge
  87.     else BorderPosition := bpNone;
  88.  
  89.  
  90.    //Finally you can use case statement to execute needed code based on which
  91.     //border edge is your mouse cursor positioned
  92.     case BorderPosition of
  93.       bpNone:
  94.       begin
  95.         Label1.Caption := 'Not on border';
  96.         vsForm.Cursor:=crDefault;
  97.       end;
  98.       bpLeft:
  99.       begin
  100.         Label1.Caption := 'Left border';
  101.         vsForm.Cursor:=crSizeWE;
  102.         if ssLeft in shift then
  103.           ResizeForm.SetMouseDown( self, 5 );
  104.       end;
  105.       bpRight:
  106.       begin
  107.         Label1.Caption := 'Right border';
  108.         vsForm.Cursor := crSizeWE;
  109.         if ssLeft in Shift then
  110.           ResizeForm.SetMouseDown( self, 4 );
  111.       end;
  112.  
  113.       bpTop:
  114.       begin
  115.         Label1.Caption := 'Top border';
  116.         vsBottom.Cursor := crSizeNS;
  117.         if ssLeft in Shift then
  118.           ResizeForm.SetMouseDown( self, 10 );
  119.       end;
  120.       bpBottom:
  121.       begin
  122.         Label1.Caption := 'Bottom border';
  123.         vsForm.Cursor :=crSizeNS;
  124.         if ssLeft in Shift then
  125.           ResizeForm.SetMouseDown( self, 8 );
  126.       end;
  127.       bpTopLeft:
  128.       begin
  129.         Label1.Caption := 'Top Left corner';
  130.         vsForm.Cursor :=crSizeNWSE;
  131.         if ssLeft in Shift then
  132.           ResizeForm.SetMouseDown( self, 15 );
  133.       end;
  134.       bpTopRight:
  135.       begin
  136.         Label1.Caption := 'Top Right corner';
  137.         vsForm.Cursor :=crSizeNESW;
  138.         if ssLeft in Shift then
  139.           ResizeForm.SetMouseDown( self, 14 );
  140.       end;
  141.       bpBottomLeft:
  142.       begin
  143.         Label1.Caption := 'Bottom Left corner';
  144.         vsForm.Cursor :=crSizeNESW;
  145.         if ssLeft in Shift then
  146.           ResizeForm.SetMouseDown( self, 13 );
  147.       end;
  148.       bpBottomRight:
  149.       begin
  150.         Label1.Caption := 'Bottom Right corner';
  151.         vsForm.Cursor :=crSizeNWSE;
  152.         if ssLeft in Shift then
  153.           ResizeForm.SetMouseDown( self, 12 );
  154.       end;
  155.     end;
  156.  
  157.  
  158. end;                

 

TinyPortal © 2005-2018