ATLのCAtlExeModuleTクラステンプレートには、WinMain関数があります。これを使うウィンドウアプリのサンプルコードを書いてみようと思いました。
以前書いた空のウィンドウを表示するだけのWindowsアプリケーション (WTL)をもとに書いています。
#define UNICODE #define _UNICODE #define WINVER 0x0501 #define _ATL_XP_TARGETING #define _ATL_NO_COM_SUPPORT #define _ATL_APARTMENT_THREADED #define _ATL_NO_AUTOMATIC_NAMESPACE #define _WTL_NO_AUTOMATIC_NAMESPACE #include <cstdlib> #include <windows.h> #include <atlbase.h> #include <atltypes.h> #include <atlwin.h> #include <atlapp.h> #include <atlcrack.h> class TestWindow : public ATL::CWindowImpl<TestWindow> { public: DECLARE_WND_CLASS(TEXT("Test Window Class")); private: BEGIN_MSG_MAP(TestWindow) MSG_WM_DESTROY(OnDestroy) END_MSG_MAP() void OnDestroy() { PostQuitMessage(0); } }; class Module : public ATL::CAtlExeModuleT<Module> { public: bool ParseCommandLine(_In_ PCTSTR /*cmdLine*/, _Out_ HRESULT* phr) { *phr = S_OK; return true; } HRESULT PreMessageLoop(int cmdShow) { if (!m_wnd.Create(nullptr, ATL::CWindow::rcDefault, TEXT("Hello, world"), WS_OVERLAPPEDWINDOW)) { return HRESULT_FROM_WIN32(GetLastError()); } m_wnd.ShowWindow(cmdShow); m_wnd.UpdateWindow(); return S_OK; }; private: TestWindow m_wnd; }; Module module; int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int cmdShow) { std::quick_exit(module.WinMain(cmdShow)); } |
CAtlExeModuleT::WinMainは、以下の関数を呼び出します。Run含め、すべてCRTPになっています。つまり、派生クラスでメンバ関数を作ることで、動作をオーバーライドできます。
- InitializeCom
- ParseCommandLine
- Run
- PreMessageLoop
- RunMessageLoop
- PostMessageLoop
- UninitializeCom
そのままだと、アウトプロセスのCOMサーバー用のための実装(/RegServer
コマンドライン引数を解釈したり、CoRegisterClassObject関数を呼び出したり)が多いです。そのため、不要な処理をある程度取り除いています。具体的には、_ATL_NO_COM_SUPPORTを定義したり、何もしないParseCommandLine関数を定義したりしました。
RunMessageLoop関数がGetMessage関数などによるメッセージループを実装しているため、ソースコードが少し短くなりました。場合によってはアリではないでしょうか。
参考: CAtlExeModuleT クラス(MSDNライブラリ)
スポンサード リンク |