Limiting an application to a single instance is very problematic. There are dozens of solutions available; most of them work most of the time. The problem is that solutions that use ProcessIDs or Window Handles fail occasionally due to Windows sloppy internal handling.
Here is a quick and dirty solution for keeping a single instance of a window. It uses shared memory to maintain a linked list of open windows. An application checks the list on startup, and if the application is on the list, it is exited.
Here is the header:
#if !defined(AFX_SingleInstance_H__INCLUDED_) #define AFX_SingleInstance_H__INCLUDED_ // SingleInstance.h : header file // void RegisterSiblingWindowHandle(LPCTSTR lpLabel, HWND hWnd); HWND GetSiblingWindowHandle(LPCTSTR lpLabel); void RemoveSiblingWindowHandle(LPCTSTR lpLabel); void RemoveSiblingWindowHandle(HWND hWnd); void OpenSiblingWindowHandles(void); void CloseSiblingWindowHandles(void); //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations // immediately before the previous line. #endif // !defined(AFX_SingleInstance_H__INCLUDED_)
To use the code, you need to activate the link to the shared list. The easiest way to do that is to insert the function
OpenSiblingWindowHandles();
into the constructor of CWinApp() if you are using MFC, or right after the RegisterClass() in your WinMain() in a standard Windows application.
You need to release the list at the end of the application as well with
CloseSiblingWindowHandles();
This works from the CWinApp() destructor in MFC or after the message loop in a Windows application.
When an application starts, before the main window is created (either via ProcessShellCommand(), DoModal(), or CreateWindow()), insert this code:
HWND hWndOther = GetSiblingWindowHandle(_T("My Unique ID")); if( hWndOther != NULL ) { ::SetWindowPos(hWndOther, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); ::SetFocus(hWndOther); return FALSE; }
When a new window is opened (like in CMainFrame or after CreateWindow()):
RegisterSiblingWindowHandle(_T("My Unique ID"), m_hWnd);
To unregister a window (in ExitInstance() or just before the CloseSiblingWindowHandles()):
RemoveSiblingWindowHandle(_T("My Unique ID"));
Of course, replace all the _T(“My Unique ID”) tags with a unique ID for your app.