【问题标题】:Is there a way to round Delphi VCL Form without losing native windows borders有没有办法在不丢失本机窗口边框的情况下舍入 Delphi VCL 表单
【发布时间】:2021-04-09 14:32:58
【问题描述】:

我在这里有这个回购DelphiUCL

这是一个非常好的 Lib,它允许 bsSisezable 表单看起来像 UWP Forms 并且引起我注意的是,当我调整此表单的大小时,它仍然调整为 bsResizable 表单而不像 bsNone 表单

我需要确切知道的内容: 有没有办法在不丢失本机窗口边框的情况下创建平滑圆角 Delphi VCL 表单?

【问题讨论】:

  • 在 Delphi XE3 中引入了 VCL 样式(如果没有记错的话)。有些款式的上角是圆形的,有些款式的所有角都是圆形的。即使在 Windows 10 上。虽然不清楚您使用的 Delphi 版本以及您的目标 Windows 版本(如果不是 Windows 10)。请澄清。
  • 你不能在这里要求图书馆推荐,help center 指导方针明确说明了这一点。我已经编辑了你的问题。
  • 我认为具体问题的答案是否定的。您要求同时有两个相互冲突的要求。
  • 原生窗口边框不是圆形的。因此答案是否定的。
  • @DavidHeffernan |很抱歉..我只是想开箱即用,也许 delphi vcl 形式可以通过一些技巧或解决方法 API 来完成(非常尊重和感谢)

标签: user-interface delphi user-experience vcl


【解决方案1】:

我有一个解决方法,但我不知道它是否符合您的需要。解决方法包括定义一个圆角矩形区域来剪辑窗口以删除标题栏和边框。这样一来,窗口就是一个圆角矩形。

然后,要取回标题栏和边框,您必须 - 例如 - 检测鼠标是否靠近边缘之一,如果是,则删除该区域,以便标题栏和边框再次可见并且可以使用。

所有这些都涉及处理一些消息。

代码如下:

unit RegionDemoMain;

interface

uses
    Winapi.Windows, Winapi.Messages,
    System.SysUtils, System.Variants, System.Classes,
    Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
    TRoundedForm = class(TForm)
        CloseButton: TButton;
        HelpLabel: TLabel;
        procedure FormCreate(Sender: TObject);
        procedure CloseButtonClick(Sender: TObject);
        procedure WMMouseMove(var Msg : TWMMouseMove); message WM_MOUSEMOVE;
        procedure WMNCMouseLeave(var Msg : TMessage); message WM_NCMOUSELEAVE;
        procedure WMNCButtonDown(var Msg : TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
        procedure WMNCButtonUp(var Msg : TWMNCLButtonUp); message WM_NCLBUTTONUP;
        procedure WMSYSCommand(var Msg : TWMSysCommand); message WM_SYSCOMMAND;
    private
        FRgnHandle       : HRGN;
        FRgnTop          : Integer;
        FRgnBottom       : Integer;
        FRgnRight        : Integer;
        FRgnLeft         : Integer;
        FRgnCorner       : Integer;
        FMouseLeaveCount : Integer;
        FNCLButtonDown   : Boolean;
        procedure DeleteRegion;
        procedure CreateRegion;
    end;

var
  RoundedForm: TRoundedForm;

implementation

{$R *.dfm}

procedure TRoundedForm.FormCreate(Sender: TObject);
begin
    FRgnTop    := GetSystemMetrics(SM_CYCAPTION) +
                  GetSystemMetrics(SM_CYFRAME) +
                  GetSystemMetrics(SM_CYFRAME); 
    FRgnBottom := GetSystemMetrics(SM_CYFRAME) +
                  GetSystemMetrics(SM_CYFRAME);
    FRgnRight  := GetSystemMetrics(SM_CXFRAME) +
                  GetSystemMetrics(SM_CXFRAME);
    FRgnLeft   := GetSystemMetrics(SM_CXFRAME) +
                  GetSystemMetrics(SM_CXFRAME);
    FRgnCorner := 15;
    CreateRegion;
end;

procedure TRoundedForm.CreateRegion;
begin
    if FRgnHandle <> 0 then
        DeleteObject(FRgnHandle);
    FRgnHandle := CreateRoundRectRgn(FRgnLeft,
                                     FRgnTop,
                                     Width  - FRgnRight,
                                     Height - FRgnBottom,
                                     FRgnCorner,
                                     FRgnCorner);
    SetWindowRGN(Handle, FRgnHandle, True);
end;

procedure TRoundedForm.CloseButtonClick(Sender: TObject);
begin
    Close;
end;

procedure TRoundedForm.DeleteRegion;
begin
    if FRgnHandle <> 0 then begin
        SetWindowRGN(Handle, 0, True);
        DeleteObject(FRgnHandle);
        FRgnHandle := 0;
    end;
end;

procedure TRoundedForm.WMMouseMove(var Msg: TWMMouseMove);
begin
    if (Msg.YPos < GetSystemMetrics(SM_CYSIZEFRAME)) or
       (Msg.YPos > (Height - 55)) or
       (Msg.XPos < 10) or
       (Msg.XPos > (Width - 25)) then
        DeleteRegion
    else if (FRgnHandle = 0) and (Msg.YPos > 10) then
        CreateRegion;
    inherited;
end;

procedure TRoundedForm.WMNCButtonDown(var Msg: TWMNCLButtonDown);
begin
    FNCLButtonDown := TRUE;
    inherited;
end;

procedure TRoundedForm.WMNCButtonUp(var Msg: TWMNCLButtonUp);
begin
    FNCLButtonDown := FALSE;
    inherited;
end;

procedure TRoundedForm.WMNCMouseLeave(var Msg : TMessage);
begin
    Inc(FMouseLeaveCount);
    if (FRgnHandle = 0) and (not FNCLButtonDown) then
        CreateRegion;
    inherited;
end;

procedure TRoundedForm.WMSYSCommand(var Msg: TWMSysCommand);
begin
    if Msg.CmdType = SC_RESTORE then
        CreateRegion;
    inherited;
end;

end.

和 DFM 文件:

object RoundedForm: TRoundedForm
  Left = 0
  Top = 0
  Caption = 'RoundedForm'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object HelpLabel: TLabel
    Left = 200
    Top = 96
    Width = 222
    Height = 13
    Caption = 'Move the cursor near one edge of the window'
  end
  object CloseButton: TButton
    Left = 268
    Top = 132
    Width = 75
    Height = 25
    Caption = 'CloseButton'
    TabOrder = 0
    OnClick = CloseButtonClick
  end
end

【讨论】:

  • |这正是我要搜索的内容,我认为这对于解决我的上述请求非常有用(非常感谢)
  • @Roberto 很高兴为您提供帮助。请使用我的答案左侧的勾号将我的答案标记为“已接受”。
  • |不,它仍然不完整......我仍然必须找到一个解决方案来隐藏原生窗口边框,而它们出现......我必须找到一个技巧来让原生边框看起来像隐藏但它们不是......
  • 我确实用 TUForm (TRoundedForm = class(TUForm)) 替换了代码中的类 TForm 并且工作正常,但仍然缺少可以隐藏本机窗口边框且不会丢失任何代码或技巧TForm 的选项,如原生阴影等 ...
  • @Roberto 您说“这正是我要寻找的”,现在您想要更多……我建议您接受我的回答并提出一个新问题,并正确解释了新要求。使用 Paint,创建一个图像并使用您想要的注释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2015-09-20
相关资源
最近更新 更多