Board index » cppbuilder » Avoiding multiple programinstances and restore the firstone

Avoiding multiple programinstances and restore the firstone


2005-04-22 07:17:30 PM
cppbuilder76
If you want to avoid multiple programinstances and/or restore
the firstone then you can use code below.
The use of a mutex and after that searching for windows
would be doing twice nearly the same.
Just add some code to WinMain.
For SubZero and PaoloItaly.
Hans.
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
// -------------------------------------
AnsiString OldTitle = Application->Title;
Application->Title = "";
HWND hwnddesktop = GetDesktopWindow();
HWND hwnd = FindWindowEx(hwnddesktop, 0, 0, 0);
while( hwnd )
{
char titlebuffer[250];
GetWindowText(hwnd, titlebuffer, sizeof(titlebuffer));
if ( OldTitle == AnsiString ( titlebuffer ) )
{
ShowMessage ( "this is not the first instance ("
+ AnsiString ( titlebuffer )
+ ") you will get the first one." );
::SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
::SetForegroundWindow( hwnd );
return 1;
}
hwnd = FindWindowEx(hwnddesktop, hwnd, 0, 0);
}
Application->Title = OldTitle;
// -----------------------------------
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
 
 

Re:Avoiding multiple programinstances and restore the firstone

Hi Hans,
Quote
If you want to avoid multiple programinstances and/or restore
the firstone then you can use code below.
What the word firstone means? Really (not a joke), it's not in my
dictionary...
Quote
The use of a mutex and after that searching for windows
would be doing twice nearly the same.
Yes. I use this, but not sure if that's the best way:
bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )
{
::CreateMutex( NULL, NULL, MUTEX.c_str() );
if ( GetLastError() )
{
Application->Title = "Something different";
HWND FirstWnd;
FirstWnd = ::FindWindow( "TApplication", NAME.c_str() );
if ( ::IsIconic( FirstWnd ) ) ::ShowWindow( FirstWnd,
SW_SHOWDEFAULT );
::SetForegroundWindow( FirstWnd );
return ( false );
}
return ( true );
}
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
if ( ! StartNewInstance( "program", "notprogram" ) )
return 0;
// etc...
--
Best regards,
Vladimir Stefanovic
 

Re:Avoiding multiple programinstances and restore the firstone

Vladimir Stefanovic wrote:
Quote
What the word firstone means? Really (not a joke), it's not in my
dictionary...
Maybe it is not a word (English is not my native language either,
so please correct me).
I meant 'the first'.
Example:
Q: About which instance are you speaking ?
Possible answers:
A: The one which started first.
A: The first one.
A: The firstone.
A: The first.
Quote
>The use of a mutex and after that searching for windows
>would be doing twice nearly the same.

Yes. I use this, but not sure if that's the best way:

bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )
You did not set back the original Title. That is needed
in case it is the first instance.
What I meant was that you can omit the mutex: (untested)
bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )
{
AnsiString OldTitle = Application->Title;
Application->Title = "Something different";
HWND FirstWnd;
FirstWnd = ::FindWindow( "TApplication", NAME.c_str() );
// TApplication ???
if ( FirstWnd )
{
if ( ::IsIconic( FirstWnd ) ) ::ShowWindow( FirstWnd,
SW_SHOWDEFAULT );
::SetForegroundWindow( FirstWnd );
Application->Title = OldTitle;
return ( false );
}
Application->Title = OldTitle;
return ( true );
}
But my code comes in handy when the Title is not know.
And it does not require changing of stringcontents for
different projects.
Hans.
 

{smallsort}

Re:Avoiding multiple programinstances and restore the firstone

Hans Galema wrote:
Quote
if ( OldTitle == AnsiString ( titlebuffer ) )
{
ShowMessage ( "this is not the first instance ("
+ AnsiString ( titlebuffer )
+ ") you will get the first one." );

::SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
Might want to make that a PostMessage, or at least SendMessageTimeout
What happens here if the original app is closing, or is closed while
ShowMessage is up?
Quote
::SetForegroundWindow( hwnd );
 

Re:Avoiding multiple programinstances and restore the firstone

Bob Gonder wrote:
Quote
What happens here if the original app is closing, or is closed while
ShowMessage is up?
It would not close itself I think. And if it is closed while the
mesage is up then the user would have done that while the
message is up. If he want to do that: be it.
Hans.
 

Re:Avoiding multiple programinstances and restore the firstone

Quote
I meant 'the first'.

Example:
Q: About which instance are you speaking ?
Possible answers:
A: The one which started first.
A: The first one.
A: The firstone.
A: The first.
He, he - I overlooked that, and that was easy to understand: first-one.
Somehow I imagined that it was something with: fir(e)stone - fire stone.
Also thank's for the code comments.
--
Best regards,
Vladimir Stefanovic
Quote

>>The use of a mutex and after that searching for windows
>>would be doing twice nearly the same.
>
>Yes. I use this, but not sure if that's the best way:
>
>bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )

You did not set back the original Title. That is needed
in case it is the first instance.

What I meant was that you can omit the mutex: (untested)

bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )
{
AnsiString OldTitle = Application->Title;

Application->Title = "Something different";
HWND FirstWnd;
FirstWnd = ::FindWindow( "TApplication", NAME.c_str() );
// TApplication ???

if ( FirstWnd )
{
if ( ::IsIconic( FirstWnd ) ) ::ShowWindow( FirstWnd,
SW_SHOWDEFAULT );
::SetForegroundWindow( FirstWnd );
Application->Title = OldTitle;

return ( false );
}

Application->Title = OldTitle;

return ( true );
}

But my code comes in handy when the Title is not know.
And it does not require changing of stringcontents for
different projects.


Hans.
 

Re:Avoiding multiple programinstances and restore the firstone

Hans Galema wrote:
Quote
What I meant was that you can omit the mutex: (untested)
Now tested. This works ok and has less code and is much faster
as my original post.
Quote
bool StartNewInstance( AnsiString NAME, AnsiString MUTEX )
{
AnsiString OldTitle = Application->Title;

Application->Title = "Something different";
HWND FirstWnd;
FirstWnd = ::FindWindow( "TApplication", NAME.c_str() );
// TApplication ???
Yes: TApplication. You could provide a NULL too.
Quote

if ( FirstWnd )
{
if ( ::IsIconic( FirstWnd ) ) ::ShowWindow( FirstWnd,
SW_SHOWDEFAULT );
::SetForegroundWindow( FirstWnd );

Application->Title = OldTitle;

return ( false );
}

Application->Title = OldTitle;

return ( true );
}
Hans.
 

Re:Avoiding multiple programinstances and restore the firstone

Hans Galema < XXXX@XXXXX.COM >wrote:
Quote

[...]
::SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
::SetForegroundWindow( hwnd );
This code is problematic if the window is not minimized
because it will disable the Minimize border icon. Ultimately,
the problem is with Windows incorrectly recording the window
state (unless you apply WS_EX_APPWINDOW to the window's
ExStyle but then you get 2 icons on the task bar) so testing
if it's minimized is useless.
The only solution is to manually track the window state and
have the second instance send the first instance a custom
message so that the first instance can decide what to do.
This component does exactly that:
newsgroups.borland.com/cgi-bin/dnewsweb&utag=
~ JD
 

Re:Avoiding multiple programinstances and restore the firstone

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
Quote

[...]
if ( ::IsIconic( FirstWnd ) )
This code is unreliable. See my other post in this thread.
~ JD
 

Re:Avoiding multiple programinstances and restore the firstone

JD wrote:
Quote
>::SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
>::SetForegroundWindow( hwnd );

This code is problematic if the window is not minimized
because it will disable the Minimize border icon.
That does not happen here. Bcb5 on XP.
Hans.
 

Re:Avoiding multiple programinstances and restore the firstone

Quote
>if ( ::IsIconic( FirstWnd ) )

This code is unreliable. See my other post in this thread.
Yes, I have experienced that :)
--
Best regards,
Vladimir Stefanovic
 

Re:Avoiding multiple programinstances and restore the firstone

JD,
Can you please send me the explanation of the problem when
Windows reports wrong about Minimized/Maximized state.
I saw that text commented in the code of yours (I think).
--
Best regards,
Vladimir Stefanovic
"JD" < XXXX@XXXXX.COM >wrote in message
Quote

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
>
>[...]
>if ( ::IsIconic( FirstWnd ) )

This code is unreliable. See my other post in this thread.

~ JD

 

Re:Avoiding multiple programinstances and restore the firstone

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
Quote

Can you please send me the explanation of the problem when
Windows reports wrong about Minimized/Maximized state.
Be it a bug or be it by design, Windows incorrectly records
the window state but it happens only if the windows ExStyle
does *not* include WS_EX_APPWINDOW and then only if the window
is minimized.
Since the VCL updates it's state directly from Windows, it's
no use trying to get the correct state from else where. You
need to keep track of it yourself.
~ JD
 

Re:Avoiding multiple programinstances and restore the firstone

Thanks!
Have you succeded to catch Win+D (Minimize all windows) ?
--
Best regards,
Vladimir Stefanovic
"JD" < XXXX@XXXXX.COM >wrote in message
Quote

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
>
>Can you please send me the explanation of the problem when
>Windows reports wrong about Minimized/Maximized state.

Be it a bug or be it by design, Windows incorrectly records
the window state but it happens only if the windows ExStyle
does *not* include WS_EX_APPWINDOW and then only if the window
is minimized.

Since the VCL updates it's state directly from Windows, it's
no use trying to get the correct state from else where. You
need to keep track of it yourself.

~ JD

 

Re:Avoiding multiple programinstances and restore the firstone

Hans Galema < XXXX@XXXXX.COM >wrote:
Quote
JD wrote:

>>::SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
>>::SetForegroundWindow( hwnd );
>
>This code is problematic if the window is not minimized
>because it will disable the Minimize border icon.

That does not happen here. Bcb5 on XP.
I recalled that it would disable biMinimize but reading my
comments in the code tells me that that may not be the exact
problem.
I can tell you for certain that it's not an issue with the VCL
(Gambit helped me track that down) and that it is in fact a
problem with Windows. Since I developed it on an XP machine,
I would suggest that you assume that I was inaccurate with my
description of the problem and take another look, being sure
to leave the first instance restored and testing outside of
the IDE.
~ JD