WTL版本的单实例程序。
如果此程序已经有一个实例在运行,当用户再次启动一个新的程序时,通知正在运行的实例,并将此实例放到窗口的最前面。
//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;};
#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;}//......
}
//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库中则没有类似功能的宏,不过自定义一个这样的宏非常容易):
//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; \}