Limiting a dialog-based application to a single instance

Running only one instance of an SDI/MDI application is easy. You only have to follow the examples, but doing this in a dialog-based application is something else.

For some reason, you can't use the PreCreateWindow of a dialog box, so you can't change the class name to your desired class name, in order to use it with conjunction with the AfxRegisterClass function in the InitInstance of your derived CWinApp class.

What you have to do is a little trickey:

After checking with SPY++, I found out that the class name of the dialog box application is "#32770". Now, in order to try to find previous instances, you use FindWindow( LPCTSTR lpszClassName, LPCTSTR lpszWindowName ). In the MDI/SDI application example, the lpszWindowName is set to NULL, because you have the class name and that is enough. However, in a dialog-based application, you must also use the Window title. The title is set up in the InitDialog function with the command SetWindowText. When you write your FirstInstance function in the CWinApp class (like in the known examples), you write something like this: FindWindow ("#32770", "My application "); Yes, I wrote "My application " with a space in the end on purpose, since this is the name that you write in the SetWindowText in your InitDialog function.

In order to undrstand this better, just download the example. It was tested successfully with MSVC 6.0, Win 98.

If it does to you any problems with other MSVC versions/operating systems, please let me know.

Download demo project - 29 KB

Date Last Updated: February 3, 1999



Comments

  • Using psapi

    Posted by Legacy on 08/30/2001 12:00am

    Originally posted by: Alex Kulish

    To be sure looking for instances I test running module file name. It works but needs psapi.dll. I combined it in my own dll and use smthg like CompareWindows(hwnd1, hwnd2) == true if both windows belong to the same application. Mail me if you need a source

    Reply
  • FindWindow( ) can be dangerous

    Posted by Legacy on 07/04/2001 12:00am

    Originally posted by: Jeff

    Dangerous. FindWindow may or may not return. See http://www.pgh.net/~newcomer/nomultiples.htm

    Reply
  • there is a very much simpler way

    Posted by Legacy on 08/18/1999 12:00am

    Originally posted by: Stefan Soltsien

    first you have to add a member variable to your application object:
    
    HANDLE m_hMutex;

    initialize it in the constructor with NULL

    deinitialize it in the destructor:
    if(m_hMutex)
    ::CloseHandle(m_hMutex);


    then you have to create a named mutex i.e. in the
    WinMain Function or in the InitInstance-Method of your
    Application object.
    m_hMutex = ::CreateMutex(NULL, FALSE, "SomeUniqueName");
    if( m_hMutex != NULL )
    { // indicates running instance
    if(::GetLastError()==ERROR_ALREADY_EXISTS)
    return FALSE; // forbid further processing
    }

    The trick is that GetLastError returns a value that determines whether the Mutex already exists. Since it is
    a named mutex, the second instance of a program is connected to the existing mutex.
    The advantage of the "Mutex-Method" compared to FindWindow or other methods is that it detects a running instance BEFORE any window object is created.

    cheers stefan

    Reply
  • Look at here!

    Posted by Legacy on 08/18/1999 12:00am

    Originally posted by: Haining Geng


    I had the problem before.

    Go to MSJ:

    http://www.microsoft.com/msj/backissuestop.htm

    and look at October 1997 issue, C++ Q & A, the answer is clear.

    Reply
  • One_line_of_code

    Posted by Legacy on 04/10/1999 12:00am

    Originally posted by: David_Shepherd

    Pardon_the_underscores,_but_for_some_reason,_I_cannot_enter_spaces!!_:-(

    Anyway,_consider_the_following_(Since_this_IS_an_MFC_forum):

    if_(_m_hPrevInstance_!=NULL_)
    {
    ____//That's_it!!!
    }

    -David

    • The m_hPrevInstance parameter is a holdover from Win16. It is no longer in use, ... Mutex is a safe way to do it. m_hPrevInstance is no longer valid. ...

      Posted by jauming on 11/06/2007 09:23pm

      The m_hPrevInstance parameter is a holdover from Win16. It is no longer in use, ... Mutex is a safe way to do it. m_hPrevInstance is no longer valid. ...
      www.eggheadcafe.com/forumarchives/vcmfc/Jan2006/post25364503.asp - 23k -

      Reply
    Reply
  • The best way to limit a dialog app to one instance!

    Posted by Legacy on 04/09/1999 12:00am

    Originally posted by: High Plains Software

    Here's the best way to find a dialog-based app:
    
    

    Step 1: Insert the following in the InitApplication() method of your dialog:

    WNDCLASS wc;

    wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
    wc.lpfnWndProc = DefDlgProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = DLGWINDOWEXTRA;
    wc.hInstance = AfxGetInstanceHandle();
    wc.hIcon = LoadIcon(IDR_MAINFRAME);
    wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW + 1;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "MyClassName"; // replace this with your unique class name
    ::RegisterClass(&wc);

    Step 2: Insert the following at the beginning of the InitInstance() method:

    HWND hwnd = ::FindWindow("MyClassName", NULL);
    if (hwnd)
    {
    ::ShowWindow(hwnd, SW_SHOWNORMAL);
    ::BringWindowToTop(hwnd);
    ::SetForegroundWindow(hwnd);
    return FALSE;
    }

    Step 3: Edit the .rc file (in Visual Studio, File | Open | Open as Text).
    Insert the following CLASS statement in the app's dialog template:

    IDD_MY_DIALOG DIALOGEX 0, 0, 292, 167
    CLASS "MyClassName"

    That's it! You can now find your app regardless of the window's title.

    Reply
  • Even better, activate the current instance...

    Posted by Legacy on 03/03/1999 12:00am

    Originally posted by: Jon Rizzo

    In BOOL CDialogApp::InitInstance() 
    
    

    HWND hWnd = ::FindWindow(NULL,"title Of your App");
    if (hWnd)
    {
    ::ShowWindow(hWnd, SW_SHOWDEFAULT);
    ::BringWindowToTop(hWnd);
    ::SetForegroundWindow(hWnd);
    return FALSE;
    }

    Reply
  • Another way...

    Posted by Legacy on 02/28/1999 12:00am

    Originally posted by: ljp

    In BOOL CDialogApp::InitInstance()

    HWND hWnd = ::FindWindow(NULL,"title Of your App");
    if (hWnd)
    {
    return FALSE;
    }

    Reply
  • Not allowing multiple instances of a dialog app...

    Posted by Legacy on 02/10/1999 12:00am

    Originally posted by: Chris Conn

    I'd have to agree with Gunner on this one. The mutex method allows you to change the title of the application's main window without affecting whether an instance is running. I've actually done this using a primarily CPropertySheet based application, which can have up to four different property sheets displayed depending on command line switches. In the future, I also expect to allow only "n" number of instances of the application running.

    Reply
  • A simpler way would be to use a global Mutex.

    Posted by Legacy on 02/03/1999 12:00am

    Originally posted by: Gunnar Roth


    It works with every kind of application.
    Example:

    In InitInstance you add this code

    CreateMutex(NULL,TRUE,_T("My Super Program Mutex")); // mutex will be automatically deleted when process ends.
    BOOL bAlreadyRunning = (GetLastError() == ERROR_ALREADY_EXISTS);
    if(bAlreadyRunning)
    return FALSE;

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Best-in-Class organizations execute on a strategy that supports the multi-channel nature of customer requests. These leading organizations do not just open up their service infrastructures to accommodate new channels, but also empower their teams to deliver an effective and consistent experience regardless of the channel selected by the customer. This document will highlight the key business capabilities that support a Best-in-Class customer engagement strategy.

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds