Delphi Borderless и Captionless Application - PullRequest
5 голосов
/ 16 января 2012

Я готов сконструировать одно приложение в Delphi XE2 без границ и надписей, используя следующий код:

  BorderIcons = []
  BorderStyle = bsNone

Но проблема в том, что меню правой кнопкой мыши на приложении на панели задач нет, какна изображении выше.Затем я попробовал следующие коды на событии FormShow, но есть и другая проблема.Одна граница создается на левой стороне и левой-нижней стороне.Коды:

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;

Пожалуйста, помогите мне.

Ответы [ 4 ]

7 голосов
/ 17 января 2012

Простое решение - не удалять системное меню в первую очередь.Обратите внимание, что системное меню является официальным названием меню, которое отсутствует в вашем приложении.

Сделайте так, чтобы ваш файл .dfm выглядел следующим образом:

BorderIcons = [biSystemMenu]
BorderStyle = bsNone

Избавьтесь от этого FormShowкод - он не нужен.

ОК, похоже, что какой-то случайный код из моих экспериментов смутил меня.Вот что работает.

Сделайте именно то, что вы изначально делали в форме .dfm:

BorderIcons = []
BorderStyle = bsNone

Затем добавьте обратно системное меню, используя 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;
5 голосов
/ 17 января 2012
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;

Вам не нужен код в обработчике OnShow с этим решением.

Приведенный выше код можно вызывать в любое время (не только в OnCreate), его можно использовать, например, для изменения поведения работающей формы (просто включите WS_VISIBLE в стили окон, если формауже видно).

Если вы хотите, чтобы поведение действовало на время жизни формы, лучше установить флаги в переопределении CreateParams (где стили формы применяются VCL).Это также примет во внимание возможное воссоздание формы.Не устанавливайте никаких свойств формы из OI для этого решения, все флаги явно установлены в коде:

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;
3 голосов
/ 17 января 2012

У вас может быть окно, в котором нет заголовка или стандартного заголовка, просто взяв на себя рисование всего окна:

Создайте новое пустое приложение.Используйте этот код для своей формы:

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.

То, что вы видите выше, достаточно только для того, чтобы перерисовать сплошным цветом область, не относящуюся к клиенту, а не удалить ее полностью.В зависимости от стиля пользовательского окна, которое вы хотите, вы должны отобразить все, что вы хотите в форме.Если вам не нужна кнопка «Закрыть», удалите кнопку «Закрыть», а если вам не нужно поведение изменения размера, удалите поведение изменения размера.Если вы установите FormStyle=fsDialog плюс приведенный выше код, вы получите окно с полной произвольно нарисованной областью заголовка (в которую вы можете поместить все, что захотите).Если вы на самом деле не хотите, чтобы область заголовка вообще существовала, вы можете изменить приведенный выше код, чтобы добиться этого тоже.

2 голосов
/ 17 января 2012

Вы можете сделать то, что Дэвид говорит и / или также взглянуть на: SetWindowRgn API.

Если вы используете только SetWindowRgn, вам не нужно удалять границу TForm, просто сделайте прямоугольник, который начинается под ним.

...