【问题标题】:Child controls flicker during resize of TCustomControl descendant在调整 TCustomControl 后代的大小期间子控件闪烁
【发布时间】:2016-10-31 08:48:57
【问题描述】:

长期以来,我在我的应用程序中使用了 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 我只能猜测它是 Delphi 7 的破解版或试用版。
  • 只是好奇为什么有人会认为破解版不会附带该东西的合法版本不会附带的所有内容,并专注于将其分开而不是帮助 OP。根据问题中的信息,我怀疑问题出在哪里。几分钟后,我确认了一个复制案例。几分钟后,我有了解决方案。这是一个合法的问题,有足够的信息来快速识别问题并找到解决方案。恕我直言,这个问题绝对值得一票否决。
  • +Deltics 是的。它应该被关闭,因为没有minimal reproducible example。这不是 20 个问题的游戏。需要问题才能准确地说明问题。
  • @David Heffernan - 我不明白你对“精确”的定义,因为这个问题显然已经足够精确了。有些人似乎痴迷于(近乎恋物癖)链接到 MCVE 主题并殴打人们,因为他们没有提供代码来舀喂重现案例,然后才屈尊试图提供帮助。这根本不是总是必要的。它在哪里,那么就足够公平了,但是如果有足够的信息来创建一个 MCVE,几乎可以像复制/粘贴一样快(如在本例中)坚持一个只是毫无意义的迂腐。

标签: delphi delphi-7


【解决方案1】:

TCustomPanelTCustomControl 之间影响此行为的区别在于 TCustomPanelcsAcceptControls 样式添加到ControlStyle 在构造函数中。这反过来会影响 TWinControl 基类中的行为,该基类会将 WS_CLIPCHILDREN 样式添加到具有该样式集的控件的窗口中。

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

  1. 覆盖 constructor 并将 csAcceptsControls 添加到容器控件的 ControlStyle

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

代码

选项 1:

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

请注意,这意味着您的容器控件现在可以接受在设计时放置在其上的控件。即使没有此 ControlStyle,您也可以通过设置 Parent 属性在运行时将控件添加到容器。

选项 2:

procedure TMyContainer.CreateParams(var aParams: TCreateParams);
begin
  inherited;
  aParams.Style := aParams.Style or WS_CLIPCHILDREN;
end;

这实现了您所追求的绘画行为的特定变化,但不影响控件在设计时接受控件的能力。

【讨论】:

  • 选项 2 因此将 WS_CLIPCHILDREN 添加到参数中就可以了。谢谢!
猜你喜欢
  • 2013-03-25
  • 2019-01-09
  • 2014-11-25
  • 2011-03-28
  • 2019-01-05
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 2015-01-24
相关资源
最近更新 更多