TAdvSmoothPageSlider - Run time loading error

Using: TMSSmoothControls v (July 6, 2017) in Delphi Tokyo Pro

My app contains a TFrame that contains a TAdvSmoothPageSlider with *no* pages.

* The frame is created at runtime.
* Initialization logic then creates several TAdvSmoothPage instances inside the TAdvSmoothPageSlider.

This works fine apart from an AV:
Project MyApp.exe raised exception class EReadError with message 'Error reading PageSlider.ActivePageIndex: Control 'MyFrame' has no parent window'.

The debug stack pins this down to a request for a window handle during the dfm load of the frame processing property ActivePageIndex (which is -1). This occurs in the Create() so there is no chance to assign Parent.

My solution is:

unit AdvSmoothPageSlider.pas

1) Add "default -1" to property ActivePageIndex (Line 342)

TAdvSmoothPageSlider = class(TAdvSmoothPage, ITMSStyle, ITMSTones)
  property ActivePageIndex: Integer read GetActivePageIndex write SetActivePageIndex default -1;

This avoids unnecessary setter logic being fired.


2) Avoid GetPageRect() call if there are no pages (circa Line 2153):

procedure TAdvSmoothPageSlider.SetAllPagesPosition;
  i: Integer;
  R: TRect;
  APage: TAdvSmoothPage;
  if FPages.Count > 0 then //<<< ADDED
    R := GetPageRect;

This works for me - although may not be best solution. :-)

Footnote: Due to custom application settings, it is not practical to build the TAdvSmoothPageSlider and pages at design time.

While we are at it, is it possible to add more defaults to published properties to reduce the bloat in dfms? (HeaderFill, FooterFill, ... etc.) Ideally, the dfm should only include overridden properties.

Thanks, Ian

Follow up question:

I noticed TAdvSmoothPageSlider includes a FTimer (TTimer) instance which is always enabled with 10 msec timing.

I include 7 X TAdvSmoothPageSlider instances throughout my (multimedia) application. Should I be concerned about the overhead, seeing that the controls are only occasionally visible?

  1. We improved the code with respect to SetAllPagesPosition
    2. It is unclear how you have ActivePageIndex = -1. Did you force this value to -1? I could  not see this here otherwise. If a problem persists, you have some sample source project source with which we can reproduce this.
    3. Although, the less timers the better, 7 TTimer objects should not be a reason of concern.
  1. Great :-)
    2. ActivePageIndex := -1; is in constructor, so I'm matching the default value with that.
    3. Thanks.

    I have one additional problem dealing with the animation 'ghosting' on startup (ie. the shadow is drawn as if selecting a slide) even though the frame/pageslider is not visible. Any suggestions welcome, otherwise I'll see if I can reproduce it with a small sample.
  1. : Understood, that makes sense and we'll adapt it.

    For the ghosting, it would be helpful if there was a sample source project with which this can be reproduced so we have all details/settings/code.
Hi Bruno

In preparing a demo, I was able to diagnose the problem.

Basically, I was using a TSplitView on a main form with 'options' sliding in - which is where several AdvSmoothPageSliders are created.

I noticed that after startup, the DoTimer() is fired which has the FAnimate value true (for the first time only). This looks like the culprit, along with the fact that the FShadowForm is set to visible. The animation would therefore be performed for that one time.

My initial solution was to either:
a) Set ShadowColor := clNone, or
b) Set Visible := False
for *all* SmoothPages and containing Slider.

However, just setting the parent TSplitView visibility also worked. (Yeah!)

For what it's worth, the (working) demo is here...


A screen shot is included to illustrate the shadow after opening and closing the TSplitView - prior to appling the fix.

For the curious, the example does illustrate my attempt to implement theming on the Smooth controls. I use the buttons, listboxes, etc. extensively in my app, which caters for light and dark themes. 

I'm still nervous about the 10 msec timer :-) I'd be happier if that was only enabled if the control was visible.

Thanks for your assistance.

Regards, Ian


Thank you for your feedback. We'll investigate if we can improve the behaviour with the shadowcolor and the timer.
Thanks Pieter.

My earlier testing with setting a parent control Visible to false to prevent the shadow form 'ghosting' is inconclusive as it was not easy to debug. A revised fix was a small change in SetActivePageIndex() to prevented the timer to trigger first time if the control was not visible.

procedure TAdvSmoothPageSlider.SetActivePageIndex(const Value: Integer);
  if csDesigning in ComponentState then
    if Assigned(ActivePage) then
  FAnimate := Visible; // Was: True;


We've applied the fix, the next version will address this.