在调整TCustomControl后代的大小时,子控制闪烁

use*_*246 3 delphi delphi-7

很长一段时间,我TCustomPanel在我的应用程序中使用了名为MyContainer 的类的后代.我可以说是其他视觉控制的典型容器.这很好.有一天我意识到我根本不使用面板功能,所以我可以直接派生出MyContainer TCustomControl.

在这样做之后,当使用鼠标调整MyContainer的大小时,我会遇到儿童控件(例如对齐的TMemo)的可怕闪烁.这太可怕了 - 看起来整个TMemo已经消失了一会儿,所以我可以看到背景.MyContainer自己画得很好 - 这只是儿童控件的问题.

当MyContainer来自TCustomPanel时,它没有发生.我缺少什么,在哪里?子控件是双缓冲的,MyContainer也是.我使用Delphi 7个人版,所以我没有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);
Run Code Online (Sandbox Code Playgroud)

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

Del*_*ics 6

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

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

  1. 重写构造函数并将csAcceptsControls添加到容器控件的ControlStyle

要么

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

代码

选项1:

constructor TMyContainer.Create(Owner: TComponent);
begin
  inherited;
  ControlStyle := ControlStyle + [csAcceptsControls];
end;
Run Code Online (Sandbox Code Playgroud)

请注意,这意味着您的容器控件现在可以接受在设计时丢弃的控件.即使没有此ControlStyle,您也可以通过设置Parent属性在运行时向容器添加控件.

选项2:

procedure TMyContainer.CreateParams(var aParams: TCreateParams);
begin
  inherited;
  aParams.Style := aParams.Style or WS_CLIPCHILDREN;
end;
Run Code Online (Sandbox Code Playgroud)

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