3
votes

For long time I used descendant of TCustomPanel class, called MyContainer, in my application. Typical container for other visual controls I can say. And it was fine. One day I realized that I don't use panel functionality at all so I can derive MyContainer directly from TCustomControl.

After doing so I experience horrible flickering for child controls (e.g. aligned TMemo) when MyContainer is being resized using mouse. It is just horrible - it looks like entire TMemo is disappering for a moment so I can see the background. MyContainer paints itself fine - it is a problem only with child controls.

It was not happening when MyContainer was derived from TCustomPanel. What I am missing and where? Child control is double buffered and MyContainer too. I use Delphi 7 Personal Edition, so I don't have VCL source and so I am unable to compare TCustomPanel with TCustomControl implementation. Handling WM_EXITSIZEMOVE and WM_ENTERSIZEMOVE messages (to enable/disable child align) does not help.

I believe my problem is connected with erasing control background. As part of my "migration" to TCustomControl I added the following code to Paint method:

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);

Without this code, child control does not flicker anymore but painting of parent control is ruined.

1
"I don't have VCL source" - why not? It has been included in every Delphi release since the dawn of time. Without seeing your actual code, we can't tell you what you are (or are not) doing wrong.Remy Lebeau
@Remy I can only guess it's either a cracked or trial version of Delphi 7.Jerry Dodge
Just curious as to why anyone would think that a cracked version would not come with everything that the legit version of that thing would not come with and focus on picking that apart rather than helping the OP. From the info in the question I suspected what the problem was. A couple of minutes later I had confirmed with a repro case. A couple of minutes after that I had a solution. It was a legit question with sufficient information to quickly identify the problem and reach a solution. The question absolutely did not deserve a downvote imho.Deltics
+Deltics Yes it does. And it should be closed because there is no minimal reproducible example. This isn't a game of 20 questions. Questions are required to specify the problem precisely.David Heffernan
@David Heffernan - I don't understand your definition of "precisely" because this question was demonstrably more than adequately precise. Some people seem to have an obsession (bordering on the fetishistic) with linking to the MCVE topic and beating people up for not providing code to spoon feed a repro case before deigning to even bother to try to help. It's simply not always necessary. Where it is, then fair enough, but where there is enough information to create a MCVE almost as quickly as one could be copy/pasted (as in this case) insisting on one is just pointlessly pedantic.Deltics

1 Answers

6
votes

The difference between TCustomPanel and TCustomControl that affects this behaviour is that TCustomPanel adds the csAcceptControls style to the ControlStyle in the constructor. This in turn then affects the behaviour in the TWinControl base class, which adds the WS_CLIPCHILDREN style to the window for the controls with that style set.

So, you can achieve the same result in one of two ways:

  1. Override the constructor and add the csAcceptsControls to the ControlStyle of your container control

OR

  1. Override CreateParams and directly add the WS_CLIPCHILDREN flag to the window Style of your container control

The Code

Option 1:

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

Note that this will mean that your container control can now accept controls dropped on it at design-time. Even without this ControlStyle you can add controls to a container at run-time by setting the Parent property.

Option 2:

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

This achieves the specific change in painting behaviour you are after but without affecting the ability of the control to accept controls at design-time.