在调整TCustomControl后代

时间:2016-06-28 20:55:04

标签: delphi delphi-7

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

这样做后,当使用鼠标调整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);

如果没有这段代码,子控件就不会闪烁,但是父控件的绘制会被破坏。

1 个答案:

答案 0 :(得分:6)

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

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

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

    1. 覆盖 CreateParams 并直接将 WS_CLIPCHILDREN 标记添加到容器控件的样式窗口中
    2. 守则

      选项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;
      

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