I don’t have any ProcessMessages in there!  Actually the Program does a very 
ordered and stable startup, and has to run in sequence so moving the 
calculations to  thread won’t actually gain me anything other than having it 
responsive to Minimise/maximise.  That may be enough reason to do it if is an 
issue.

Aside – the SW_SHOWNOACTIVE had another oddity to it – the Program B started 
fine, Program A kept focus, but the window for Program B came up in front of 
Program A which is just a nuisance.   I guess its related in part to the the 
occasional bugs in Z order that MS never have sorted, where a new form (even 
modal) will appear sometimes behind the launching form.  Still there Windows 
7/8.

From: Jolyon Smith 
Sent: Friday, July 25, 2014 1:19 PM
To: NZ Borland Developers Group - Delphi List 
Subject: Re: [DUG] Shellexecute question

It shouldn't be puzzling.  It is not the fact that the form is starting 
minimized, but the fact that Application.Run varies it's behaviour for the 
SW_SHOWMINNOACTIVE value CmdShow, a variation which does not occur for 
SW_MINIMIZED.


But NOOOOOoooooo - do NOT add calls to ProcessMessages().  Do not add ANY calls 
to ProcessMessages().  And remove any you already have !!! :)

ProcessMessages() calls make your application UI code re-entrant in highly 
unpredictable ways that can have you forever trying to find Heisenbugs, 
especially in a case like this where a user is likely to click on your launched 
app icon to see if it has "woken up" yet.

Do blocking work on a background thread, allow the UI to continue to respond on 
the main thread, and provide whatever feedback to the UI relating to the 
progress of the background thread via properly marshalled, thread safe 
mechanisms.


You will get more sleep that way.  :)





On 25 July 2014 12:43, John Bird <[email protected]> wrote:

  It looks like the code in D2007 Application.Run is the later one.   I would 
like to solve this at some stage out of curiosity so will return.   The 
SW_SHOWMINIMIZED works as expected which is a puzzle.  Usual story however, 
this is not on the list of urgent things to get working so it has to be put 
aside for now.   

  Its a good point you make about where to put startup code – my rule of thumb 
has generally been initialising non component stuff can be done in the form 
create, but I tend to put anything initialising component stuff on the form 
show event, and this is where much of it is – there is a bit of setting things 
visible or not depending on what properties are set and I don’t think this can 
generally be done before the Show event.   This Program B does this general 
initialisation and then starts a timer which then fires of the rest of the 
startup code which is long running.   Some of the long running code takes 20-40 
seconds to run (calculations) and it doesn’t respond to minimising/maximising 
while that is happening which is another minor issue – I may need to put some 
extra processmessages calls in there eventually.

  This relates to a previous question – the long running calculation sets up 
some quite large arrays and I tried saving/reading them in from disk to bypass 
the calculations but it produced a stack overflow. I am presuming that this is 
not from the code, as Russell’s code to save and load arrays to disk ran 
standalone, but due to the program using a larger amount of memory.  Another 
investigation for later on the list of priorities!
  From: Jolyon Smith 
  Sent: Friday, July 25, 2014 7:49 AM
  To: NZ Borland Developers Group - Delphi List 
  Subject: Re: [DUG] Shellexecute question

  If the other Delphi application isn't correctly responding to 
SW_SHOWMINNOACTIVE then the problem is in the TApplicaiton code of the version 
of Delphi involved.  The fact that your FormShow event isn't firing suggests 
that it's an older version of Delphi involved, since an inspection of the 
TApplication.Run method reveals how this behaviour (or lack of) would 
eventuate.... 


        case CmdShow of
          SW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;
          SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;
        end;
        if FShowMainForm then
          if FMainForm.FWindowState = wsMinimized then
            Minimize else
            FMainForm.Visible := True;

  The internal state is forced to wsMinimize, bypassing normal property 
setters, resulting in the "show" code simply calling the Minimize method on the 
main form, rather than making the form visible, which is why the FormShow even 
isn't fired.  The form isn't shown!  i.e. the FormShow event will eventually 
fire only when the user first activates the application and the window becomes 
shown.  You could argue that this is desirable behaviour, but doesn't suit your 
purposes in this case.

  This was changed in later versions of Delphi.  The above code is from D7.  
The version below from XE4 (the only 2 versions I have available on this 
system):

        case CmdShow of
          SW_SHOWMINNOACTIVE:
            begin
              FInitialMainFormState := wsMinimized;
              FMainForm.FWindowState := wsMinimized;
            end;
          SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;
        end;
        if FShowMainForm then
          if (FMainForm.FWindowState = wsMinimized) or (FInitialMainFormState = 
wsMinimized) then
          begin
            Minimize;
            if (FInitialMainFormState = wsMinimized) then
              FMainForm.Show;
          end else
            FMainForm.Visible := True;

  Now it appears that the Show method of your main form should be called, 
though I haven't tested to see whether this is actually the case.  But in 
theory, SW_SHOWMINNOACTIVE should work for you if you upgrade the target EXE to 
a more current version of Delphi.

  Alternatively, you could move the initialisation code in that EXE, currently 
triggered by the FormShow event, to a more appropriate initialisation event.  
After all, this is initialisation that needs to be performed regardless of 
whether the form is Show'n or not.  ;)

  It's possible that some of that code cannot be performed in FormCreate, which 
is a quite common reason to use FormShow instead.  If that's the case, then one 
possible solution is to post a custom message to yourself in FormCreate, to 
fabricate the create-deferred event you need, without relying on the form being 
shown to generate the FormShow event:


  const
     MM_INITIALISE = WM_USER + 1;


  TMyForm = class(TForm)
    ...
    procedure MMInitialise(var aMessage: TMessage); message MM_INITIALISE;
  end;


  TMyForm.FormOnCreate...

  begin
     PostMessage(Handle, MM_INITIALISE, 0, 0);
     ....
  end;


  procedure TMyForm.MMInitialise(var aMessage: TMessage); 
  begin
    // Do initialisation here...
  end;



  Good luck



  On 25 July 2014 00:22, John Bird <[email protected]> wrote:

    Hey that should have been perfect, as I already was doing SW_SHOWMINIMIZED 
which works fine, and so does SW_SHOWNOACTIVE  which also does what it should – 
start the other window but not change focus.

    However SW_SHOWMINNOACTIVE doesn’t work.   Now the other program is a 
Delphi program of mine that does some initialisation in the Formshow event 
(turning on timers etc) and I am wondering if somehow the event doesn’t fire.  
The process starts, but nothing runs, looks asleep in Task Manager. Not worth 
messing around with, as its a minor issue.

    I toyed with using SW_SHOWINACTIVE and getting the program (Program B) to 
minimise itself on start, but that is just damned complicated and 
fiddly/fragile.  It also seems prone to ending up with 2 icons on the task bar, 
as though multiple copies have started even if only one is running – (maybe due 
to the large amount of work it does on startup – it is unresponsive for a good 
while) .

    I also tried Russells suggestion about setting the foreground window and it 
don’t work for me (Windows 8.1)

    What I did in the end was go back to the SW_SHOWMINIMIZED and then after 
the ShellExecute (in Program A) I put a ShowMessage saying I had started the 
other program.   Because this gives a modal clue that they have to click on to 
continue it will do the job of setting the focus back.  And its a bit useful 
for them to be informed it has been started.


    From: Jolyon Smith 
    Sent: Thursday, July 24, 2014 8:21 PM
    To: Russell Belding ; NZ Borland Developers Group - Delphi List 
    Subject: Re: [DUG] Shellexecute question

    Have you tried passing SW_SHOWMINNOACTIVE instead of SW_MINIMIZED ? 


    Caveat:  The show flag parameter is merely passed to the application being 
executed.  What it chooses to do with that flag is it's own affair, but if 
you're lucky, it will respect your wishes.  If not, then you will have to 
engage in a focus window arms race/lotto as already suggested.  But Route #1 
would be to try the officially mandated mechanisms.

    Good luck.  :)



    On 24 July 2014 19:46, russell <[email protected]> wrote:

      Tyr this after spawning the other program.



      SetForegroundWindow(forms.application.mainWindow.handle)



      To give the main window of your program focus.

      Perhaps modifications of this will take you to the window of the calling 
program where you want the focus?



      Russell



      From: [email protected] 
[mailto:[email protected]] On Behalf Of John Bird
      Sent: Thursday, 24 July 2014 4:43 p.m.
      To: NZ Borland Developers Group - Delphi List
      Subject: [DUG] Shellexecute question



      I have a program (Program A) that fires up another (program B)  via 
ShellExecute, if its not already running.  However even though Program B is 
started minimised, focus shifts away from Program A, which is a minor nuisance.



      Is there any way to stop this within Delphi?  Or will I have to do 
something like delve into the Windows API?



      if ShellExecute(Application.Mainform.Handle, 'open', Pchar(aProgName), 
PChar(aparaml), PChar(aDir), SW_SHOWMINIMIZED) <= 32 then

        ShowMessage('Start Minimised error:')




      _______________________________________________
      NZ Borland Developers Group - Delphi mailing list
      Post: [email protected]
      Admin: http://delphi.org.nz/mailman/listinfo/delphi
      Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe



----------------------------------------------------------------------------

    _______________________________________________
    NZ Borland Developers Group - Delphi mailing list
    Post: [email protected]
    Admin: http://delphi.org.nz/mailman/listinfo/delphi
    Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe

    _______________________________________________
    NZ Borland Developers Group - Delphi mailing list
    Post: [email protected]
    Admin: http://delphi.org.nz/mailman/listinfo/delphi
    Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe



------------------------------------------------------------------------------
  _______________________________________________
  NZ Borland Developers Group - Delphi mailing list
  Post: [email protected]
  Admin: http://delphi.org.nz/mailman/listinfo/delphi
  Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe 

  _______________________________________________
  NZ Borland Developers Group - Delphi mailing list
  Post: [email protected]
  Admin: http://delphi.org.nz/mailman/listinfo/delphi
  Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe




--------------------------------------------------------------------------------
_______________________________________________
NZ Borland Developers Group - Delphi mailing list
Post: [email protected]
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe
_______________________________________________
NZ Borland Developers Group - Delphi mailing list
Post: [email protected]
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to [email protected] with 
Subject: unsubscribe

Reply via email to