WTL-Single instance application

WTL版本的单实例程序。

如果此程序已经有一个实例在运行,当用户再次启动一个新的程序时,通知正在运行的实例,并将此实例放到窗口的最前面。

一.实现代码:

1.SingleInstance.h类

//SingleInstance.h

#pragma once

#include <windows.h>

class CSingleInstance

{

public:

    CSingleInstance(LPCTSTR mutexName)

    {

        m_hMutex = ::CreateMutex(NULL, FALSE, mutexName);

        m_IsAnotherInstanceRunning = (::GetLastError()==ERROR_ALREADY_EXISTS);

    }

    ~CSingleInstance()

    {

        if (m_hMutex)

        {

            ::CloseHandle(m_hMutex);

            m_hMutex = NULL;

        }

    }

public:

    BOOL IsAnotherInstanceRunning()

    {

        return m_IsAnotherInstanceRunning;

    }

private:

    HANDLE m_hMutex;

    BOOL m_IsAnotherInstanceRunning;

};

2.应用程序的入口处

#include "MainDlg.h"

#include "SingleInstance.h"

CAppModule _Module;

//The instance name string is generated with GuidGen tool

CSingleInstance g_SingleInstance(_T("{64B21E05-75CB-4329-A4E8-C6FE192F3506}"));

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)

{

    if (g_SingleInstance.IsAnotherInstanceRunning())

    {

        UINT registeredMsg = ::RegisterWindowMessage(BROADCAST_MSG_NAME);

        ATLASSERT(registeredMsg != 0);

        ::PostMessage(HWND_BROADCAST,registeredMsg,NULL,NULL);

        return 0;

    }

    //......

}

3.主窗口

//MainDlg.h

#pragma once

//The message name string is generated with GuidGen tool

LPCTSTR BROADCAST_MSG_NAME = _T("{1DF33122-865B-4A28-8249-D225842A49FB}");

class CMainDlg : 

    public CDialogImpl<CMainDlg>

{

private:

    UINT m_RegisteredMsg;

public:

    enum { IDD = IDD_MAINDLG };

    BEGIN_MSG_MAP_EX(CMainDlg)

        REGISTERED_MESSAGE_HANDLER(m_RegisteredMsg, OnRegisteredMsg)

        MSG_WM_INITDIALOG(OnInitDialog)

        COMMAND_ID_HANDLER(IDCANCEL, OnCancel)

    END_MSG_MAP()

public:

    CMainDlg()

    {

        m_RegisteredMsg = ::RegisterWindowMessage(BROADCAST_MSG_NAME);

        ATLASSERT(m_RegisteredMsg != 0);

    }

public:

    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)

    {

        // center the dialog on the screen

        CenterWindow();

        // set icons

        HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, 

            ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));

        SetIcon(hIcon, TRUE);

        HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, 

            ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));

        SetIcon(hIconSmall, FALSE);

        return TRUE;

    }

    LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)

    {

        // TODO: Add validation code 

        EndDialog(wID);

        return 0;

    }

    

    LRESULT OnRegisteredMsg(UINT uRegisteredMsg, WPARAM /*wParam*/, LPARAM /*lParam*/)

    {

        //Take this instance to foregrond

        if (IsIconic())

        {

            ShowWindow(SW_SHOWNORMAL);

        }

        ::SetForegroundWindow(m_hWnd);

            

        return 0;

    }

};

 

二.小技巧

主对话框的消息映射的第一行用于添加注册消息的响应函数:

BEGIN_MSG_MAP_EX(CMainDlg)

    REGISTERED_MESSAGE_HANDLER(m_RegisteredMsg, OnRegisteredMsg)

    //......

END_MSG_MAP()

其中的REGISTERED_MESSAGE_HANDLER()宏是一个自定义宏(MFC的消息映射中有一个宏ON_REGISTERED_MESSAGE()用于处理注册消息,而WTL库中则没有类似功能的宏,不过自定义一个这样的宏非常容易Open-mouthed smile):

//LRESULT OnPreProcessMessage(UINT uRegisteredMsg, WPARAM wParam, LPARAM lParam)

#define REGISTERED_MESSAGE_HANDLER(uRegisteredMsg, func) \

    if(uMsg == uRegisteredMsg) \

    { \

        SetMsgHandled(TRUE); \

        lResult = func(uMsg, wParam, lParam); \

        if(IsMsgHandled()) \

            return TRUE; \

    }

 

你可能感兴趣的:(application)