delphi

Message lost because of TStyleManager.TrySetStyle


I created a replacement to the TApplication object.

Among other features (to-memory and to-GUI logging, save GUI state to disk, singleton instance, user/application path-related utilities, etc), it implements a place where the GUI can be PROPERLY initialized (no more abusing of OnFormCreate!) via a posted window message using PostMessage(MForm.Handle, MSG_LateFormInit) that the application sends to the main form.

However, I discovered a problem: if I call TrySetStyle() before I make the main form visible, my message is lost.

This is because TrySetStyle() internally recreates the form, which affects the messaging loop (MSG_LateFormInit message is lost or not dispatched as expected).

The DPR looks like this:

program Stuff;  
begin
  AppData:= TAppData.Create('My App Name');
  AppData.CreateMainForm(TMainForm, MainForm, False {Not visible});  // This calls PostMessage

  // Warning:
  // Don't call TrySetStyle until the main form is visible. 
  // Solution: Make the main form visible before you call TrySetStyle!
  TStyleManager.TrySetStyle('Amakrits');

  Application.Run;
end.

Conundrum:

  1. I don't want to move the POST code after TrySetStyle(). I don't want to force the user to call more code than necessary in his main form/DPR, because it is easy to forget to do it. Until now, all the code is self-contained (well... there is the method in the form that intercepts the MSG_LateFormInit message, but that's optional).
    All the changes are done in the DPR. I want to keep it like this.

  2. On the other hand, I do want to call TrySetStyle() while the form is still invisible to prevent the flicker.

PS: I don't know if the user will call TrySetStyle() or not. This is optional for him.

So, I need to find a reliable way to POST and receive the MSG_LateFormInit signal, preferably while the main form is still invisible.


Solution

  • One option would be to post the MSG_LateFormInit message to your TAppData's hidden window first, where the desired Form object is in the message's LParam field, and then you can give TAppData a message handler that sends the MSG_LateFormInit message to the specified Form if it is still alive.

    This way, you are no longer affected by the Form's HWND changing between the time the message is posted and the time the message is dispatched. the TAppData's window should be persistent and never recreated.