我们有些程序是可以同时运行多个进程,典型的像Visual Studio.但有些就能一次运行一个进程.比如Outlook.那你可能会问啥时可以让它同时打开多个应用程序,啥时只能一个啊.这个主要看进程间是否独立,会不会有冲突,是否会时读写相同的文件.
如果你不写代码去做些处理默认肯定是可以让你同时运行多个进程的.那假如只能一次运行一个进程咋整呢?有两种常用的方式.
使用互斥(Mutex)
在处理线程同步的时候我们也会用到这东东.我们知道它是一个内核对象.系统中一次只能创建一个,如果你再次创建一个同名的会出错.我们就是利用这个原理来达到一次只运行一个进程.
在APP类中的InitInstance函数的开头添加如下代码.
HANDLE hMutex;
BOOL CMyApp::InitInstance(){
hMutex = CreateMutex(NULL,FALSE,_T("ArwenApp"));
if(GetLastError() == ERROR_ALREADY_EXISTS){ //如果已经存在同名的Mutex会得到这个错误.
CloseHandle(hMutex);
return FALSE;
}
//其他代码
}
CMyApp::~CMyApp(){ //析构函数中关闭互斥句柄,当然如果你不写也没事.关闭应用程序时系统也会自动给你Close,不过还是自己写上好点了.
CloseHandle(hMutex);
}
查找窗体是否存在
在APP类中的InitInstance函数的开头添加如下代码.
BOOL CMyApp::InitInstance(){
CWnd* pWndExist;
CWnd* pWndPopup;
pWndExist = CWnd::FindWindow(_T("ArwenAppClass"),NULL);
if(pWndExist) { //如果窗体存在说明已经打开了应用程序,下面的操作只是让程序更人性化.也可以简单的返回FALSE就行.
pWndPopup = pWndExist->GetLastActivePopup(); //获得打开的活动窗体
if(pWndPopup->IsIconic())
pWndPopup->ShowWindow(SW_RESTORE); //如果窗体被最小化了,restore它
pWndPopup->ShowWindow(SW_SHOW); //显示已经打开的窗体
pWndPopup->SetForegroundWindow(); //让窗体显示在最前面
return FALSE;
}
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS));
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = LoadIcon(IDR_MAINFRAME);
wndcls.hCursor = LoadStandardCursor( IDC_ARROW );
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = _T("ArwenAppClass"); //注册一个窗体用来做判断是符存在已经打开的应用程序,除此之外该窗体没起啥作用
if(!AfxRegisterClass(&wndcls))
{
return FALSE;
}
CreateWindow(wndcls, _T("ArwenAppClass"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL);
//其他代码
}