vc sdk 单例程序运行

 

 使应用程序只能运行一个实例  
     
        Windows是多进程操作系统,框架生成的应用程序可以多次运行,形成多个运行实例。  
  但在有些情况下为保证应用程序的安全运行,要求程序只能运行一个实例,比如程    
  序要使用只能被一个进程单独使用的特殊硬件(例如调制解调器)时,必须限制程    
  序只运行一个实例。  
   
  这里涉及两个基本的问题,一是在程序的第二个实例启动时,如何发现该程序已有    
  一个实例在运行,而是如何将第一个实例激活,而第二个实例退出。  
   
  对于第一个问题,可以通过给应用程序设置信号量,实例启动时首先检测该信号量,    
  如已存在,则说明程序已运行一个实例。  
   
  第二个问题的难点是获取第一个实例的主窗对象指针或句柄,然后便可用    
  SetForegroundWindow来激活。虽然FindWindow函数能寻找正运行着的窗口,但该函    
  数要求指明所寻找窗口的标题或窗口类名,不是实现通用方法的途径。  
  我们可以用Win32   SDK函数SetProp来给应用程序主窗设置一个特有的标记。  
  用GetDesktopWindow   可以获取Windows系统主控窗口对象指针或句柄,所有应用程  
  序主窗都可看成该窗口的子窗口,即可用GetWindow函数来获得它们的对象指针或句  
  柄。用Win32   SDK函数GetProp查找每一应用程序主窗是否包含有我们设置的特定标  
  记便可确定它是否我们要寻找的第一个实例主窗。使第二个实例退出很简单,只要  
  让其应用程序对象的InitInstance函数返回FALSE即可。此外,当主窗口退出时,应  
  用RemoveProp函数删除我们为其设置的标记。  

 

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
 MSG msg;
 hInst = hInstance;//Handle to the module whose executable file contains the dialog box template.
 MenuIcon = new CMenuIcon(hInst);
 //防止多例程序运行


 char szClassName[256];
 
 hDlgModelLess = CreateDialog(hInst, (LPCTSTR)IDD_MAINDLG, NULL, (DLGPROC)MainDlgProc);
 GetClassName(hDlgModelLess , szClassName , 256);
 HANDLE hMutex = CreateMutex(NULL , FALSE , szClassName);
 if(GetLastError() == ERROR_ALREADY_EXISTS)
 {
  //   关闭信号量句柄    
  CloseHandle(hMutex);    
  //   寻找先前实例的主窗口     
  HWND   hWndPrevious   =  GetWindow(GetDesktopWindow(),NULL);     
 while   (IsWindow(hWndPrevious))     
 {     
  //   检查窗口是否有预设的标记?     
  //   有,则是我们寻找的主窗     
   if   (GetProp(hWndPrevious,   szClassName))     
   {     
    //   主窗口已最小化,则恢复其大小     
    if   (IsIconic(hWndPrevious))     
     ShowWindow(hWndPrevious,SW_RESTORE);         
   //   将主窗激活     
    SetForegroundWindow(hWndPrevious);         
   //   退出本实例 
   return   FALSE;
  // }
  //
  hWndPrevious = GetWindow(hWndPrevious,GW_HWNDNEXT); 
 }
   
  return FALSE;
 }
 ShowWindow(hDlgModelLess , SW_SHOW);
 while ( GetMessage(&msg, NULL, 0, 0) )
 {
  if (msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN )//屏蔽回车键
  {
   continue;
  }
  if (!IsWindow(hDlgModelLess) || !IsDialogMessage(hDlgModelLess, &msg))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 
 return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章