IContextMenu::QueryContextMenu 未被 Shell 调用 (Win10)
IContextMenu::QueryContextMenu not called by Shell (Win10)
我有一个名为 ValidatorContextMenuHandler
的 class,它实现了 IShellExtInit
和 IContextMenu
接口。
注册表中引用了我的 DLL,并正确加载到 Windows 资源管理器中。每当调用方法时,我都会通过创建 MessageBoxes 来检查这一点。当我右键单击一个文件时,我还会收到有关我的 ContextMenuHandler
正在实例化的通知。所以, IShellExtInit::Initialize()
确实被调用了(实际上是两次)。我对 IShellExtInit::Initialize()
的实现如下所示:
IFACEMETHODIMP ValidatorContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hKeyProgID)
{
MessageBox(NULL, L"ContextMenuHandler Initialized!", L"Notice", MB_OK);
return S_OK;
}
然而,在那之后什么也没有发生。 IContextMenu::QueryContextMenu()
从未被调用,我找不到原因。 QueryContextMenu()
的第一行应该显示一个 MessageBox,但它一开始就没有达到这一点。
我的方法实现如下所示:
STDMETHODIMP ValidatorContextMenuHandler::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
MessageBox(NULL, L"QUERYING CONTEXT MENU", L"ValidatorContextMenuHandler::QueryContextMenu()", MB_OK);
//...Removed the unnecessary code after this, so that the post doesn't get too long
}
没有编译错误,我测试的DLL是最新版本(用regsvr32 /u
卸载DLL,重新启动Windows Explorer,用regsvr32
加载DLL)。
对于那些想看我的头文件的人:
#pragma once
#include<Windows.h>
#include<ShlObj.h>
extern UINT g_cObjCount;
class ValidatorContextMenuHandler : public IShellExtInit, IContextMenu
{
protected:
DWORD m_ObjRefCount;
~ValidatorContextMenuHandler();
public:
ValidatorContextMenuHandler();
//IUnknown Methods
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
//IShellExtInit Methods
IFACEMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hKeyProgID);
//IContextMenu Methods
IFACEMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
};
我发现了它不起作用的原因。白白受挫。
在我的 ValidatorContextMenuHandler.cpp
文件中,我犯了一个简单的错误。当查询 IContextMenu
接口时,我不小心将 this
转换为 IClassFactory
而我应该将其转换为 IContextMenu
。打错了。
之前:
else if (IsEqualIID(riid, IID_IContextMenu))
{
*ppvObject = (IClassFactory*)this;
this->AddRef();
return S_OK;
}
之后:
else if (IsEqualIID(riid, IID_IContextMenu))
{
*ppvObject = (IContextMenu*)this;
this->AddRef();
return S_OK;
}
我有一个名为 ValidatorContextMenuHandler
的 class,它实现了 IShellExtInit
和 IContextMenu
接口。
注册表中引用了我的 DLL,并正确加载到 Windows 资源管理器中。每当调用方法时,我都会通过创建 MessageBoxes 来检查这一点。当我右键单击一个文件时,我还会收到有关我的 ContextMenuHandler
正在实例化的通知。所以, IShellExtInit::Initialize()
确实被调用了(实际上是两次)。我对 IShellExtInit::Initialize()
的实现如下所示:
IFACEMETHODIMP ValidatorContextMenuHandler::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hKeyProgID)
{
MessageBox(NULL, L"ContextMenuHandler Initialized!", L"Notice", MB_OK);
return S_OK;
}
然而,在那之后什么也没有发生。 IContextMenu::QueryContextMenu()
从未被调用,我找不到原因。 QueryContextMenu()
的第一行应该显示一个 MessageBox,但它一开始就没有达到这一点。
我的方法实现如下所示:
STDMETHODIMP ValidatorContextMenuHandler::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
MessageBox(NULL, L"QUERYING CONTEXT MENU", L"ValidatorContextMenuHandler::QueryContextMenu()", MB_OK);
//...Removed the unnecessary code after this, so that the post doesn't get too long
}
没有编译错误,我测试的DLL是最新版本(用regsvr32 /u
卸载DLL,重新启动Windows Explorer,用regsvr32
加载DLL)。
对于那些想看我的头文件的人:
#pragma once
#include<Windows.h>
#include<ShlObj.h>
extern UINT g_cObjCount;
class ValidatorContextMenuHandler : public IShellExtInit, IContextMenu
{
protected:
DWORD m_ObjRefCount;
~ValidatorContextMenuHandler();
public:
ValidatorContextMenuHandler();
//IUnknown Methods
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
//IShellExtInit Methods
IFACEMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hKeyProgID);
//IContextMenu Methods
IFACEMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
};
我发现了它不起作用的原因。白白受挫。
在我的 ValidatorContextMenuHandler.cpp
文件中,我犯了一个简单的错误。当查询 IContextMenu
接口时,我不小心将 this
转换为 IClassFactory
而我应该将其转换为 IContextMenu
。打错了。
之前:
else if (IsEqualIID(riid, IID_IContextMenu))
{
*ppvObject = (IClassFactory*)this;
this->AddRef();
return S_OK;
}
之后:
else if (IsEqualIID(riid, IID_IContextMenu))
{
*ppvObject = (IContextMenu*)this;
this->AddRef();
return S_OK;
}