私、WTLでそんなに大きなアプリケーションを作ったことがないので、WTL::CAppModuleの必要性を感じたことがないんです。あと、基底クラスであるATL::CComModuleは、ATL 7より非推奨になっています。それも、なんとなく避けたい理由の1つです。
では、WTL::CMessageFilterやWTL::CIdleHandlerを使いたいときはどうするかというと、こうです。WinMain関数かどこかで定義したWTL::CMessageLoopのオブジェクトを直接使います。WTL::CAppModuleのAddMessageLoopとGetMessageLoopのメンバー関数を使わない、それだけのことです。
以下のサンプルプログラムでは、WTL::CMessageFilterだけしか登場しませんが、WTL::CIdleHandlerも同じ要領です。
#define UNICODE #define _UNIDODE #define WINVER 0x0600 #define _ATL_NO_AUTOMATIC_NAMESPACE #define _WTL_NO_AUTOMATIC_NAMESPACE #include <windows.h> #include <atlbase.h> #include <atlwin.h> #include <atltypes.h> #include <atlapp.h> #include <atlcrack.h> #include <atlctrls.h> // https://msdn.microsoft.com/ja-jp/library/bb531404.aspx #ifdef UNICODE #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_IA64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_X64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") #else #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #endif #endif class TestWindow : public ATL::CWindowImpl<TestWindow>, public WTL::CMessageFilter { public: DECLARE_WND_CLASS(TEXT("Test Window Class")); bool Initialize(int cmdShow, _Inout_ WTL::CMessageLoop& msgLoop) { if (!Create(nullptr, CRect(0, 0, 200, 100), TEXT("Hello, world"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU)) { return false; } ShowWindow(cmdShow); UpdateWindow(); msgLoop.AddMessageFilter(this); return true; } BOOL PreTranslateMessage(_In_ MSG* msg) override { return IsDialogMessage(msg); } BEGIN_MSG_MAP(TestWindow) COMMAND_ID_HANDLER_EX(IDOK, OnOK) COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) MSG_WM_CREATE(OnCreate) MSG_WM_DESTROY(OnDestroy) END_MSG_MAP() private: void OnOK(UINT, int, HWND) { SendMessage(WM_CLOSE); } void OnCancel(UINT, int, HWND) { SendMessage(WM_CLOSE); } LRESULT OnCreate(const CREATESTRUCT*) { constexpr DWORD ButtonStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON; constexpr DWORD ButtonExStyle = WS_EX_NOPARENTNOTIFY; m_buttonOK.Create( *this, CRect(20, 20, 80, 50), L"OK", ButtonStyle, ButtonExStyle, IDOK); m_buttonCancel.Create( *this, CRect(100, 20, 160, 50), L"Cancel", ButtonStyle, ButtonExStyle, IDCANCEL); m_font = WTL::AtlCreateControlFont(); m_buttonOK.SetFont(m_font); m_buttonCancel.SetFont(m_font); return 0; } void OnDestroy() { PostQuitMessage(0); } WTL::CFont m_font; WTL::CButton m_buttonOK; WTL::CButton m_buttonCancel; }; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int cmdShow) { if (!WTL::AtlInitCommonControls(ICC_STANDARD_CLASSES)) { return -1; } WTL::CMessageLoop msgLoop; TestWindow wnd; if (!wnd.Initialize(cmdShow, msgLoop)) { return -1; } return msgLoop.Run(); } |
このコードは、Visual C++ 2015とWTL 9.1.5321 Finalでコンパイル・動作確認しました。
なお、ATL 7で導入されたATL::CAtlExeModuleTやATL::CAtlDllModuleTを活用しているプログラムに、あとからWTLを導入しようという場合、WTL::CAppModuleの入る隙がありません。そんなときも、この書き方が適用できます。
そんなわけで、邪道かもしれない、WTL::CAppModuleを使わないWTLプログラミングの話でした。ちなみに、昔書いた空のウィンドウを表示するだけのWindowsアプリケーション (WTL)でも、WTL::CAppModuleを使っていません。当時(それ以前)から、この書き方をずっとやっていたわけです。
スポンサード リンク |
この記事のカテゴリ
- VC++ ⇒ WTL::CAppModuleを使わない書き方