1. gzyueqian
      18529173453
      首頁 > 新聞中心 > > 正文

      如何做到像《金山詞霸》一樣只運行一個實例

      更新時間: 2007-05-16 13:31:35來源: 粵嵌教育瀏覽量:938


        我們在使用《金山詞霸》時發現,在《金山詞霸》已經運行了的情況下,再次點擊《金山詞霸》的圖標,那么它不會再運行另外一個《金山詞霸》,而是將已有的《金山詞霸》給激活,始終只能運行一個《金山詞霸》的實例。

        在我們的程序當中如果要實現類似《金山詞霸》的功能,就要解決兩個問題,首先是要判斷該程序已有一個實例在運行,其次是要將已運行的應用程序實例激活,同時退出第二個應用程序實例。

        對于個問題,我們可以通過設置命名互斥對象或命名信標對象,在程序啟動的時候檢測互斥對象或信標對象,如互斥對象或信標對象已存在,則可以判斷此程序已有一個實例正在運行。

        第二個問題是如何找到已經運行的應用程序實例,如果我們能夠找到已運行實例主窗口的指針,即可調用SetForegroundWindow來激活該實例。我們可以通過兩種形式找到已運行實例的主窗口,一種形式是通過調用FindWindowEx去查找正在運行的窗口的句柄,這種方式用得比較多一些,而本文通過另一種形式去查找正在運行的窗口的句柄。通過調用SetProp給應用程序主窗口設置一個標記,用GetDesktopWindow 可以獲取Windows環境下的桌面窗口的句柄,所有應用程序的主窗口都可以看成該窗口的子窗口,接著我們就可以用GetWindow函數來獲得這些窗口的句柄。然后再用Win32 SDK函數GetProp查找每一個應用程序的主窗口是否包含有我們設置的標記,這樣就可以找到我們要找的個實例主窗口。

        下面演示代碼是以一個單文檔應用程序為例,工程名字是Mutex。

      1、在應用程序類InitInstance()函數中判斷是否已有一個應用程序實例正在運行。

      BOOL CMutexApp::InitInstance()

      {

      //創建命名信標對象。

      HANDLE hSem=CreateSemaphore(NULL,1,1,"維新");

      if(hSem) //信標對象創建成功。

      {

      //信標對象已經存在,則程序已有一個實例在運行。

      if(ERROR_ALREADY_EXISTS==GetLastError())

      {

      CloseHandle(hSem); //關閉信號量句柄。



      //獲取桌面窗口的一個子窗口。

      HWND hWndPrev=::GetWindow(::GetDesktopWindow(),GW_CHILD);



      while(::IsWindow(hWndPrev))

      {

      //判斷窗口是否有我們預先設置的標記,如有,則是我們尋找的窗口,并將它激活。

      if(::GetProp(hWndPrev,"維新"))

      {

      //如果主窗口已小化,則恢復其大小。

      if (::IsIconic(hWndPrev))

      ::ShowWindow(hWndPrev,SW_RESTORE);



      //將應用程序的主窗口激活。

      ::SetForegroundWindow(hWndPrev);

      return FALSE; //退出實例。

      }

      //繼續尋找下一個窗口。

      hWndPrev = ::GetWindow(hWndPrev,GW_HWNDNEXT);

      }



      AfxMessageBox("已有一個實例在運行,但找不到它的主窗口!");

      }

      }

      else

      {

      AfxMessageBox("創建信標對象失敗,程序退出!");

      return FALSE;

      }



      AfxEnableControlContainer();



      // Standard initialization

      // If you are not using these features and wish to reduce the size

      // of your final executable, you should remove from the following

      // the specific initialization routines you do not need.



      #ifdef _AFXDLL

      Enable3dControls(); // Call this when using MFC in a shared DLL

      #else

      Enable3dControlsStatic(); // Call this when linking to MFC statically

      #endif



      // Change the registry key under which our settings are stored.

      // TODO: You should modify this string to be something appropriate

      // such as the name of your company or organization.

      SetRegistryKey(_T("Local AppWizard-Generated Applications"));



      LoadStdProfileSettings(); // Load standard INI file options (including MRU)



      // Register the application's document templates. Document templates

      // serve as the connection between documents, frame windows and views.



      CSingleDocTemplate* pDocTemplate;

      pDocTemplate = new CSingleDocTemplate(

      IDR_MAINFRAME,

      RUNTIME_CLASS(CMutexDoc),

      RUNTIME_CLASS(CMainFrame), // main SDI frame window

      RUNTIME_CLASS(CMutexView));

      AddDocTemplate(pDocTemplate);



      // Parse command line for standard shell commands, DDE, file open

      CCommandLineInfo cmdInfo;

      ParseCommandLine(cmdInfo);



      // Dispatch commands specified on the command line

      if (!ProcessShellCommand(cmdInfo))

      return FALSE;



      // The one and only window has been initialized, so show and update it.

      m_pMainWnd->ShowWindow(SW_SHOW);

      m_pMainWnd->UpdateWindow();



      return TRUE;

      }

      2、在框架類的OnCreate()函數中設置查找標記。

      int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

      {

      if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

      return -1;



      if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

      | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

      !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

      {

      TRACE0("Failed to create toolbar\n");

      return -1; // fail to create

      }



      if (!m_wndStatusBar.Create(this) ||

      !m_wndStatusBar.SetIndicators(indicators,

      sizeof(indicators)/sizeof(UINT)))

      {

      TRACE0("Failed to create status bar\n");

      return -1; // fail to create

      }



      // TODO: Delete these three lines if you don't want the toolbar to

      // be dockable



      m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

      EnableDocking(CBRS_ALIGN_ANY);

      DockControlBar(&m_wndToolBar);





      //設置查找標記。

      ::SetProp(m_hWnd,"維新",(HANDLE)1);



      return 0;

      }

      3、在程序退出是刪除設置的標記,在框架類中響應WM_DESTROY消息,進行處理。

      void CMainFrame::OnDestroy()

      {

      CFrameWnd::OnDestroy();



      // TODO: Add your message handler code here

      //刪除所設置的標記。

      ::RemoveProp(m_hWnd,"維新");

      }

      至此,使應用程序只運行一個實例的功能就完成了。

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 中文字幕在线精品视频站 | 亚洲欧美va在线播放 | 亚洲中文字幕乱码久久 | 亚洲一区二区三区深田咏美 | 中文字幕日本一区二区三区 | 中文字幕不卡亚洲 |