为该程序在属性列表里面添加一条记录
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
);