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になっています。つまり、派生クラスでメンバ関数を作ることで、動作をオーバーライドできます。

  1. InitializeCom
  2. ParseCommandLine
  3. Run
    1. PreMessageLoop
    2. RunMessageLoop
    3. PostMessageLoop
  4. UninitializeCom

そのままだと、アウトプロセスのCOMサーバー用のための実装(/RegServerコマンドライン引数を解釈したり、CoRegisterClassObject関数を呼び出したり)が多いです。そのため、不要な処理をある程度取り除いています。具体的には、_ATL_NO_COM_SUPPORTを定義したり、何もしないParseCommandLine関数を定義したりしました。

RunMessageLoop関数がGetMessage関数などによるメッセージループを実装しているため、ソースコードが少し短くなりました。場合によってはアリではないでしょうか。

参考: CAtlExeModuleT クラス(MSDNライブラリ)


スポンサード リンク

この記事のカテゴリ

  • ⇒ ATL::CAtlExeModuleT::WinMain関数を使う例
  • ⇒ ATL::CAtlExeModuleT::WinMain関数を使う例