如何讓應(yīng)用程序只運(yùn)行一個(gè)?關(guān)于這個(gè)問題是不是有很多小伙伴們?cè)趯W(xué)習(xí)的過程中都覺得不解呢?那么下面的內(nèi)容中就讓武林小編為大家介紹讓應(yīng)用程序只運(yùn)行一個(gè)的實(shí)現(xiàn)方法吧。
在我們的程序當(dāng)中如果要實(shí)現(xiàn)類似《360軟件管家》的功能,就要解決兩個(gè)問題,首先是要判斷該程序已有一個(gè)實(shí)例在運(yùn)行,其次是要將已運(yùn)行的應(yīng)用程序?qū)嵗せ睿瑫r(shí)退出第二個(gè)應(yīng)用程序?qū)嵗?/p>
對(duì)于第一個(gè)問題,我們可以通過設(shè)置命名互斥對(duì)象或命名信標(biāo)對(duì)象,在程序啟動(dòng)的時(shí)候檢測(cè)互斥對(duì)象或信標(biāo)對(duì)象,如互斥對(duì)象或信標(biāo)對(duì)象已存在,則可以判斷此程序已有一個(gè)實(shí)例正在運(yùn)行。
第二個(gè)問題是如何找到已經(jīng)運(yùn)行的應(yīng)用程序?qū)嵗?,如果我們能夠找到已運(yùn)行實(shí)例主窗口的指針,即可調(diào)用SetForegroundWindow來激活該實(shí)例。我們可以通過兩種形式找到已運(yùn)行實(shí)例的主窗口,一種形式是通過調(diào)用FindWindowEx去查找正在運(yùn)行的窗口的句柄,這種方式用得比較多一些,而本文通過另一種形式去查找正在運(yùn)行的窗口的句柄。通過調(diào)用SetProp給應(yīng)用程序主窗口設(shè)置一個(gè)標(biāo)記,用GetDesktopWindow 可以獲取Windows環(huán)境下的桌面窗口的句柄,所有應(yīng)用程序的主窗口都可以看成該窗口的子窗口,接著我們就可以用GetWindow函數(shù)來獲得這些窗口的句柄。然后再用Win32 SDK函數(shù)GetProp查找每一個(gè)應(yīng)用程序的主窗口是否包含有我們?cè)O(shè)置的標(biāo)記,這樣就可以找到我們要找的第一個(gè)實(shí)例主窗口。
下面演示代碼是以一個(gè)單文檔應(yīng)用程序?yàn)槔こ堂质荕utex。
?
BOOL CMutexApp::InitInstance()
{
?????? //創(chuàng)建命名信標(biāo)對(duì)象。
?????? HANDLE hSem=CreateSemaphore(NULL,1,1,"維新");
?????? if(hSem)? //信標(biāo)對(duì)象創(chuàng)建成功。
?????? {
????????????? //信標(biāo)對(duì)象已經(jīng)存在,則程序已有一個(gè)實(shí)例在運(yùn)行。
????????????? if(ERROR_ALREADY_EXISTS==GetLastError())
????????????? {?????????????????
???????????????????? CloseHandle(hSem);????? //關(guān)閉信號(hào)量句柄。
?
//獲取桌面窗口的一個(gè)子窗口。
???????????????????? HWND hWndPrev=::GetWindow(::GetDesktopWindow(),GW_CHILD);??
?
???????????????????? while(::IsWindow(hWndPrev))
???????????????????? {
???????????????????? //判斷窗口是否有我們預(yù)先設(shè)置的標(biāo)記,如有,則是我們尋找的窗口,并將它激活。
??????????????????????????? if(::GetProp(hWndPrev,"維新"))??
??????????????????????????? {
??????????????????????????? //如果主窗口已最小化,則恢復(fù)其大小。
?????????????????????????????????? if (::IsIconic(hWndPrev))????
????????????????????????????????????????? ::ShowWindow(hWndPrev,SW_RESTORE);
?
?????????????????????????????????? //將應(yīng)用程序的主窗口激活。
?????????????????????????????????? ::SetForegroundWindow(hWndPrev);
?????????????????????????????????? return FALSE;????????????????????? //退出實(shí)例。
??????????????????????????? }
??????????????????????????? //繼續(xù)尋找下一個(gè)窗口。
??????????????????????????? hWndPrev = ::GetWindow(hWndPrev,GW_HWNDNEXT);
???????????????????? }
???????????????????
???????????????????? AfxMessageBox("已有一個(gè)實(shí)例在運(yùn)行,但找不到它的主窗口!");
????????????? }
?????? }
?????? else
?????? {
????????????? AfxMessageBox("創(chuàng)建信標(biāo)對(duì)象失敗,程序退出!");
????????????? 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()函數(shù)中設(shè)置查找標(biāo)記。
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);
?
?????
?????? //設(shè)置查找標(biāo)記。
?????? ::SetProp(m_hWnd,"維新",(HANDLE)1);
?
?????? return 0;
}
3、在程序退出是刪除設(shè)置的標(biāo)記,在框架類中響應(yīng)WM_DESTROY消息,進(jìn)行處理。
void CMainFrame::OnDestroy()
{
?????? CFrameWnd::OnDestroy();
?????
?????? // TODO: Add your message handler code here
?????? //刪除所設(shè)置的標(biāo)記。
?????? ::RemoveProp(m_hWnd,"維新");
}
至此,使應(yīng)用程序只運(yùn)行一個(gè)實(shí)例的功能就完成了。
?
看完后你知道如何讓應(yīng)用程序只運(yùn)行一個(gè)了嗎?希望這項(xiàng)技術(shù)對(duì)您會(huì)有幫助,并且不會(huì)顯得太難,謝謝大家的閱讀!
新聞熱點(diǎn)
疑難解答
圖片精選