摘要:让程序只运行一个实例的方法有数种,但原理都是相同的,就是在程序的主窗口创建之前,检查系统中是否已经存在某个与本程序相关的特定标志了。如果存在,则说明已经有一个实例在运行了,当前程序不用创建主窗口,直接退出即可。否则,就说明本程序是第一次运行。各种方法所不同的是,各自检查的标志不同,这也使得各种方法在使用时各有利弊了。一般来说,使程序只运行一个实例的最简单的方法当然是使用FindWindow()查找主窗口,如果主窗口已经存在了,当然说明已经有一个实例运行了。代码如下:// 主窗口创建前HWND hWnd = FindWindow("ClassName", "Caption");if(IsWindow(hWnd)){       ShowWindow(hWnd, SW_NORMAL);     // 显示       SetForegroundWindow(hWnd);                  // 激活       return;}这个方法的不足之处是,FindWindow()的参数ClassName和Caption比较难取得。比如,凡是使用DialogBoxParam()创建的对话框,他们的ClassName都是“#32770”,没有唯一性;而使用MFC创建的Doc/View结构的窗口的Caption更是会随Doc?Name的不同而有所变化。另一种方法就是使用Mutex互斥体了。代码如下:// 声明全局的局柄HANDLE g_hHandle;// 主窗口创建前g_hHandle = CreateMutex(NULL, FALSE, "Mutex Name");if(GetLastError() == ERROR_ALREADY_EXISTS){      return FALSE;}使用Mutex代码比较简洁,但是此时不能取得已经启动的实例窗口局柄,因此无法激活已经启动的实例窗口。第三种方法是我认为比较完善的方法,就是通过SetProp()为程序主窗口设置一个特殊的Property,然后在启动时遍历所有的窗口,找出包含着个Property的窗口局柄。这个方法的缺点就是代码比较多。如下:// 声明全局的property名和property valueLPCTSTR g_szPropName = "prop name";HANDLE g_hValue = (HANDLE)1;// 定义枚举窗口回调函数BOOL CALLBACK EnumWndProc(HWND?hwnd,?LPARAM?lParam){???????HANDLE?h?=?GetProp(hwnd,?g_szPropName);???????if(?h?==?g_hValue)???????{?????????????*(HWND*)lParam?=?hwnd;?????????????return?false;???????}???????return?true;}//?主窗口创建前判断HWND?hWnd?=?NULL;EnumWindows(EnumWndProc,?(LPARAM)&hWnd);if(IsWindow(hWnd)){??????ShowWindow(hWnd,?SW_NORMAL);??????SetForegroundWindow(hWnd);??????return?FALSE;}//?主窗口创建后设置SetProp(m_hWnd,?g_szPropName,?g_hValue);这个方法就是需要遍历系统中所有的窗口,效率可能稍低了些。 ...[阅读全文]