Пишу shell extension (по руководству Michael Dunn, но без ATL), которое должно добавлять пункты в контекстное меню explorer-а. Реализовал интерфейсы IShellExtInit и IContextMenu, однако Windows упорно отказывается запрашивать интерфейс IContextMenu.
Кроме того, компонент по-разному ведет себя при вызове меню на рабочем столе и в окне explorer-a. Если, вызывая контекстное меню на рабочем столе, система по крайней мере вызывает метод IShellExtInit::Initialize, то при вызове из explorer-а не происходит даже этого! Класс просто создается, а потом разрушается.
Подскажите, пожалуйста, возможные причины. Заренее благодарен.
Windows XP SP2, Visual C++ .NET.
class CShellExt : public IShellExtInit, public IContextMenu
{
protected:
long m_lRef;
public:
CShellExt();
~CShellExt();
public:
// IUnknown
STDMETHOD(QueryInterface(REFIID, void**));
STDMETHOD_(ULONG, AddRef());
STDMETHOD_(ULONG, Release());
// IShellExtInit
STDMETHOD(Initialize(LPCITEMIDLIST, IDataObject*, HKEY));
//IContextMenu
STDMETHOD(GetCommandString(UINT, UINT, UINT *, LPSTR, UINT));
STDMETHOD(InvokeCommand(LPCMINVOKECOMMANDINFO));
STDMETHOD(QueryContextMenu(HMENU, UINT, UINT, UINT, UINT));
};
CShellExt::CShellExt()
{
m_lRef = 0;
InterlockedIncrement(&g_lObjs);
}
CShellExt::~CShellExt()
{
InterlockedDecrement(&g_lObjs);
}
STDMETHODIMP CShellExt::QueryInterface(REFIID riid, void** ppv)
{
*ppv = 0;
if (riid == IID_IUnknown || riid == IID_IShellExtInit || riid == IID_IContextMenu){
*ppv = this;
AddRef();
return(S_OK);
}
return (E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CShellExt::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
STDMETHODIMP_(ULONG) CShellExt::Release()
{
if (InterlockedDecrement(&m_lRef) == 0){
delete this;
return 0;
}
return m_lRef;
}
STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pDataObj, HKEY hProgID)
{
MessageBox(NULL, L"Initialize", L"", MB_OK);
return S_OK;
}
STDMETHODIMP CShellExt::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags)
{
MessageBox(NULL, L"QueryContextMenu", L"", MB_OK);
return S_OK;
}
STDMETHODIMP CShellExt::GetCommandString(UINT idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax)
{
MessageBox(NULL, L"GetCommandString", L"", MB_OK);
return S_OK;
}
STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo)
{
MessageBox(NULL, L"InvokeCommand", L"", MB_OK);
return S_OK;
}