Delphi XE2样式绘制

3

在绘制VCL样式窗口元素时,我遇到了角落被错误地涂绘的问题。在具有圆角的样式中,控件的边框和样式的圆形窗口角之间的空间会出现白色背景。

enter image description here

上面的图片是使用Aqua Light Slate运行的,但任何具有圆角的样式都会显示相同的问题。我错过了什么?

type
  TSample = class(TCustomControl)
  protected
    procedure Paint; override;
  end;

{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
  R: TRect;
  S: TSample;
begin
  R := ClientRect;
  InflateRect(R, -20, -20);
  S := TSample.Create(Application);
  S.Parent := Self;
  S.BoundsRect := R;
end;

{ TSample }
procedure TSample.Paint;
var
  Details: TThemedElementDetails;
begin
  Details := StyleServices.GetElementDetails(twCaptionActive);
  StyleServices.DrawParentBackground(Self.Handle, Canvas.Handle, Details, False);
  StyleServices.DrawElement(Canvas.Handle, Details, ClientRect);
end;

顺便说一句,我也尝试了ParentBackground := True,但没有变化。还尝试过确保删除csOpaque。 - DaveS_Lifeway
你是否已经厌倦了调试 StyleServices.DrawElement 方法以查看它如何在画布上绘制位图? - RRUZ
坦白说,我本来希望避免深入主题引擎的内部,但如果没有更好的想法,那就只能这样做了。 - DaveS_Lifeway
不幸的是,这并没有起到帮助作用。DrawElement 无论是在离屏位图还是控件画布上都会绘制白色的角落。我通过先使用纯色填充离屏位图,然后调用一个矩形为位图宽度不足并且居中的 DrawElement 来证明了这一点。结果是两侧都是我的纯色以及中间的标题栏,而且依然有白色的角落。出于某种原因,DrawElement 没有透明地绘制角落。 - DaveS_Lifeway
1个回答

5
好的,我花了一些时间研究了你的问题,并找到了答案。绘制圆角的关键是调用 StyleServices.GetElementRegion 函数获取区域,然后使用 SetWindowRgn 函数将该区域应用于控件。
请参考以下示例。
procedure TSample.Paint;
var
  Details : TThemedElementDetails;
  Region  : HRgn;
  LRect   : TRect;
begin
  Details := StyleServices.GetElementDetails(twCaptionActive);
  LRect := Rect(0, 0, Width, Height);
  StyleServices.GetElementRegion(Details, LRect, Region);
  SetWindowRgn(Handle, Region, True);
  StyleServices.DrawParentBackground(Self.Handle, Canvas.Handle, Details, False);
  StyleServices.DrawElement(Canvas.Handle, Details, ClientRect);
end;

以下是结果

图片描述


注:本文涉及IT技术相关内容。

这绝对有效,非常感谢您的帮助!对于使用离屏位图作为标题区域的情况,这也是有效的。对于其他人做类似事情的人来说,值得指出的是整个客户端矩形需要传递给GetElementRegion。 - DaveS_Lifeway

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接