通过一个小例子,了解一下互斥对象的用处.
有些软件是不允许运行第二个实例的,比如360,你只要运行了他,在运行一次他就只会被调到前面不会再创建一个新的进程.
1.定义一个互斥对象句柄
HANDLE m_hMutex;//互斥对象句柄
2.给窗口设置一个标记属性,以便等会凭着这个标记找到本实例窗口
在WM_CREATE消息函数中设置窗口标记属性
int CMFCTESTDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
SetProp(
m_hWnd, //窗口句柄
AfxGetApp()->m_pszExeName,//属性名称
(HANDLE)2 //属性值,这个值随便设,设为1最简单,找到该标记然后返回1
);
return 0;
}
3.在初始化实例中创建互斥对象,然后当实例运行第二次的时候把第一个实例调到前面而不去创建一个新的实例
m_hMutex = CreateMutex(
nullptr, //默认安全属性
FALSE, //不被继承
TEXT("MFCTESTApp")//互斥对象名称,保证独一无二
);
//如果尝试运行第二个实例则会出现错误,进入到if语句中把该实例调到最前面
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
//获取桌面句柄
CWnd* pDesktopWnd = CWnd::GetDesktopWindow();
//得到桌面的第一个窗口句柄(桌面上的窗口都是它的子窗口)
CWnd* pWnd = pDesktopWnd->GetWindow(GW_CHILD);
while (pWnd)
{
//找到被标记的窗口属性
if (GetProp(pWnd->m_hWnd,AfxGetApp()->m_pszExeName) == (HANDLE)2)
{
//调到最前面
pWnd->SetForegroundWindow();
return FALSE;
}
//继续找
pWnd = pWnd->GetWindow(GW_HWNDNEXT);
}
return FALSE;
}
4.删除前面设置的窗口标记属性
在WM_DESTROY消息函数中删除
void CMFCTESTDlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
//删除属性
RemoveProp(m_hWnd, AfxGetApp()->m_pszExeName);
}