让一个程序只允许一个实例,并且如果已经有一个允许实例,则激活它
为该程序在属性列表里面添加一条记录
int CTrainingSystemDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; //设置标记 ::SetProp(m_hWnd, _T("UniqueMark"), AfxGetApp()->m_hInstance); return 0; }
在InitInstance函数中判断标记是否存在,如果存在,则激活含有该标记的程序:
HANDLE hMutex = ::CreateMutex(NULL, TRUE, _T("training_system")); if (::GetLastError() == ERROR_ALREADY_EXISTS) { //AfxMessageBox(_T("程序已经运行")); //寻找先前实例的主窗口 HWND hPrevWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD); while (::IsWindow(hPrevWnd)) { //检查窗口是不是有先前设置的标记 //如果有,则是我们寻找的窗口 if (::GetProp(hPrevWnd, _T("UniqueMark"))) { //主窗口已经最小化,则将其恢复 if (::IsIconic(hPrevWnd)) { ::ShowWindow(hPrevWnd, SW_RESTORE); } //将主窗口激活 ::SetForegroundWindow(hPrevWnd); //将主窗口的对话框激活 ::SetForegroundWindow(::GetLastActivePopup(hPrevWnd)); return FALSE; } //继续寻找下一个窗口 hPrevWnd = ::GetWindow(hPrevWnd, GW_HWNDNEXT); } return FALSE; }
在程序结束时删除标记:
void CTrainingSystemDlg::OnDestroy() { CDialog::OnDestroy(); //删除标记 ::RemoveProp(m_hWnd, _T("UniqueMark")); }
附:以下是MSDN上面的说明
Before a window is destroyed (that is, before it returns from processing the WM_NCDESTROY message), an application must remove all entries it has added to the property list. The application must use the RemoveProp function to remove the entries.
BOOL SetProp( HWND hWnd, //要添加或者修改那个窗口的属性列表 LPCTSTR lpString, //可以理解成一个key HANDLE hData //可以理解成一个value。当key已经存在,那么就替换掉value,否则创建 ); HANDLE GetProp( //返回值时key对应的value,也就是你在SetProp的时候指定的hData HWND hWnd, //要返回那个窗口的属性 LPCTSTR lpString //要查找的key ); HANDLE RemoveProp( HWND hWnd, //要移除谁的属性 LPCTSTR lpString //要删除的key );