229上位机VC MFC使程序仅能运行一个
229上位机VC MFC使程序仅能运行一个 功能展示 不像娱乐软件如视频播放软件一样,可以同时打开多个程序观看不同视频,上位机运行时,大多数要求仅能运行一个程序,如果一个上位机程序运行多个实例,同时控制PLC,或同时控制设备等一些工控硬件,肯定会出问题。所以要求仅运行一个程序实例在上位机开发是很常见的功能,当前例程通过两种方法实现程序仅能运行一个的功能,效果如图:打开程序后,再打开第二个第三个多个程序时,全部程序都会阻止运行且第一程序提示阻止信息 要点提示 方法一:1.通过在程序入口处调用函数CreateMutex()创建一互斥对象,再通过代码if(GetLastError()==ERROR_ALREADY_EXISTS)判断此互斥对象是否存在,存在表示一程序实现在运行,我们新打开的程序就不运行,直接退出; 2.在程序退出时调用函数ReleaseMutex(m_hMutex);释放之前创建的互斥对象; 方法二功能更全:1.在程序一窗口初始化时调用函数SetProp(m_hWnd,sPropName,(HANDLE)1);在指定窗口的属性表中增加一个新项;2.在程序入口处我们也可以通过代码HANDLE hSem = CreateSemaphore(NULL,1,1,sPropName);if(GetLastError() == ERROR_ALREADY_EXISTS) 来判断程序是否已运行,具体实现过程可看下面的视频演示; CreateMutex作用是找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥对象。函数原型HANDLECreateMutex(LPSECURITY_ATTRIBUTESlpMutexAttributes, BOOLbInitialOwner, LPCTSTRlpName ); 参数 类型及说明: lpMutexAttributes SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值),表示使用不允许继承的默认描述符 bInitialOwner Long,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有 lpName String,指定互斥体对象的名字。用vbNullString创建一个未命名的互斥体对象。如已经存在拥有这个名字的一个事件,则打开现有的已命名互斥体。这个名字可能不与现有的事件、信号机、可等待计时器或文件映射相符; 一旦不再需要,注意必须用CloseHandle函数将互斥体句柄关闭。线程中止前,一定要调用ReleaseMutex释放互斥体; SetProp()函数在指定窗口的属性表中增加一个新项,或者修改一个现有项;函数原型:BOOLSetProp(HWND hWnd,LPCTSTR lpString,HANDLEhData);参数说明: hWnd:指向窗口的句柄,该窗口的属性表要接收一个新项。 lpString:指向以null结尾的字符串指针,或者包含一个标识字符串的原子。如果该参数是一个原子,那么它必须是以前使用GlobalAddAtom函数创建的。原子是16位的数据值,它必须是放置在lpstring参数低位字中,而高位字必须为O。 hData:指向要拷贝到属性表中的数据的句柄。该数据句柄可以标识任何对应用程序有用的值。 在清除窗口之前(也就是在处理WM_NCDESTROY消息之前),应用程序必须把它加到属性表的所项清除。应用程序必须使用RemoveProp函数来清除这些项 实现功能 1.新建基于对话框的应用程序 2.在stdafx.h头文件中添加头文件#define UM_ONLYRUNONCE WM_USER+101 //例程仅运行一次 #definesPropName "Gkbc8_OnlyRunOneInstance“ 3.在主对话框中添加函数protected: void LetMeRunOnce(); voidLetMeShow(); 在对话框初始化时调用函数LetMeRunOnce();//仅运行本实例一次 在对话框退出时OnDestroy()中调用函数RemoveProp(m_hWnd,sPropName); 注意LetMeShow()函数是对消息UM_ONLYRUNONCE的响应,得添加响应映射代码ON_MESSAGE(UM_ONLYRUNONCE,LetMeShow) 4.在App类中添加函数IsProgramRunning()用于判断程序是否已运行,此函数在App类的InitInstance()函数中调用 if(IsProgramRunning()) return FALSE; - BOOL CGkbc8App::IsProgramRunning()
- {
- HANDLE hSem = CreateSemaphore(NULL,1,1,sPropName);
- if(GetLastError() == ERROR_ALREADY_EXISTS)
- {
- CloseHandle(hSem);
- HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(),GW_CHILD);
- while(::IsWindow(hWndPrevious))
- {
- if(::GetProp(hWndPrevious,sPropName))
- {
- ::PostMessage(hWndPrevious,UM_ONLYRUNONCE,0,0);
- return TRUE;
- }
- hWndPrevious = ::GetWindow(hWndPrevious,GW_HWNDNEXT);
- }
- return TRUE;
- }
- return FALSE;
- }
复制代码我们来演示下功能实现的整个过程
|