只允许一个实例的方法比较简单:
在InitInstance() 函数里加入如下代码,利用互斥量来保证只运行一次
HANDLE m_hMutex = CreateMutex(NULL, TRUE, m_pszAppName)
if(GetLastError() == ERROR_ALREADY_EXISTS)
return FALSE;
如果要找到已经运行的实例,并激活,则要利用信号量来实现。
在App::InitInstance() 中加入以下代码
HANDLE hSem = CreateSemaphore(NULL, 1, 1, m_pszAppName);
// 信号量已存在?
// 信号量存在,则程序已有一个实例运行
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// 关闭信号量句柄
CloseHandle(hSem);
// 寻找先前实例的主窗口
HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (::IsWindow(hWndPrevious))
{
// 检查窗口是否有预设的标记?
// 有,则是我们寻找的主窗
if (::GetProp(hWndPrevious, m_pszAppName))
{
//主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_SHOW);
//将主窗激活
::SetForegroundWindow(hWndPrevious);
//将主窗的对话框激活
::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
//退出本实例
return FALSE;
}
// 继续寻找下一个窗口
hWndPrevious = ::GetWindow(hWndPrevious,GW_HWNDNEXT);
}
// 前一实例已存在,但找不到其主窗
// 可能出错了
// 退出本实例
return FALSE;
}
在Dlg::OnCreate加入以下代码
::SetProp(m_hWnd, AfxGetApp()-> m_pszAppName, (HANDLE)1);
在Dlg::OnDestroy()中加入以下代码
::RemoveProp(m_hWnd, AfxGetApp()-> m_pszAppName);
目前存在的问题:
对于最小化到托盘的程序无法激活……
========================================================
2011年12月15日更新
解决对于最小化到托盘的程序无法激活的问题
实际上上面的代码已经含有了最小化的代码部分
//主窗口已最小化,则恢复其大小
if (::IsIconic(hWndPrevious))
::ShowWindow(hWndPrevious, SW_SHOW);
但是个人对其不理解的是IsIconic函数的具体作用,反正我自己写的最小化到托盘的程序里面这个函数没有正确的返回状态。
解决的方法很简单,直接用
::ShowWindow(hWndPrevious, SW_SHOW);
即可,目前没有发现什么副作用