Я реализовал обработчик контекстных меню, основанный на примере Microsoft здесь, в котором используется iexploreCommand .
Код отображает контекстное меню, с подменом, просто отлично с Windows 11 Современное и классическое контекстное меню. Таким образом, нет проблем с моим пакетом MSIX или с моим файлом appxmanifest.xml.
Проблема в том, что iShelliTemarray пуст, когда пользователь щелкнет правой кнопкой мыши на фоне каталога, когда Использование классического контекстного меню. Он работает правильно при использовании современного контекстного меню. Классическое или современное контекстное меню. Это только пусто, когда в контекстном меню есть одна или несколько подменга в классическом контекстном меню. Также обратите внимание, что щелкните правой кнопкой мыши по файлам и папкам по-прежнему популярны IshelliTemarray, как и ожидалось, независимо от того, есть ли подменга />#include "pch.h"
#include
#include
#include
#include
using namespace Microsoft::WRL;
HMODULE g_hModule = nullptr;
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hModule = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
class SubCommand : public RuntimeClass
{
public:
SubCommand(PCWSTR title, PCWSTR icon, PCWSTR command) :
m_title(title), m_icon(icon), m_command(command) {
}
IFACEMETHODIMP GetTitle(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* name)
{
*name = nullptr;
auto title = wil::make_cotaskmem_string_nothrow(m_title);
RETURN_IF_NULL_ALLOC(title);
*name = title.release();
return S_OK;
}
IFACEMETHODIMP GetIcon(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* iconPath)
{
*iconPath = nullptr;
return E_NOTIMPL;
}
IFACEMETHODIMP GetToolTip(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* infoTip) { *infoTip = nullptr; return E_NOTIMPL; }
IFACEMETHODIMP GetCanonicalName(_Out_ GUID* guidCommandName) { *guidCommandName = GUID_NULL; return S_OK; }
IFACEMETHODIMP GetState(_In_opt_ IShellItemArray* selection, _In_ BOOL okToBeSlow, _Out_ EXPCMDSTATE* cmdState)
{
*cmdState = ECS_ENABLED;
return S_OK;
}
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
{
// If user right-clicks a file or folder, the selected item is in the array
// If user right-clicks the background, the array is empty
try
{
DWORD count = 0;
if (selection)
{
RETURN_IF_FAILED(selection->GetCount(&count));
}
if (count > 0)
{
ComPtr item;
RETURN_IF_FAILED(selection->GetItemAt(0, &item));
PWSTR filePath;
RETURN_IF_FAILED(item->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
wil::unique_cotaskmem_string filePathCleanup(filePath);
WCHAR message[100];
StringCchPrintfW(message, ARRAYSIZE(message), L"First item: %s", filePath);
MessageBox(nullptr, message, L"Debug", MB_OK);
}
else
{
MessageBox(nullptr, L"No items selected", L"Debug", MB_OK);
}
return S_OK;
}
catch (...)
{
return E_FAIL;
}
}
IFACEMETHODIMP GetFlags(_Out_ EXPCMDFLAGS* flags) { *flags = ECF_DEFAULT; return S_OK; }
IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands) { *enumCommands = nullptr; return E_NOTIMPL; }
private:
PCWSTR m_title;
PCWSTR m_icon;
PCWSTR m_command;
};
class SubCommandEnum : public RuntimeClass
{
public:
SubCommandEnum()
{
m_commands.push_back(Make(L"SubmenuTest", L"SubmenuTest.ico", L"SubmenuTest"));
}
IFACEMETHODIMP Next(ULONG celt, IExplorerCommand** pUICommand, ULONG* pceltFetched)
{
ULONG fetched = 0;
while (fetched < celt && m_index < m_commands.size())
{
pUICommand[fetched] = m_commands[m_index].Get();
pUICommand[fetched]->AddRef();
++fetched;
++m_index;
}
if (pceltFetched)
{
*pceltFetched = fetched;
}
return (fetched == celt) ? S_OK : S_FALSE;
}
IFACEMETHODIMP Skip(ULONG celt)
{
m_index += celt;
return (m_index < m_commands.size()) ? S_OK : S_FALSE;
}
IFACEMETHODIMP Reset()
{
m_index = 0;
return S_OK;
}
IFACEMETHODIMP Clone(IEnumExplorerCommand** ppenum)
{
auto clone = Make();
clone->m_index = m_index;
*ppenum = clone.Detach();
return S_OK;
}
private:
std::vector m_commands;
size_t m_index = 0;
};
class __declspec(uuid("8A0E292E-E857-424B-9457-EC5377D0DCFD")) ContextMenuHandler : public RuntimeClass
{
public:
IFACEMETHODIMP GetTitle(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* name)
{
*name = nullptr;
auto title = wil::make_cotaskmem_string_nothrow(L"ExplorerHelper");
RETURN_IF_NULL_ALLOC(title);
*name = title.release();
return S_OK;
}
IFACEMETHODIMP GetIcon(_In_opt_ IShellItemArray* items, _Outptr_result_nullonfailure_ PWSTR* iconPath)
{
*iconPath = nullptr;
return E_NOTIMPL;
}
IFACEMETHODIMP GetToolTip(_In_opt_ IShellItemArray*, _Outptr_result_nullonfailure_ PWSTR* infoTip) { *infoTip = nullptr; return E_NOTIMPL; }
IFACEMETHODIMP GetCanonicalName(_Out_ GUID* guidCommandName) { *guidCommandName = GUID_NULL; return S_OK; }
IFACEMETHODIMP GetState(_In_opt_ IShellItemArray* selection, _In_ BOOL okToBeSlow, _Out_ EXPCMDSTATE* cmdState)
{
*cmdState = ECS_ENABLED;
return S_OK;
}
IFACEMETHODIMP Invoke(_In_opt_ IShellItemArray* selection, _In_opt_ IBindCtx*) noexcept
{
// Any code added here no longer runs now that we have a submenu
return S_OK;
}
IFACEMETHODIMP GetFlags(_Out_ EXPCMDFLAGS* flags) { *flags = ECF_HASSUBCOMMANDS; return S_OK; }
IFACEMETHODIMP EnumSubCommands(_COM_Outptr_ IEnumExplorerCommand** enumCommands)
{
*enumCommands = Make().Detach();
return S_OK;
}
IFACEMETHODIMP SetSite(_In_ IUnknown* site) noexcept { m_site = site; return S_OK; }
IFACEMETHODIMP GetSite(_In_ REFIID riid, _COM_Outptr_ void** site) noexcept { return m_site.CopyTo(riid, site); }
protected:
ComPtr m_site;
};
CoCreatableClass(ContextMenuHandler)
STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory)
{
return Module::GetModule().GetActivationFactory(activatableClassId, factory);
}
_Use_decl_annotations_
STDAPI DllCanUnloadNow(void)
{
return Module::GetModule().GetObjectCount() == 0 ? S_OK : S_FALSE;
}
_Use_decl_annotations_
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** instance)
{
return Module::GetModule().GetClassObject(rclsid, riid, instance);
}
Подробнее здесь: https://stackoverflow.com/questions/794 ... ay-for-dir
Контекстное меню iExploreCommand с подменем возвращает пустой ishelliTemarray для фона каталогов Нажмите с помощью класс ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение