COM の作成 :【VC++】



ブラウザでダウンロード

COM は、ビルドするとその PC に登録されてしまいます。
リリースしたものは、他の PC で regsvr32.exe で登録します。
以下、Microsoft の regsvr32 的なドキュメント
1) ダウンロード センターから入手可能な Regsvr32.exe
2) Regsvr32.exe の登録し、COM DLL の登録を解除するソースコード
● ATL プロジェクトを作成する






● クラスを追加する








● メソッドを追加





● ビルド環境設定










● 簡単なメソッドの実装


tool.h に lightbox.h の参照を追加して、#pragma の記述を行います
01.#pragma once
02.#include "resource.h"
03.#include "night.h"
04. 
05.#include "lightbox\lightbox.h"
06. 
07.#pragma comment( lib, "lightbox\\lightbox.lib" )
08.#pragma comment( lib, "shlwapi.lib" )
09.#pragma comment( lib, "wininet.lib" )  
01.// *********************************************************
02.// MsgBox
03.// *********************************************************
04.STDMETHODIMP Ctool::MsgBox(BSTR str)
05.{
06.    _bstr_t bstr = str;
07. 
08.    ::MessageBox( NULL, (LPTSTR)bstr, "", MB_OK );
09. 
10.    return S_OK;
11.}
テスト用スクリプト
● 戻り値を返すメソッドの実装
何故か、ウィザードでは指定できないようなので、手作業で追加します

場所は 3 箇所あるので注意して下さい。
night.idl
01.// night.idl : night の IDL ソース
02.//
03. 
04.// このファイルは、タイプ ライブラリ (night.tlb) およびマーシャリング コードを
05.// 作成するために MIDL ツールによって処理されます。
06. 
07.import "oaidl.idl";
08.import "ocidl.idl";
09. 
10.[
11.    object,
12.    uuid(56CFD513-9FFE-49F7-BE4F-CCFFD77A260D),
13.    dual,
14.    nonextensible,
15.    helpstring("Itool インターフェイス"),
16.    pointer_default(unique)
17.]
18.interface Itool : IDispatch{
19.    [id(1), helpstring("メソッド MsgBox")] HRESULT MsgBox([in] BSTR str);
20.    [id(2), helpstring("メソッド GetClipboard")] HRESULT GetClipboard([out,retval] BSTR *pVal);
21.};
22.[
23.    uuid(246E5E95-954B-4461-A7A8-1677C3412E20),
24.    version(1.0),
25.    helpstring("night 1.0 タイプ ライブラリ")
26.]
27.library nightLib
28.{
29.    importlib("stdole2.tlb");
30.    [
31.        uuid(543A98AE-FEFC-4D34-99ED-D8D7FE94823C),
32.        helpstring("tool Class")
33.    ]
34.    coclass tool
35.    {
36.        [default] interface Itool;
37.    };
38.};
id(2) の行が追加されています
戻り値は、[out,retval] BSTR *pVal で表現されます


tool.h
01.// Ctool
02. 
03.class ATL_NO_VTABLE Ctool :
04.    public CComObjectRootEx<CComMultiThreadModel>,
05.    public CComCoClass<Ctool, &CLSID_tool>,
06.    public IDispatchImpl<Itool, &IID_Itool, &LIBID_nightLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
07.{
08.public:
09.    Ctool()
10.    {
11.    }
12. 
13.DECLARE_REGISTRY_RESOURCEID(IDR_TOOL)
14. 
15. 
16.BEGIN_COM_MAP(Ctool)
17.    COM_INTERFACE_ENTRY(Itool)
18.    COM_INTERFACE_ENTRY(IDispatch)
19.END_COM_MAP()
20. 
21. 
22. 
23.    DECLARE_PROTECT_FINAL_CONSTRUCT()
24. 
25.    HRESULT FinalConstruct()
26.    {
27.        return S_OK;
28.    }
29. 
30.    void FinalRelease()
31.    {
32.    }
33. 
34.public:
35. 
36.    STDMETHOD(MsgBox)(BSTR str);
37.    STDMETHOD(GetClipboard)(BSTR *pVal);
38.};
39. 
40.OBJECT_ENTRY_AUTO(__uuidof(tool), Ctool)
Ctool クラスとしてのメソッド宣言の追加です
仮引数の記述のみを行います


tool.cpp
01.STDMETHODIMP Ctool::GetClipboard(BSTR *pVal)
02.{
03.    _bstr_t bstrValue;
04.    LboxString LString;
05.    LboxTool Tool;
06. 
07.    Tool.GetClipboardText( LString );
08.    bstrValue.operator = (LString.szLboxString);
09. 
10.    *pVal = bstrValue.copy();
11. 
12.    return S_OK;
13.}
処理本体です。
戻り値のメモリ管理は、受け渡したアプリケーションで行われるので、
copy メソッドにより作成された新しいメモリを渡します。
テスト用スクリプト


● 引数を省略可能にするには
以下は、別の COM のサンプルです
1.interface IMyAPI : IDispatch
2.{
3.    [id(1), helpstring("メソッド MsgBox")] HRESULT MsgBox(
4.        [in] BSTR Message,
5.        [in,optional] VARIANT Title
6.    );
7.};
1.public:
2.    STDMETHOD(MsgBox)(
3.        BSTR Message,
4.        VARIANT Title
5.    );
01.STDMETHODIMP CMyAPI::MsgBox(
02.    BSTR Message,
03.    VARIANT Title
04.)
05.{
06.    // 引数省略チェック用
07.    _variant_t vtWork(Title);
08. 
09.    _bstr_t bstr(Message);
10.    _bstr_t bstr2;
11. 
12.    // タイトル引数チェック
13.    if ( vtWork.vt != VT_ERROR ) {
14.        bstr2.operator = (Title);
15.    }
16.    else {
17.        bstr2.operator = ("デフォルト文字列");
18.    }
19. 
20.    MessageBox( NULL, (LPTSTR)bstr, (LPTSTR)bstr2, MB_OK );
21. 
22.    return S_OK;
23.}


● BOOLを返すには
通常の C++ における 真偽値の扱いと違うので( 正確に定義されている )
LboxBool 関数によって変換します。
1.[id(3), helpstring("メソッド MsgOkCancel")] HRESULT MsgOkCancel(
2.    [in] BSTR Value,
3.    [out,retval] BOOL *pVal
4.);
01.STDMETHODIMP CMyAPI::MsgOkCancel(
02.    BSTR Value,
03.    BOOL *pVal
04.)
05.{
06.    _bstr_t bstrValue;
07.    LboxWintool Wintool;
08. 
09.    bstrValue.operator = (Value);
10. 
11.    *pVal = LboxBool( Wintool.MsgOkCancel((LPTSTR)bstrValue) );
12. 
13.    return S_OK;
14.}
LboxBool
01.BOOL LboxBool( BOOL bFlg )
02.{
03.    BOOL bRet;
04. 
05.    if ( bFlg ) {
06.        bRet = 0xffffffff;
07.    }
08.    else {
09.        bRet = 0;
10.    }
11. 
12.    return bRet;
13.}