はじめに
ATL を使ってもデスクトップアプリを作成できます。本来は COM サーバを作成するための機能ですが、COM インターフェースを実装しなければ、普通のデスクトップアプリになります。
プロジェクトの作成
「新しいプロジェクト」ダイアログで「ATL プロジェクト」を選び OK ボタンをクリックします。
Fig.2 のようなダイアログが開くので、「アプリケーションの種類」を「実行可能ファイル (.exe)」を選んで OK ボタンをクリックします。
ソリューションエクスプローラに新しいプロジェクトが追加されます。
画面の作成
プロジェクトを選択して、コンテキストメニュー「追加」/「新しい項目」を実行する。ATL の項目から「ATL ダイアログ」を選択して「追加」ボタンをクリックします。
Fig.4 のようなダイアログが開くので、「短い名前」を入力します。これはダイアログのクラス名やファイル名の元になります。
プロジェクトのリソースビューで、ツリーを展開して Dialog の中の "IDD_..." をダブルクリックしてダイアログのデザイン画面を開きます。
ここで、必要なコントロールをダイアログに貼り付けてデザインを行います。
Visual Studio のバグ(?) 対応
ビルドを行うと、次のようなエラーが発生することがあるが、これは Visual Studio のバグでリソースファイル名に余分な空白が含まれているためである。
RC2135 file not found: xxxxxx.tlb
リソースファイルをコードで開き、エラーメッセージの xxxxxx (ファイル名の拡張子を除いた部分) を検索して、余分な空白を手動で削除します。それから、ビルドしなおし、エラーが消えることを確認します。
実行するとダイアログの OK ボタンとキャンセルボタンをクリックするとエラーが発生します。これは、このダイアログがモーダルでないにも関わらず、モーダルダイアログとして閉じるようになっているためです。
ダイアログのヘッダーファイル (この例では Server2Dlg.h) を開いて、コードの最後の方にある OK ボタンとキャンセルボタンのハンドラを修正します。これは "EndDialog(wID)" をコメントアウトし、代わりに "DestroyWindow()"を追加します。
_tWinMain へのコード追加
デフォルトだと、ダイアログを作成して表示するコードがないので、これを追加しないと何も表示されません。次のコードは、ATLServer2.cpp のコード例です。
// ATLServer2.cpp : WinMain の実装
# include "stdafx.h"
# include "resource.h"
# include "ATLServer2_i.h"
# include "Server2Dlg.h" // 追加
using namespace ATL;
class CATLServer2Module : public ATL::CAtlExeModuleT< CATLServer2Module >
{
public :
DECLARE_LIBID(LIBID_ATLServer2Lib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_ATLSERVER2, "{b0f20685-a805-41b9-b28b-ab076b2375d6}")
};
CATLServer2Module _AtlModule;
// Window メイン
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
// ダイアログを表示するためのコード
MSG msg;
CServer2Dlg dlg;
dlg.Create(NULL);
dlg.ShowWindow(nShowCmd);
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
// ここまで
return _AtlModule.WinMain(nShowCmd);
}
次の画像は、このサンプルプログラムの実行例です。コントロールは Static (Label 相当) だけ貼り付けてあります。
COM インターフェースの実装
COM インターフェースを実装すれば、COM サーバとして動作するはずです。
ソリューションエクスプローラでこのプロジェクトを選択し、コンテキストメニューの「追加」から「新しい項目の追加」ダイアログを開き、 「ATL シンプルオブジェクト」を選んで「追加」ボタンをクリックします。
COM DLL の場合と同じ要領で、プロパティやメソッドを実装します。コード編集が終わったら、ビルドを行います。エラーがなくなったらできあがった exe ファイルと tlb ファイルを適切なフォルダへコピーして、レジストリに登録します。
レジストリ登録は regsvr32 でなく、自分自身で行います。コマンドプロンプトを管理者モードで起動し、スイッチ /RegServer を付けて実行することで登録が行われます。下に例を示します。
C:> AxServer1.exe /RegServer
(参考) /UnRegServer を付けて実行すると登録が解除されます。
実際に COM インターフェースを実装して、テストしてみたところ起動が非常に遅かったです。メソッドの呼び出しもうまくいきませんでした。もしかしたら、COM DLL の場合と異なりマーシャリングを手動で行わないといけないのかもしれません。(別プロセスのため)