网上查找MFC单例运行资料时,都是在说再次运行实例时提示已经有实例在运行了,而不是继续运行已经在运行的实例。一旦上个实例在隐藏状态下,就无法再打开了。本文主要介绍实例重复运行时,怎么再次调起上次的实例,并且不破坏当时的运行环境。
主要功能分为两个模块:
1、单例运行的实现
2、重复运行实例时激活上个实例,并且保持其运行状态
一、单例运行的实现
单例运行很容易实现,网上也有很多的代码示例,代码如下:
HANDLE hMutex=CreateMutex(NULL,TRUE,L"urlOpen");
if(hMutex)
{
if(ERROR_ALREADY_EXISTS==GetLastError())
{
HWND hOldSingleWnd = ::FindWindow(_T("urlOpen"),_T(APP_TITLE));
if (hOldSingleWnd)
{
::ShowWindow(hOldSingleWnd,SW_RESTORE);
::SetWindowPos(hOldSingleWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
::SetWindowPos(hOldSingleWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
//return ;
}
return FALSE;
}
}
原理:在创建窗口类对象之前,设置一个互斥锁,判断互斥锁是否已经存在,如果存在直接返回不再创建窗口类对象。
二、 重复运行实例时激活上个实例,并且保持其运行状态
上面创建单例运行的代码,我们可以看到有查找urlOpen窗口的逻辑,如果找到urlOpen窗口便将窗口展示出来。但是熟悉MFC的朋友都知道,MFC创建的窗口类名称是#32770,所以我们就需要自定义窗口类名称。具体操作如下:
1、将窗口类名称设置为可以修改状态
在资源视图,右键xx.rc属性,将Mfc Mode修改为false
2、在单例运行逻辑代码之后添加修改窗口类名称的代码
WNDCLASS wc;
// 获取窗口类信息。MFC默认的所有对话框的窗口类名为 #32770
::GetClassInfo(AfxGetInstanceHandle(), _T("#32770"), &wc);
// 改变窗口类名
wc.lpszClassName = _T("urlOpen");
// 注册新窗口类,使程序能使用它
AfxRegisterClass(&wc);
通过上面两个步骤,就可以修改窗口类名称了。
将一和二结合起来,就可以实现MFC程序单例运行,并且在重复运行时继续运行上个实例了。