Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi Borderless and Captionless Application

I am willing to designed one Application in Delphi XE2 Borderlessly and Captionlessly by using the following code :

  BorderIcons = []
  BorderStyle = bsNone

But the problem is that there is no Menu on Right Click on the Application on Taskbar just like in the above image. Then I have tried the following codes on FormShow event, but there is also another problem. One Border is created on Left side and Left-Botton side. The codes are :

procedure TForm1.FormShow(Sender: TObject);
var
  r: TRect;
begin
  r := ClientRect;
  OffsetRect(r, 0, GetSystemMetrics(SM_CYCAPTION));
  OffsetRect(r, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
  SetWindowRgn(Handle,
  CreateRectRgn(
  r.Left, r.Top,
  ClientWidth + r.Left, ClientHeight + r.Top), True);

end;

Please help me.

like image 647
Rubi Halder Avatar asked Jan 16 '12 18:01

Rubi Halder


3 Answers

The simple solution is not to remove the system menu in the first place. Note that the system menu is the official name for the menu that is missing in your app.

Make your .dfm file look like this:

BorderIcons = [biSystemMenu]
BorderStyle = bsNone

Get rid of that FormShow code–it's not needed.

OK, it looks like a stray bit of code from my experimentation was confounding me. Here's what works.

Do exactly what you originally did in your .dfm form:

BorderIcons = []
BorderStyle = bsNone

Then add back the system menu using CreateParams:

TForm1 = class(TForm)
protected
  procedure CreateParams(var Params: TCreateParams); override;
end;
...
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style := Params.Style or WS_SYSMENU;
end;
like image 132
David Heffernan Avatar answered Oct 14 '22 19:10

David Heffernan


procedure TForm1.FormCreate(Sender: TObject);
begin
  BorderStyle := bsNone;
  SetWindowLong(Handle, GWL_STYLE, 
      WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU);
  SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_CONTROLPARENT or WS_EX_APPWINDOW);
end;

You don't need the code in the OnShow handler with this solution.

The above code can be called any time (not just in OnCreate), it can be used to alter the behavior of a running form for instance (just include WS_VISIBLE to window styles if the form is already visible).

If you want the behavior to be in effect for the life time of the form, it's better to set the flags in an overriden CreateParams (where form styles are applied by VCL). This will also take possible recreation of the form into account. Don't set any form property from the OI for this solution, all of the flags are explicitly set in the code:

type
  TForm1 = class(TForm)
    ..
  protected
    procedure CreateParams(var Params: TCreateParams); override;

..

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.Style := WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU;
  Params.ExStyle := WS_EX_CONTROLPARENT or WS_EX_APPWINDOW;
end;
like image 27
Sertac Akyuz Avatar answered Oct 14 '22 19:10

Sertac Akyuz


You can have a window that appears not to have a caption bar, or a standard caption, by simply taking over the painting of the entire window:

Create a new empty application. Use this code for your form:

unit ncUnit1;

interface

// XE2 uses clause
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,      
  Vcl.Graphics,   Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
// If you're not using XE2 take out the prefixes (WinApi, Vcl, System, etc)

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  protected
    procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
    procedure SolidColorNcPaint(solidColor,frameColor:TColor);
    procedure Resizing(State: TWindowState); override;


  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.WMNCPaint(var Message: TWMNCPaint);
begin
  SolidColorNcPaint(clBtnFace,clBtnFace);
end;

procedure TForm1.Resizing(State: TWindowState);
begin
  inherited;
  PostMessage(Self.Handle,WM_NCPAINT,0,0); {force initial paint}
end;

procedure TForm1.SolidColorNcPaint(solidColor,frameColor:TColor);
var
 aBorder:Integer;
 ahdc : HDC;
begin
 aBorder := GetSystemMetrics(SM_CYSIZEFRAME);
 canvas.Lock;
 ahdc := GetWindowDC(Handle);
 canvas.Handle := ahdc;
 ExcludeClipRect(canvas.Handle, aBorder, 0, Width-aBorder, Height - aBorder) ;
 Canvas.Brush.Style := bsSolid;
 Canvas.Brush.Color := frameColor;
 Canvas.Pen.Color := solidColor;
 Canvas.Rectangle( 0,0, Width,Height);
 ReleaseDC(Self.Handle, ahdc);
 canvas.Handle := 0;
 canvas.Unlock;
end;


end.

What you see above is only enough code to redraw a solid color over the non-client area of the window, not to remove it completely. Depending on the style of custom window you want, you should render whatever you want on the form. If you don't want a Close button then remove the close button, and if you do not want the resizing behaviour, remove the resizing behaviour. If you set the FormStyle=fsDialog plus the above code, you would get a window that has a complete custom drawn title area (which you can put whatever you want into). If you actually don't want the title area to exist at all, you can modify the above code to achieve that too.

like image 3
Warren P Avatar answered Oct 14 '22 19:10

Warren P