Link to home
Start Free TrialLog in
Avatar of WaitingWonder2
WaitingWonder2

asked on

OnAfterShow Event

I need to create an aftershow event for a form when a form becomes visible. I did write a code that works fine when the form is not modal but I still fight to get the solution for modal forms. I want to make a form that will be a parent form for all forms in my project. The only thought that I have is to re-write TCustomForm from VCL...

P.S. I have seen the solution from https://www.experts-exchange.com/questions/20690523/AfterShow-Event.html?sfQueryTermInfo=1+onaftershow I think it's hacky and don't like it. So, I need a correct solution even if it will need to re-wrote some VCL classes.

TAdvForm = class(TForm)
  private
    FOnAfterShow: TNotifyEvent;
  protected
    procedure DoAfterShow; dynamic;
  public
    procedure Show;
  published
    property OnAfterShow: TNotifyEvent read FOnAfterShow write FOnAfterShow;
  end;

implementation

{$R *.dfm}

procedure TAdvForm.DoAfterShow;
begin
  if Assigned(FOnAfterShow) then FOnAfterShow(Self);
end;

procedure TAdvForm.Show;
begin
  inherited Show;
  DoAfterShow;
end;

Open in new window

Avatar of cyberkiwi
cyberkiwi
Flag of New Zealand image

Just override DoShow
That's why it is set to dynamic, so that you can!

// this is from Forms
procedure TCustomForm.DoShow;
begin
  if Assigned(FOnShow) then FOnShow(Self);
end;

// this is yours
procedure TCustomForm.DoShow;
begin
  if Assigned(FOnShow) then FOnShow(Self);
  if Assigned(FOnAfterShow) then FOnAfterShow(Self);
end;
Avatar of WaitingWonder2
WaitingWonder2

ASKER

Your code is not working since FOnShow is a private variable in TCustomForm. Even if I make:

procedure TAdvForm.DoShow;
begin
  inherited DoShow;
  if Assigned(FOnAfterShow) then FOnAfterShow(Self);
end;

My OnAfterShow will be called before the forms becomes visible (the same as OnShow event) but I need after.
Good point.
sub OnShow for FOnShow.

Either of

Form.Activate
Form.VisibleChanging

depending on when you need it to happen.  A private property to track first time show also if required.
Activate is probably the first thing that happens after becoming visible.
Both this methods were given in the original post. I don't like a work-around solution with Form.Activate, I wrote it at the beginning in my first post.

Form.VisibleChanging is calling when Visible is changing, i.e. before showing a form and before closing a form.

Please, test you solution before providing it. It feels like you are guessing, not knowing the correct solution.
Mate,

If you want things to happen after the form's onshow is called (that's what "OnAfterShow" implies, then override DoShow).

If you want it to happen just before it becomes visible to the user, override VisibleChanging

If you want it to happen right after it becomes visible, override the Paint method - but this may not be called due to desktop compositing and overlapping windows - depends on your definition of 'visible'.

If you want it to happen right after it is activated (a bit after visible, the form is fully active for interactiveness, but this gets called each time it enters this state) - override Activate.

What exactly are you trying to do that can fall outside of all these?
I know you stated that you don't like it, but is there a particular reason? Just because someone said that it is hacky?
My opinion, but "even if it will need to re-wrote some VCL classes." sounds like more of a hack than overriding a procedure marked dynamic/virtual.
If you have a look at TCustomForm more closely then would understand that DoShow is called before ShowWindow.

Visible is when property Visible is set to true. It is done in method Show. I override it and it works perfectly for non Modal forms, the problem is with modal form.

I have enough experience to understand what is a good solution and what is going around. Many excellent components like DevExpress and Raize are written from scratch, I mean from TComponent etc. Do you know why they do it? Why not just inherite from TLabel to create a new nice looking label but they do all work from scratch. My guess is that VCL lacks something to expand it in convenient way.
ASKER CERTIFIED SOLUTION
Avatar of WaitingWonder2
WaitingWonder2

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes apologies I inspected it more and it does call showwindow so overriding DoShow would run too early.

CM_SHOWINGCHANGED?
Does it work? Because as you have found, a modal form does not need to go through ShowWindow.  Playing with Windows messages directly is the power of Delphi, but even the best can get it wrong.  I use DevExpress (you mentioned them), and see this bug.
http://www.devexpress.com/Support/Center/p/B137461.aspx

It may help you prevent some issues - it involves
   CM_SHOWINGCHANGED
+ modal dialog
+ postmessage (3rd party to component developer)
= unexpected outcome