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;
}

 

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