zoukankan      html  css  js  c++  java
  • MFC:只允许产生一个应用程序实例的具体实现

    转自:http://blog.csdn.net/sdcxyz/article/details/6804566 ,有改动。

    Windows是多进程操作系统,框架生成的应用程序可以多次运行,形成多个运行实例。但在有些情况下为保证应用程序的安全运行,要求程序

    只能运行一个实例,比如程序要使用只能被一个进程单独使用的特殊硬件(例如调制解调器)时,必须限制程序只运行一个实例。

    这里涉及两个基本的问题:一是在程序的第二个实例启动时,如何发现该程序已有一个实例在运行;二是如何将第一个实例激活,而使

    第二个实例退出。

    对于第一个问题,可以通过给应用程序设置互斥量/信号量,实例启动时首先检测该信号量,如已存在,则说明程序已运行一个实例。第二个问

    题的难点是获取第一个实例的主窗对象指针或句柄,然后便可用SetForegroundWindow来激活。虽然FindWindow函数能寻找正运行着的窗

    口,但该函数要求指明所寻找窗口的标题或窗口类名,不是实现通用方法的途径。我们可以用Win 32 SDK函数SetProp来给应用程序主窗设

    置一个特有的标记。用GetDesktopWindow可以获取Windows系统主控窗口对象指针或句柄,所有应用程序主窗都可看成该窗口的子窗口,

    即可用GetWindow函数来获得它们的对象指针或句柄。用Win 32 SDK函数GetProp查找每一应用程序主窗是否包含有我们设置的特定标记

    便可确定它是否我们要寻找的第一个实例主窗。使第二个实例退出很简单,只要让其应用程序对象的InitInstance函数返回FALSE即可。此

    外,当主窗口退出时,应用RemoveProp函数删除我们为其设置的标记。

    下面通过在CWinApp的成员函数InitInstance/ExitInstance和CWnd的成员函数OnCreate/OnDestroy中添加若干代码实现。

    CWinApp:

    BOOL CMFCXXXApp::InitInstance()
    
    {
    
    	this->m_hMutex = ::CreateMutexW(NULL,FALSE,this->m_pszAppName);//m_hMutex是新增的成员变量
    
    	if(::GetLastError()==ERROR_ALREADY_EXISTS)
    
    	{
    
    		::CloseHandle(m_hMutex);
    
    		HWND hPre = ::GetWindow(::GetDesktopWindow(),GW_CHILD);
    
    		while(::IsWindow(hPre))
    
    		{
    
    			if(::GetPropW(hPre,this->m_pszAppName))
    
    			{
    
    				if(::IsIconic(hPre))
    
    				{
    
    					::ShowWindow(hPre,SW_RESTORE);
    
    				}
    
    				::SetForegroundWindow(hPre);
    
    				::SetForegroundWindow(::GetLastActivePopup(hPre));
    
    				return false;
    
    			}
    
    			hPre = ::GetWindow(hPre,GW_HWNDNEXT);
    
    		}		
    
    	}
    
    //......
    
    //以下省略
    
    }
    int CMFCXXXApp::ExitInstance()
    
    {
    
    	::CloseHandle(this->m_hMutex);
    
    	return CWinApp::ExitInstance();
    
    }

    CWnd:

    int CMFCXXXDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    
    {
    
    	if (CDialogEx::OnCreate(lpCreateStruct) == -1)
    
    		return -1;
    
    	// TODO:  在此添加您专用的创建代码
    
    	::SetPropW(this->m_hWnd,::AfxGetAppName(),(HANDLE)1);
    
    	return 0;
    
    }
    void CMFCXXXDlg::OnDestroy()
    
    {
    
    	CDialogEx::OnDestroy();
    
    	::RemovePropW(this->m_hWnd,::AfxGetAppName());
    
    }
  • 相关阅读:
    问卷调查--来自20145320周岐浩
    第一次尝试编写java
    写在开始编写Java之前(2)——Java的环境
    写在开始编写Java之前(1)——Java的跨平台性
    一步一步实现JS拖拽插件
    序列图像三维重建 学习流水账
    linux配置虚拟机网络环境(老师要求的host-only)
    递归函数时间复杂度分析(转)
    什么是static?什么是final?
    复习java数据库操作的总结
  • 原文地址:https://www.cnblogs.com/qinfengxiaoyue/p/3051401.html
Copyright © 2011-2022 走看看