WTL-支持Single instance的CApplicationT类
为CApplicationT添加了Single instance功能支持:
#pragma once#include <Windows.h>#include <ATLHelper.h>#pragma data_seg("Shared")
volatile HWND _g_hMainWindow = NULL;
#pragma data_seg()#pragma comment(linker,"/Section:Shared,RWS")
namespace WTL
{//CApplicationT class
template<typename T, typename TMainWindow, bool bInitializeCom = false>class CApplicationT :
public CAppModule
{public:
//Call this method in the application's entry point[_tWinMain(...)]
int WinMain(HINSTANCE hInstance,LPTSTR lpCmdLine,int nCmdShow){UNREFERENCED_PARAMETER(lpCmdLine);T* pT = static_cast<T*>(this);if(!(pT->OnStartup()))
return 0;
HRESULT hr = S_OK;if (bInitializeCom)
{hr = ::CoInitialize(NULL);// If you are running on NT 4.0 or higher you can use the following
// call instead to make the EXE free threaded. This means that calls
// come in on a random RPC thread.
// hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
CHECKHR(hr);}// This resolves ATL window thunking problem when Microsoft Layer
// for Unicode (MSLU) is used
::DefWindowProc(NULL, 0, 0, 0L);pT->OnInitCommonControl();hr = Init(NULL, hInstance);CHECKHR(hr);int nRet = 0;
{CMessageLoop msgLoop;AddMessageLoop(&msgLoop);TMainWindow wndMain;_g_hMainWindow = wndMain.Create(NULL,CWindow::rcDefault);if(_g_hMainWindow == NULL)
{ATLTRACE(_T("Failed to create Main window!\n"));
return 0;
}wndMain.ShowWindow(nCmdShow);wndMain.UpdateWindow();wndMain.CenterWindow();nRet = msgLoop.Run();RemoveMessageLoop();_g_hMainWindow = NULL;}Term();if (bInitializeCom)
::CoUninitialize();pT->OnShutdown();return nRet;
}public:
BOOL IsAnotherInstanceRunning(){return (_g_hMainWindow!=NULL);
}void TakeAnotherInstanceForeground()
{if (_g_hMainWindow)
{CWindow mainWnd(_g_hMainWindow);if (mainWnd.IsIconic())
mainWnd.ShowWindow(SW_RESTORE);mainWnd.SetForegroundWindow();}}protected:
//Override this method to do some work on start up
BOOL OnStartup(){return TRUE;
}//Override this method to do some work on shut down
void OnShutdown()
{}//Override this method to support other native controls
void OnInitCommonControl()
{AtlInitCommonControls(ICC_COOL_CLASSES|ICC_BAR_CLASSES|ICC_WIN95_CLASSES);}};//CApplication class
template<typename TMainWindow, bool bInitializeCom = false>class CApplication :
public CApplicationT<CApplication<TMainWindow,bInitializeCom>, TMainWindow, bInitializeCom>
{};}//namespace WTL
使用方法:
1.如果CApplicationT提供的功能已满足要求,不需要修改默认行为,也不需要添加Single instance功能支持,可直接用typedef定义自己的WTL应用程序类:
typedef CWinTraits<WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN> CMainWinTraits;
class CMainWindow :
public CWindowImpl<CMainWindow,CWindow,CMainWinTraits>
{public:
//...
};typedef CApplication<CMainWindow> CMainApp;
CMainApp g_MainApp;
2.如果需要使用Single instance功能,则可以覆盖OnStartup()方法,执行单程序实例检测:
class CMainApp :
public CApplicationT<CMainApp,CMainWindow>
{public:
BOOL OnStartup(){//Check if another instance is running on start up
if (IsAnotherInstanceRunning())
{::MessageBox(NULL,_T("Another instance is running.\n\nClick OK to take another instance foreground."),
_T("WTL message"),
MB_OK|MB_ICONINFORMATION);TakeAnotherInstanceForeground();return FALSE;
}return TRUE;
}};