让一个程序只允许一个实例,并且如果已经有一个允许实例,则激活它

为该程序在属性列表里面添加一条记录

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
);
posted @ 2012-03-16 14:43  kcy-666  阅读(521)  评论(0编辑  收藏  举报