A Single Instance Application Class


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

There are two new paragraphs

What's new in the latest version
Using the DDE to make your application open a document with a double-click on its icon


Making single-instance an application means enabling the application to recognize, at startup, if another running instance of itself exists so that, in this case, the application stops its execution. Generally, before quitting, the new instance retrieves the main window handle of the existing instance via the FindWindow() or FindWindowEx() function and uses this handle to bring the application window to foreground.
The problem can be solved in several ways. The most known solutions are:

  • Using a CMutex (a synchronization object global to the system).
  • Using shared data sections.

The small class described in this article, CSingleInstanceApp, uses the first method to implement the single-instance behaviour in a MFC application. It makes very simple to add the feature to a new project, eliminating the necessity of rewriting a consistent amount of code.

Comparison with other similar classes

In this section, I summarize the main features that distinguish my class from other similar classes you can find in this site. I hope this will help the reader to decide which code suits his needs better.

  • CSingleInstanceApp is an extension of CWinApp. This reduces the work needed to add the single-instance behaviour.
  • It uses a safe and stable method to build the class name, avoiding conflicts with other running applications.

Implementation details

For details about how to use a CMutex to implement the single-instance you can read the article "Single Instance of an application Class" by Kevin Lussier. In this article, I will discuss only the method I have used to build the window class name string. I assume that you know what a window class is and the reason why Windows requires the class registration before creating a window.
The key point to implement single-instance is that we need the registered class name to be the same in every instance of the application. Moreover, it is very important that two different applications don't use the same class name. The framework uses AfxRegisterWndClass() to register the window class but, unfortunately, this function registers a class name that is different in different instances of the same application (you can see it using the GetClassName() function). Thus, we cannot pass this string to FindWindow(). But what is the class name registered by AfxRegisterWndClass()?
To answer this question, once again, we have to browse in the MFC source code. We discover an interesting thing: AfxRegisterWndClass() generates a name for the class with the following code:

// generate a synthetic name for this class
HINSTANCE hInst = AfxGetInstanceHandle();
	if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
		wsprintf(lpszName, _T("Afx:%x:%x"), (UINT)hInst, nClassStyle);
		wsprintf(lpszName, _T("Afx:%x:%x:%x:%x:%x"), (UINT)hInst, nClassStyle,
		(UINT)hCursor, (UINT)hbrBackground, (UINT)hIcon);

Well, the idea behind the CSingleInstanceApp class is to mimic this way to generate the name string. hInst (the application instance handle), nClassStyle (the window class style), hCursor (the window cursor handle) and hbrBackground (the window background brush handle) are the same in every instance of the application. Only hIcon changes, so simply we cut it off from the class name string. Moreover, we have to make the class name application-dependent by adding to it the application name returned by the AfxGetAppName() function. This is exactly what the CheckSingleInstance() member function does. This is an excerpt from CheckSingleInstance():

if (hCursor == NULL && hbrBackground == NULL && hIcon == NULL)
	m_strClassName.Format(_T("%s:%x:%x"), lpstrAppName,
		(UINT)hInst, nClassStyle);
	m_strClassName.Format(_T("%s:%x:%x:%x:%x"), lpstrAppName,
		(UINT)hInst, nClassStyle, (UINT)hCursor, (UINT)hbrBackground);

How to use CSingleInstanceApp

Using this class requires the following steps:

  • Include the "CSingleInstanceApp.c" and ".h" in your project.
  • At the beginning of the application class header file #include "SingleInstanceApp.h". In the class declaration replace CWinApp with CSingleInstanceApp.
  • Add the following as the first line of the InitInstance() body of your application class:
if (!CheckSingleInstance(IDR_MAINFRAME))
	return FALSE;
  • Add the following as the first line of the PreCreateWindow() body of your frame window class:
cs.lpszClass = ((CMyApp*)AfxGetApp())->GetClassName();

Operations for CSingleInstanceApp

BOOL CheckSingleInstance(UINT nID);
CString GetClassName() const;

What's new in the latest version

The previous version of the class contained a bug: the main window produced an horrible flickering when trying to move or resize it. This is due to the fact that the window class style used the CS_HREDRAW and the CS_VREDRAW styles. Moreover, the background brush handle must be NULL, since for the mainframes, the background is automatically painted.

Using the DDE to make your application open a document with a double-click on its icon

Lots of persons noted that the application can't open another document besides the first by double-clicking its icon. This is not due to a CSingleInstanceApp bug.

Briefly, the DDE (Dynamic Data Exchange can be defined as a protocol to implement a simple form of inter-process communication). The MFC application is perfectly capable to recognize and handle the DDE command to open a document.
This feature is enabled in the InitInstance() body of your application class with the line


However, to enable this characteristic, you need to register the document type "manually" (unfortunately, the framework doesn't do it). You can do this from any explorer window, by selecting "Folder options" from the "View" menu. Go to the "File types" section and select your document type. Now press the "Edit..." button. When the modify dialog appears press the new "Edit..." button. Select the "Use DDE" checkbox. In the "DDE Message" edit box write the following string:


Now, disable the following line in the InitInstance() body of your application.

RegisterShellFileTypes()	// Disable this line to receive DDE messages

Now your application is able to open documents with a double click even while it's running.

Author's note

I'm continuously working to improve this class. I'll be grateful to you if you mail me your comments, advice, or bug apparition reports!

Download Demo and Source Code

Updated: May, 27 1998


  • Dialog based apps still don't work!

    Posted by Legacy on 03/15/2001 08:00am

    Originally posted by: Richard Parsell

    I've tried the methods noted in the examples and they work
    fine for apps with standard windows. The comment about a fix for dialog based apps does work, but in my case I can't depend on having the dialog title to get the handle.
    I want to use the class name to pop up the dialog.

    If anyone has a solution please let me know!

  • Minor fix if it's not drawing the window

    Posted by Legacy on 02/09/2000 08:00am

    Originally posted by: Otto

    I tried this one, and it worked, except that the main frame wasn't being filled in. This is using Visual C++ 5.0 (Dev Studio 97).

    The key was to change this:
    wndclass.hbrBackground = NULL;

    to this:
    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

    If you leave it NULL, the background will be not be drawn at all, at least not with my app, and you get nasty undrawn leftover stuff when the window is moved or resized. Also, when the window is first created, it looks transparent.

  • Thanks!

    Posted by Legacy on 01/20/2000 08:00am

    Originally posted by: Martin Sawyer

    Thanks for helping me solve this problem.
    Your code worked flawlessly. Good job

  • Resource Leak in destructor?

    Posted by Legacy on 10/02/1998 07:00am

    Originally posted by: Victor Vogelpoel

    [Credits to BoundsChecker]
    I'm not sure if it's necessary, but you may have to call CloseHandle on m_hMutex AFTER the mutex was released in the destructor. BC complains about a system object not being released...

    // Release the mutex
    if ( m_hMutex != NULL ) {
    ReleaseMutex( m_hMutex );

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date