【问题标题】:IContextMenu::QueryContextMenu not called by Shell (Win10)Shell 未调用 IContextMenu::QueryContextMenu (Win10)
【发布时间】:2021-09-15 09:31:23
【问题描述】:

我有一个名为ValidatorContextMenuHandler 的类,它实现了IShellExtInitIContextMenu 接口。

我的 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是最新版本(卸载DLLregsvr32 /u,重启Windows资源管理器,加载DLLregsvr32)。

对于那些想查看我的头文件的人:

#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); 
};

【问题讨论】:

  • 什么版本的 Windows?
  • 版本:Windows 10 Pro 版本:2004 Build:19041.1165

标签: c++ shell winapi contextmenu shell-extensions


【解决方案1】:

我发现了它为什么不起作用。很多挫败感都是徒劳的。

在我的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;
}

【讨论】:

  • 这就是为什么 C++ 中的 C 风格转换是危险的。您应该始终使用 C++ 风格的强制转换。如果您使用了static_cast&lt;IClassFactory*&gt;(this),那么您的原始代码将无法编译,因为您的类不是从IClassFactory 派生的,因此无法将this 转换为它。 C++ 强制转换执行 C 强制转换不执行的验证。
  • 朋友不要让朋友在没有 ATL 的 COM 中编程。
猜你喜欢
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
  • 2020-03-27
相关资源
最近更新 更多