让程序只运行一个实例
一、创建互斥体 Mutex 法:
 
但是单纯的使用互斥体的话不能取得已经创建的实例窗口局柄,因此无法激活已经启动的实例窗口;
InitInstance里添加如下代码:(注意在domodal之前)
HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("[Guid("4A45E6F4-F030-4136-B138-72C5A7D14A4A")]"));
if ( GetLastError() == ERROR_ALREADY_EXISTS ){
    AfxMessageBox(_T("已经有一个实例正在运行中……"));
    CloseHandle(m_hMutex);
    m_hMutex = NULL;
    return FALSE;
}
//其他代码,比如对话框的创建及弹出等等
if (m_hMutex) {
    CloseHandle(m_hMutex);
    m_hMutex = NULL;
}
二、FindWindow法:
通过 FindWindow 进行窗口的查找,若发现则说明已经运行过一个实例,并将其窗口激活:
HWND hWnd = ::FindWindow(_T("#32770"), _T("DlgTest"));
if (hWnd != NULL) {
    AfxMessageBox(_T("已经有一个实例正在运行中……"));
    ::ShowWindow(hWnd, SW_NORMAL);
    ::SetForegroundWindow(hWnd);
    return FALSE;
}
此种方法不是很好,如果窗口标题改变了或者每个窗口实例的标题不一样,就找不到了!
三、设置窗口属性 SetProp + EnumWindows 法
1、加入全局变量的定义及枚举窗口函数:
TCHAR g_szPropName[] = _T("{12AA5160-5215-435b-AE3C-60C9E65615CE}");
HANDLE g_hValue = (HANDLE)9527;
BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)
{
    HANDLE hProp = GetProp(hwnd, g_szPropName);
    if(hProp == g_hValue) {
        *(HWND *)lParam = hwnd;
        return FALSE;
    }
    return TRUE;
}
2、窗口的枚举以及属性的添加: 
//OnInitDialog() 中加入以下代码:
  
HWND hPreWnd = NULL;
::EnumWindows(EnumWndProc, (LPARAM)&hPreWnd);
if (hPreWnd != NULL) {
    AfxMessageBox(_T("已经有一个实例正在运行中……"));
    ::ShowWindow(hPreWnd, SW_NORMAL);
    ::SetForegroundWindow(hPreWnd);
    ExitProcess(0);
    return FALSE;
}
::SetProp(m_hWnd, g_szPropName, g_hValue);
3、窗口属性的删除: 
OnDestroy() 函数中加入以下代码:
  
::RemoveProp(m_hWnd, g_szPropName);
四、使用全局共享变量的共享节法实现单实例运行
1、新建共享节:
  
#pragma data_seg("Shared")
HWND hPreWnd = NULL;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,RWS")
2、OnInitDialog() 函数中加入以下代码:
if (hPreWnd == NULL) {
    hPreWnd = m_hWnd;
} else {
    AfxMessageBox(_T("已经有一个实例正在运行中……"));
    ::ShowWindow(hPreWnd, SW_NORMAL);
    ::SetForegroundWindow(hPreWnd);
    ExitProcess(0);
    return FALSE;
}
五、互斥体+自定义广播系统消息法
1、系统消息的注册:
    
#define REG_MSG (_T("{7510EF00-BADA-48de-A6CE-5FBC817616DD}"))
UINT WM_ACTIVE_MSG = ::RegisterWindowMessage(REG_MSG);
2、发现实例后,进行消息的广播: 
InitInstance() 函数中添加如下代码:
HANDLE m_hMutex = ::CreateMutex(NULL, FALSE, _T("{6668BB0A-DE0C-499d-8520-79653FF9B2EB}"));
if ( GetLastError() == ERROR_ALREADY_EXISTS ){
    AfxMessageBox(_T("已经有一个实例正在运行中……"));
    CloseHandle(m_hMutex);
    m_hMutex = NULL;
    DWORD dwRecipients = BSM_APPLICATIONS;
    ::BroadcastSystemMessage(BSF_NOHANG, &dwRecipients, WM_ACTIVE_MSG, 0, 0);
    return FALSE;
}
//其他窗口创建之类的代码
if (m_hMutex) {
    CloseHandle(m_hMutex);
    m_hMutex = NULL;
}
3、窗口类中全局变量的作用域扩展:
extern UINT WM_ACTIVE_MSG;
4、窗口类中自定义消息的响应:
afx_msg LRESULT OnActiveMsg(WPARAM wParam, LPARAM lParam);
ON_REGISTERED_MESSAGE(WM_ACTIVE_MSG, &CDlgTestDlg::OnActiveMsg)
LRESULT CDlgTestDlg::OnActiveMsg(WPARAM wParam, LPARAM lParam)
{
    ::ShowWindow(m_hWnd, SW_NORMAL);
    ::SetForegroundWindow(m_hWnd);
    return TRUE;
}
                    
                
                
            
        
浙公网安备 33010602011771号