使應用程序只能運行一個實例
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;
}