【问题标题】:How to make TFrame with rounded corners?如何制作圆角的TFrame?
【发布时间】:2012-07-25 09:33:35
【问题描述】:

我想制作一个基于TFrameTLMDShapeControl(用于绘制圆角背景)和TEdit 控件(也可以是TComboBoxTDBEdit 等)的组件. 之后我将使用“Add to Palette”命令将它变成一个可重用的组件控件。

问题在于我需要它的宽度是灵活的,为此我想到了将框架alClientTEdit 内的所有内容以5 像素的边距转动,以便用户可以看到圆角。

这太糟糕了,因为我不能使用Align 并将组件设置在另一个顶部。现在我每次必须使用它时都必须复制并粘贴组件! :-(((

我认为正确的唯一方法是仅使用 TEditalClient 和 5px 边距,而不使用 TShape。相反,我可以将TFrame 设置为具有透明度的圆角,这样在使用不同颜色或TImages 时它不会显得难看。

但是我该怎么做呢?

有人有代码示例吗?

【问题讨论】:

  • 如果我想让它正常工作,我会制作自己的控件,并将其安装为一个包,其中包含外部和内部控件,并包含我想要制作的所有代码工作。 TFrame 不是正确的父类。我会使用普通的TCustomControl。框架用于在设计时而不是在编译时组合视觉控件。但编译您自己的自定义控件是更可靠、更有弹性的解决方案。
  • 我已经做到了,使用内置的 TShape 而不是 TLMDShapeControl 并且效果很好。但最后,我放弃了这些风格,因为我的客户讨厌这些非本土风格并希望它们消失。
  • 是的,TShape 可以圆角,但输出有很多错误。我没有工作人员,所以我是调查需求、制定项目、代码和系统设计以及我的项目数据库的人,我没有可能成为其中之一的专家事情……但是! :-)
  • 使用CreateRoundRectRgn也是如此。 GDI 只是不支持任何类型的抗锯齿,因此您不会获得平滑的角落。如果我是你,我会像 Warren 建议的那样使用 TCustomControl,例如this way。那么只是两个问题,一个是这种控件的透明度,第二个是需要一个可以为您的角落渲染平滑弧线的库。
  • 更糟糕的是你不能设置圆度的百分比...所以如果你创建一个大控件,你会得到一个大角。

标签: delphi user-interface frame delphi-2006


【解决方案1】:

要回答你的问题如何制作圆角框架,你可以尝试这样的方法,但你会对结果不满意,因为这里使用的CreateRoundRectRgn 没有抗锯齿。

type
  TFrame1 = class(TFrame)
    Edit1: TEdit;
    Button1: TButton;
  protected
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  end;

implementation

procedure TFrame1.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
  Region: HRGN;
begin
  inherited;
  Region := CreateRoundRectRgn(0, 0, ClientWidth, ClientHeight, 30, 30);
  SetWindowRgn(Handle, Region, True);
end;

更新:

由于 GDI 没有任何支持弧形渲染的抗锯齿功能,我在这里发布了一个使用 GDI+ 的圆角矩形形状(只是一个纯实心圆角矩形)的示例(为此,您将需要 GDI+ 包装器) from here)。

以下属性对其使用很重要:

  • 颜色 - 是形状填充颜色(可以增强笔颜色、渐变等)
  • Radius - 是用于绘制圆角的圆的​​半径(以像素为单位)
  • AlphaValue - 是渲染圆角矩形的不透明度值(只是为了好玩:-)

unit RoundShape;

interface

uses
  SysUtils, Classes, Controls, Graphics, GdiPlus;

type
  TCustomRoundShape = class(TGraphicControl)
  private
    FRadius: Integer;
    FAlphaValue: Integer;
    procedure SetRadius(Value: Integer);
    procedure SetAlphaValue(Value: Integer);
  protected
    procedure Paint; override;
    property Radius: Integer read FRadius write SetRadius default 10;
    property AlphaValue: Integer read FAlphaValue write SetAlphaValue default 255;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TRoundShape = class(TCustomRoundShape)
  public
    property Canvas;
  published
    property Align;
    property AlphaValue;
    property Anchors;
    property Color;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property Font;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property Radius;
    property ShowHint;
    property Visible;
    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnMouseActivate;
    property OnMouseDown;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;
  end;

procedure Register;

implementation

{ TCustomRoundShape }

constructor TCustomRoundShape.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Width := 213;
  Height := 104;
  FRadius := 10;
  FAlphaValue := 255;
end;

procedure TCustomRoundShape.SetRadius(Value: Integer);
begin
  if FRadius <> Value then
  begin
    FRadius := Value;
    Invalidate;
  end;
end;

procedure TCustomRoundShape.SetAlphaValue(Value: Integer);
begin
  if FAlphaValue <> Value then
  begin
    FAlphaValue := Value;
    Invalidate;
  end;
end;

procedure TCustomRoundShape.Paint;
var
  GPPen: TGPPen;
  GPColor: TGPColor;
  GPGraphics: IGPGraphics;
  GPSolidBrush: IGPSolidBrush;
  GPGraphicsPath: IGPGraphicsPath;
begin
  GPGraphicsPath := TGPGraphicsPath.Create;
  GPGraphicsPath.Reset;
  GPGraphicsPath.AddArc(0, 0, FRadius, FRadius, 180, 90);
  GPGraphicsPath.AddArc(ClientWidth - FRadius - 1, 0, FRadius, FRadius, 270, 90);
  GPGraphicsPath.AddArc(ClientWidth - FRadius - 1, ClientHeight - FRadius - 1,
    FRadius, FRadius, 0, 90);
  GPGraphicsPath.AddArc(0, ClientHeight - FRadius - 1, FRadius, FRadius, 90, 90);
  GPGraphicsPath.CloseFigure;

  GPColor.InitializeFromColorRef(ColorToRGB(Color));
  GPColor.Alpha := FAlphaValue;
  GPPen := TGPPen.Create(GPColor);
  GPSolidBrush := TGPSolidBrush.Create(GPColor);

  GPGraphics := TGPGraphics.Create(Canvas.Handle);
  GPGraphics.SmoothingMode := SmoothingModeAntiAlias;
  GPGraphics.FillPath(GPSolidBrush, GPGraphicsPath);
  GPGraphics.DrawPath(GPPen, GPGraphicsPath);
end;

procedure Register;
begin
  RegisterComponents('Stack Overflow', [TRoundShape]);
end;

end.

结果(应用SmoothingModeAntiAlias平滑模式):

可以说,将 GDI+ 用于如此微小但没有抗锯齿的纯 GDI 渲染会使结果看起来很难看,这是一个很大的开销。以下是使用纯 GDI 渲染的同一个圆角矩形的示例:

【讨论】:

  • 这回答了我的问题。我将尝试制作一个组件,我们可以在其中选择我们想要的圆形上方的控件类型,看看它是否比 tframe 方式更好。谢谢!
  • 不客气!但我必须警告你;例如,如果您遵循我在上面评论中提到的TCustomControl 方式,请注意透明度。当 Windows 主题被禁用时,我一直试图使容器控件(例如 TPanel)透明,但它从未令人满意。
  • 我们如何将这个新组件应用到圆角框架上?
  • 它只是一个带有抗锯齿角的形状组件,您可以用 TShape 替换它。自从您在上面的 cmets 中讨论了 TShape 后,我就将其发布在这里。但是框架可以是透明的(ParentBackground 设置为 True),因此将这个形状置于您的控制之下可能就足够了。
  • 如果您使用区域方法,请不要忘记在每次调整框架大小时调整区域大小。仅在CreateWnd() 中创建一个固定大小的区域是不够的。
猜你喜欢
  • 2011-01-28
  • 2011-10-29
  • 2011-08-07
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 2014-11-22
相关资源
最近更新 更多