[DUG] Shellexecute question
Jolyon Smith
jsmith at deltics.co.nz
Fri Jul 25 07:49:33 NZST 2014
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 <johnkbird at paradise.net.nz> 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 <jsmith at deltics.co.nz>
> *Sent:* Thursday, July 24, 2014 8:21 PM
> *To:* Russell Belding <russell at belding.co.nz> ; NZ Borland Developers
> Group - Delphi List <delphi at listserver.123.net.nz>
> *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 <russell at belding.co.nz> 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:* delphi-bounces at listserver.123.net.nz [mailto:
>> delphi-bounces at listserver.123.net.nz] *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: delphi at listserver.123.net.nz
>> Admin: http://delphi.org.nz/mailman/listinfo/delphi
>> Unsubscribe: send an email to delphi-request at listserver.123.net.nz with
>> Subject: unsubscribe
>>
>
>
> ------------------------------
> _______________________________________________
> NZ Borland Developers Group - Delphi mailing list
> Post: delphi at listserver.123.net.nz
> Admin: http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email to delphi-request at listserver.123.net.nz with
> Subject: unsubscribe
>
>
> _______________________________________________
> NZ Borland Developers Group - Delphi mailing list
> Post: delphi at listserver.123.net.nz
> Admin: http://delphi.org.nz/mailman/listinfo/delphi
> Unsubscribe: send an email to delphi-request at listserver.123.net.nz with
> Subject: unsubscribe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://listserver.123.net.nz/pipermail/delphi/attachments/20140725/18e2fada/attachment-0001.html
More information about the Delphi
mailing list