Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Thin window border


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 5 - Last Post: Dec 1, 2016 2:37 PM Last Post By: Asger Joergensen
Jeff Allan

Posts: 6
Registered: 5/24/01
Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 30, 2016 3:35 PM
My app presents a large (usually full-screen) main window and allows the user to open several non-modal child windows.
I do support docking, but do not require it, so often child windows are positioned over the main window's contents.
When several child windows appear over the main window, their heavy borders take too much area and I don't want their shadows on the main window's contents.

How do I make the window (TForm) borders as small as possible, without losing the ability to move and resize?
How do I suppress the shadows programmatically, regardless of the user's Windows theme?

Development environment: VCL, ECB XE, Win 7 Pro 64
Deployment OSs: XP, 7, 8.1, 10, Servers 2008-R2 and newer

Thanks,
Jeff
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 30, 2016 4:48 PM   in response to: Jeff Allan in response to: Jeff Allan
Jeff wrote:

How do I make the window (TForm) borders as small as possible,
without losing the ability to move and resize?

Moving a window has nothing to do with its borders.

Sizing a window does, though. You can change the Form's BorderStyle property
to use a smaller non-sizing border (or no border at all), but then you will
have to process the WM_NCHITTEST message to return the appropriate resizing
flag based when the mouse is over a border. For example:

private
  procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
 
procedure TMyForm.WMNCHitTest(var Message: TWMNCHitTest);
begin
  inherited;
  if Message.Result = HTBORDER then
  begin
    // set Message.Result to one of the following values depending on the 
Message's XPos/YPos values:
    //
    // HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTLEFT,
    // HTRIGHT, HTTOP, HTTOPLEFT, or HTTOPRIGHT
  end;
end;


How do I suppress the shadows programmatically, regardless
of the user's Windows theme?

Try having the Form override the virtual CreateParams() method to remove
the CS_DROPSHADOW window style:

private
  procedure CreateParams(var Params: TCreateParams); override;
 
procedure TMyForm.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.WindowClass.Style := Params.WindowClass.Style and (not CS_DROPSHADOW);
end;


Or, on systems with DWM enabled, maybe try using DwmSetWindowAttribute()
with the DWMWA_NCRENDERING_POLICY attribute set to DWMNCRP_DISABLED (not
sure if this affects the drop shadow or not).

--
Remy Lebeau (TeamB)
Jeff Allan

Posts: 6
Registered: 5/24/01
Re: Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 30, 2016 7:14 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thanks for your reply, Remy.

I tried the first solution for border width: setting the BorderStyle to bsSizeToolWin and bsSingle.
This only appears to make a pixel or two difference, and ignores the BorderWidth setting.
I don't want to lose the window's title bar and border entirely using bsNone, just make it thinner (like 1 or 2 pixels wide).

I also tried adding CreateParams() to my window class and removing CS_DROPSHADOW.
Unfortunately, that didn't make any difference.
The value of CS_DROPSHADOW (8) wasn't in the style object after calling the base class's version of CreateParams().

The attached screen shot shows 2 child windows:
- the left one is as I originally had them both
- the right one has bsSizeToolWin and a CS_DROPSHADOW removed
Not much difference.

These issues both feel like something that recent versions of Windows have taken control of, away from the app. If I use the "Windows Classic" theme, via Control Panel > Personalization, the window frames are narrower, square cornered, and generally more like what I'm going for (although they look old fashioned).

Any other suggestions?
Jeff
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 1, 2016 10:38 AM   in response to: Jeff Allan in response to: Jeff Allan
Jeff wrote:

I don't want to lose the window's title bar and border entirely using
bsNone, just make it thinner (like 1 or 2 pixels wide).

You are asking for finer grain control than what Windows natively offers.
You may have to resort to disabling the native borders altogether and custom-draw
your own borders manually. But that meas handling WM_NCCALCSIZE, WM_NCPAINT,
WM_NCHITTEST, etc. Things that Windows and the VCL already do for you.

These issues both feel like something that recent versions of Windows
have taken control of, away from the app.

Windows has never really offered the level of control you are looking for.
You usually have to take matters into your own hands when you need non-standard
behaviors.

--
Remy Lebeau (TeamB)
Jeff Allan

Posts: 6
Registered: 5/24/01
Re: Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 1, 2016 12:13 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thanks again for your feedback.
I was hoping for a simpler solution than drawing my own borders, but maybe one doesn't exist.
Jeff Allan
Asger Joergensen

Posts: 370
Registered: 11/18/08
Re: Thin window border  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 1, 2016 2:37 PM   in response to: Jeff Allan in response to: Jeff Allan
Hi Jeff

Depending on how pretty you want your borders and your caption,
this might be a solution for you, it works in win7 pro and is
made using CB2009:

Below is the Cpp code and the entire project is in attachment

Best regards
Asger

#define SC_SIZE_LEFT   0xF001
#define SC_SIZE_RIGHT  0xF002
#define SC_SIZE_TOP    0xF003
#define SC_SIZE_LT     0xF004
#define SC_SIZE_RT     0xF005
#define SC_SIZE_BOTTOM 0xF006
#define SC_SIZE_LB     0xF007
#define SC_SIZE_RB     0xF008
#define SC_MOVE_ALL    0xF012
 
int pad, corner;
 
//---------------------------------------------------------------------------
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
   pad = Padding->Left;
   corner = 10;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TopMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
   if( Shift.Contains(ssLeft) )
   {
      ReleaseCapture();
      Form1->Perform( WM_SYSCOMMAND, SC_MOVE_ALL, 0 );
   }
}
//---------------------------------------------------------------------------
TCursor TForm1::findCursor( int X, int Y )
{
   if( X > corner && X < Width - corner )
      return crSizeNS;
 
   if( Y > corner && Y < Height - corner )
      return crSizeWE;
 
   if( X <= corner && Y <= corner )
      return crSizeNWSE;
 
   if( X <= corner && Y >= Height - corner )
      return crSizeNESW;
 
   if( X >= Width - corner && Y <= corner )
      return crSizeNESW;
 
   if( X >= Width - corner && Y >= Height - corner )
      return crSizeNWSE;
 
   return crDefault;
 
}
//---------------------------------------------------------------------------
void TForm1::activateSizing(TCursor cur, int X, int Y)
{
   WPARAM direction;
   switch( cur )
   {
   case   crSizeNS: direction = Y < corner ? SC_SIZE_TOP  : SC_SIZE_BOTTOM; break;
   case   crSizeWE: direction = X < corner ? SC_SIZE_LEFT : SC_SIZE_RIGHT; break;
   case crSizeNWSE: if( X <= corner && Y <= corner )
                        direction = SC_SIZE_LT;
                    else if( X >= Width - corner && Y >= Height - corner )
                            direction = SC_SIZE_RB;
                    break;
   default:         if( X <= corner && Y >= Height - corner )
                        direction = SC_SIZE_LB;
                    else if( X >= Width - corner && Y <= corner )
                            direction = SC_SIZE_RT;
   } //end switch
 
   ReleaseCapture();
   Form1->Perform( WM_SYSCOMMAND, direction, 0 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
   TCursor cur = findCursor( X, Y );
 
   Screen->Cursor = cur;
 
   if( Shift.Contains( ssLeft ) )
   {
      activateSizing( cur, X, Y );
   }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseLeave(TObject *Sender)
{
   Screen->Cursor = crDefault;
}
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02