TCustomControl派生控件调整大小时子控件闪烁问题

4

我曾经在我的应用程序中使用TCustomPanel类的后代,称为MyContainer,作为其他可视控件的典型容器。这样做一直很好。有一天我意识到我根本没有使用面板功能,因此我可以直接从TCustomControl派生 MyContainer。

但是,这样做后,当通过鼠标调整MyContainer的大小时,子控件(例如对齐的TMemo)会出现可怕的闪烁。情况非常糟糕 - 看起来整个TMemo正在消失,以至于我可以看到背景。MyContainer自己绘制得很好 - 这只是子控件的问题。

在MyContainer从TCustomPanel派生时,这种情况并未发生。我错过了什么?子控件是双缓冲的,MyContainer也是。由于我使用的是Delphi 7 Personal Edition,所以我没有VCL源代码,因此无法比较TCustomPanel和TCustomControl的实现。处理WM_EXITSIZEMOVEWM_ENTERSIZEMOVE消息(以启用/禁用子对齐)没有帮助。

我相信我的问题与擦除控件背景有关。作为迁移到TCustomControl的一部分,我将以下代码添加到Paint方法中:

Canvas.Font.Assign(Font);
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := Color;
PatBlt(Canvas.Handle, Canvas.ClipRect.Left, Canvas.ClipRect.Top, Canvas.ClipRect.Right, Canvas.ClipRect.Bottom, PATCOPY);

没有这段代码,子控件不再闪烁,但父控件的绘制被破坏。


“我没有 VCL 源代码” - 为什么没有?自从 Delphi 诞生以来,它一直被包含在每个版本中。如果我们看不到您的实际代码,就无法告诉您您正在做错什么(或没有做错)。 - Remy Lebeau
我使用的是Delphi 7个人版。 - user3848246
1
只是好奇为什么有人会认为破解版不会带有正版版本所没有的一切,并专注于挑毛病而不是帮助OP。从问题中的信息,我怀疑问题所在。几分钟后,我通过重现案例进行了确认。再过几分钟,我就有了解决方案。这是一个合法的问题,提供了足够的信息来快速识别问题并找到解决方案。在我看来,这个问题绝对不应该被downvote。 - Deltics
1
+Deltics 是的,它确实有。而且应该关闭,因为没有 [mcve]。这不是20个问题的游戏。问题需要精确地指定问题。 - David Heffernan
2
@David Heffernan - 我不理解你对“精确”的定义,因为这个问题显然已经足够精确了。有些人似乎着迷于链接到MCVE主题,并因为没有提供代码来喂养一个可重现的案例而殴打别人,然后才愿意尝试帮助。这并不总是必要的。在需要的地方,那就好,但是在有足够信息可以创建一个MCVE几乎和复制/粘贴一样快(就像这种情况),坚持使用一个只是毫无意义的追求严谨。 - Deltics
显示剩余8条评论
1个回答

7
TCustomPanel和TCustomControl之间的区别会影响这种行为,因为TCustomPanel在构造函数中向ControlStyle添加了csAcceptControls样式。这反过来会影响TWinControl基类中的行为,该基类为具有设置了该样式的控件添加WS_CLIPCHILDREN样式的窗口。

因此,您可以通过以下两种方式之一实现相同的结果:

  1. 覆盖构造函数并将csAcceptsControls添加到容器控件的ControlStyle中

或者

  1. 覆盖CreateParams并直接将WS_CLIPCHILDREN标志添加到容器控件的窗口Style中

代码

选项1:

constructor TMyContainer.Create(Owner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptsControls];
end;

请注意,这意味着您的容器控件现在可以在设计时接受拖放的控件。即使没有这个ControlStyle,您也可以通过设置Parent属性在运行时向容器添加控件。
procedure TMyContainer.CreateParams(var aParams: TCreateParams);
begin
  inherited;
  aParams.Style := aParams.Style or WS_CLIPCHILDREN;
end;

这样做可以实现您想要的绘画行为的特定更改,但不会影响控件在设计时接受控制的能力。

选项2,因此将WS_CLIPCHILDREN添加到参数中就可以了。谢谢! - user3848246

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