Create a Single Instance Application
Site Map Feedback
Up Controls Files Moving Data
You can't make the "Control Panel" appear twice at the same time like most dialog boxes...
If you want to limit your Application to be Single Instance there are several approaches and, as usual, the one with the least code has been chosen here.
To just stop extra instances all you need is this struct in your application's InitInstance():
BOOL CMyApp::InitInstance() {
  CreateMutex(0, FALSE, "MyApp-SingleInstance");
  if(GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) return FALSE;
  ...
All you need to know about CreateMutex is that Windows will only let one instance of your Application create a Mutex of a given name.
The system closes the Mutex automatically when your Application terminates.
The call fails with ERROR_ACCESS_DENIED if the Mutex was created by another Instance because no SECURITY_ATTRIBUTES were given.
So that's enough to stop other instances being created - but if you try to run two instances of Control Panel, the first instance becomes Active...
To do this code must be added to get the second instance to search for the first instance and activate its Main Window.
The newer Instance has to search and find the older Instance - and the older Instance to tell us its Main Window's Handle to activate it.
This involves more bits of code...
To start with a Unique Identifier for the Application is needed. So in your Application's Header File put the following Global number and the code for the search which is encapsulated in a structure: (Incedentally, RU12 is short for "Are You One Too" which is what Searcher is asking all existing Windows).
const UINT UWM_RU12=RegisterWindowMessage("MyApp-SingleInstance-UWM_RU12");
struct SingleInstance {
  SingleInstance() {
    CreateMutex(0, FALSE, "MyApp-SingleInstance");
//The system closes the handle automatically when the process terminates
//The call fails with ERROR_ACCESS_DENIED if the Mutex was created by another Instance because no SECURITY_ATTRIBUTES were given
  if(GetLastError()==ERROR_ALREADY_EXISTS || GetLastError()==ERROR_ACCESS_DENIED) {
      HWND hOther=0;
      EnumWindows(Searcher, (LPARAM)&hOther);
      if(hOther) { // Try to activate the older Instance
        SetForegroundWindow(hOther);
        ShowWindow(hOther, IsZoomed(hOther) ? SW_MAXIMIZE : SW_RESTORE); // Needed for windows that have been maximized, then minimized, then hidden.
      }
      exit(0); // Terminates this Instance
  } }
  static BOOL CALLBACK Searcher(HWND hWnd, LPARAM lParam) {
    DWORD Result;
    if(!SendMessageTimeout(hWnd, UWM_RU12, 0,0,  SMTO_BLOCK | SMTO_ABORTIFHUNG, 500, &Result)
    || Result!=UWM_RU12) return TRUE; // Continue searching
    *((HWND*)lParam)=hWnd;            // Found it!
    return FALSE;                     // Stop searching
  }
};

class CMyApp : public CWinApp {
...
In your Application's .cpp file all you need to do is create an instance of this structure before your CWinApp instance.
So, in the line above CMyApp theApp insert SingleInstance Instance;...
SingleInstance Instance;
CMyApp theApp;
Now just make the older Instance reply to our Searcher Message (UWM_RU12) and tell us its Main Window's Handle so it can be activated...
The "Main Window" will be CMainFrm in Document/View Applications, or the "main Dialog class" (created by your CMyApp class) in Dialog Applications.
In the Main Window's Header File, find the DECLARE_MESSAGE_MAP() line and immediately above insert the RU12 line:
  //}}AFX_MSG_MAP
  afx_msg LRESULT RU12(WPARAM, LPARAM) {return UWM_RU12;}
  DECLARE_MESSAGE_MAP()
And in the Main Window's .cpp File, find the END_MESSAGE_MAP() line and immediately above insert the RU12 line:
  //}}AFX_MSG_MAP
  ON_REGISTERED_MESSAGE(UWM_RU12, RU12)
END_MESSAGE_MAP()
You can test what you have done as follows:
  1. Compile a Debug version
  2. Use Windows Explorer to find and run your Debug Excecutable (leave it running)
  3. Use DevStudio to try to run another instance....
If you put breakpoints on the constructor for CMyApp and SingleInstance, it should get to the constructor for SingleInstance first, find and activate the other Instance, then exit without ever getting to the constructor for CMyApp.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


 (1654) Last modified: Fri, 15 May 2009 15:27:04 +0100