Это в действительности не пример реального моникера, а его имитация. А ещё вернее, создание пространства имён. В моём случае — пространства monv:хххх.
Делаете обычный ATL проект (у меня
monv), добавляете простой ATL объект (у меня
Manager, т.е. CManager, IManager и т.п.). И делаете косметику в классе и фабрике класса. Для моих целей класс не играет роли, он может быть реально действующим, но я использую
только фабрику класса. Фактически ничего более и не надо.
В
Manager.rgs файле, чтобы иметь короткое имя
monv вместо
monv.manager,
...
Monv = s 'Manager Moniker Class'
{
CLSID = s 'такое же как у Monv.Manager'
}
Monv.Manager = s 'Manager Class'
...
В
Manager.h файле изменяем CManager и добавляем CComClassFactoryMoniker
class ATL_NO_VTABLE CManager :
...
{
...
DECLARE_CLASSFACTORY_EX(CComClassFactoryMoniker<CManager>)
...
};
И в начало этого файла добиваете определение фабрики класса
template <class T>
class CComClassFactoryMoniker : public CComClassFactory,
public IParseDisplayName
{
public:
BEGIN_COM_MAP(CComClassFactoryMoniker)
COM_INTERFACE_ENTRY(IClassFactory)
COM_INTERFACE_ENTRY(IParseDisplayName)
END_COM_MAP()
//IParseDisplayName
STDMETHOD(ParseDisplayName)( /*[in]*/ IBindCtx* pbc, /*[in]*/ LPOLESTR pszDisplayName,
/*[out]*/ ULONG* pchEaten, /*[out]*/ IMoniker* *ppmkOut)
{
if( !ppmkOut || !pchEaten )
return E_POINTER;
HRESULT hr = MK_E_NOOBJECT;
ppmkOut[0] = NULL;
LPOLESTR psz1 = wcschr(pszDisplayName,':')+1; // It's always here
pchEaten[0] = wcslen(pszDisplayName);
if( psz1[0] == '{' ) // "{CLSID}"
{
// Использование техники моникеров
if( 0 ) // 0 или 1 - выбирайте, какая нравится. Соотвественно, другой код можно выбросить
{
CComPtr<IMoniker> pmk;
hr = CreateItemMoniker( L"!", psz1, &pmk ); // Создаём моникер !{CLSID}
hr = pmk->IsRunning(pbc,NULL,NULL);
if( hr == S_OK )
{
CComPtr<IRunningObjectTable> pROT;
hr = pbc->GetRunningObjectTable( &pROT );
CComPtr<IUnknown> pObj;
hr = pROT->GetObject( pmk, &pObj );
// Here it can be used the CreateObjrefMoniker, but I don't have it
hr = CreatePointerMoniker( pObj, ppmkOut );
}
else
hr = MK_E_NOOBJECT;
}
// Использование функции GetActiveObject
else
{
CLSID clsid;
hr = CLSIDFromString(psz1, &clsid);
if( hr == S_OK )
{
CComPtr<IUnknown> pObj;
hr = GetActiveObject(clsid, NULL, &pObj);
// Here it can be used the CreateObjrefMoniker, but I don't have it
hr = CreatePointerMoniker( pObj, ppmkOut );
}
else
hr = MK_E_NOOBJECT;
}
}
else // Здесь можно добавить дополнительные обработки - задавать через ProgID и т.п.
hr = MK_E_UNAVAILABLE;
return hr;
}
};
Использование: "monv:{CLSID}" или "monv.manager:{CLSID}". Например, для запущенного Excel "monv:{00024500-0000-0000-C000-000000000046}". Извращение, конечно, но для демонстрации же. Вот пример на VB для поднятия этого Excel.
Private Sub Form_Load()
Dim v
Set v = GetObject("monv:{00024500-0000-0000-C000-000000000046}")
Unload Me
End Sub