Clayton Johnson
Clayton Johnson

Reputation: 279

Error Creating TActivityIndicator at Runtime

I saw the introduction of the TActivityIndicator in Delphi 10 Seattle and thought cool I could make use of this somewhere. I wanted to use this to show that some dynamically created sections of my form were still loading the data before populating the form. So I thought I'd do this before I start loading my data in FormShow, where self is the form.

indicator := TActivityIndicator.Create(self);
indicator.IndicatorSize := TActivityIndicatorSize.aisLarge;

Sadly when I try to create them dynamically and set then TActivityIndicator.IndicatorSize I get an exception ... EInvalidOperation with message 'Control '<name>' has no parent window' Which stepping through the VCL takes me to Vcl.Controls TWinControl.CreateWnd specifically

if (WndParent = 0) and (Style and WS_CHILD <> 0) then
  if (Owner <> nil) and (csReading in Owner.ComponentState) and
    (Owner is TWinControl) then
    WndParent := TWinControl(Owner).Handle
  else
    raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);

I've checked Owner is the form which is of course a TWinControl but (csReading in Owner.ComponentState) returns false. Stepping through Owner.ComponentState = [] on FormCreate and [csFreeNotification] on FormShow.

I've found that if you try to change the IndicatorSize of a TActivityIndicator that was created at design time then it works perfectly. So what am I missing here or is it not possible to create TActivityIndicators at runtime?

Upvotes: 1

Views: 703

Answers (1)

Ken White
Ken White

Reputation: 125749

The error message is pretty clear. You need to assign a Parent on which the activity indicator will draw itself. The Owner is the component responsible for freeing the control when the Owner is destroyed; the Parent is the control on which the control will be drawn (parented) for display.

The solution is to assign that parent in code:

Indicator := TActivityIndicator.Create(Self);
Indicator.Parent := Self; // <-- here
// Set any other properties here

The same issue is common on all visual controls (such as TEdit, TLabel, TMemo, and so forth), which all need to have a Parent assigned in order to have a place to paint themselves. And in some cases, a Parent is required in order for various properties in the child control to function correctly when they depend on the child having an HWND window, which requires a Parent window, and so on.

If I understand your intent, I think you're going to be disappointed, however. TActivityIndicator is pretty static; it's not threaded, which means it will cease updating if your form is busy and doesn't process timer messages (which it uses internally).

Upvotes: 4

Related Questions