既に起動しているアプリケーションのドキュメントや、ウィンドウを、
別のアプリケーションがいじくりたい。
MFCサンプルの mfccalc でやってるんだが、
こいつの readme の「このサンプルでは、次のキーワードを使用します。」には、
肝心なキーワードが抜けていて、なかなか辿りつけなかった。
やっとたどり着いたので、メモっとく。
●サーバー側
オブジェクトのコンストラクタで、RegisterActiveObject を呼んで登録。
こんな感じ。
void CObjectOne::CObjectOne()
{
HRESULT hr=RegisterActiveObject(GetControllingUnknown(),
clsid,
ACTIVEOBJECT_WEAK,
&m_dwCookie);
}
clsid は、 idl や odl ファイルで定義した、そのクラスのid、↓これ
[ uuid(5B6EA18B-C28C-495E-A92B-A46D0812D75D)]
coclass ObjectOne
を↓この形式にしたもの。
static const CLSID clsid =
{ 0x5b6ea18b, 0xc28c, 0x495e, { 0xa9, 0x2b, 0xa4, 0x6d, 0x8, 0x12, 0xd7, 0x5d } };
3つめのパラメータは、
ACTIVEOBJECT_STRONG または ACTIVEOBJECT_WEAK。
強いのと弱いの?
CDocument の派生クラスだったら、
OnNewDocument, OnOpenDocument あたりでやるのがよさそう。
デストラクタで、RevokeActiveObject を呼んで解放。
CObjectOne::~CObjectOne()
{
if (m_dwCookie != 0)
RevokeActiveObject(m_dwCookie, NULL);
}
●クライアント側
簡単なCOMのサンプルを見ると、いきなり CreateDispatch してたりするが、
これでは、新たに作られてしまうので、
先に、探しに行く必要がある。
LPUNKNOWN pUnk = NULL;
LPDISPATCH pDisp = NULL;
CLSID clsid;
if(!m_ObjectOne){
m_ObjectOne = new CObjectOne();
}
if (m_ObjectOne->m_lpDispatch == NULL){
CLSIDFromProgID (L"TestServ.ObjectOne", &clsid);
if (S_OK == GetActiveObject (clsid, NULL, &pUnk))
pUnk->QueryInterface (IID_IDispatch, (void**)(&pDisp));
if (pDisp)
{
// attach to running object
m_ObjectOne->AttachDispatch (pDisp);
}
else
{
// create new object
m_ObjectOne->CreateDispatch ("TestServ.ObjectOne");
}
}