IEXPLORECOMMAND -Kontextmenü mit Submenus gibt leeres iShellItemArray für den Hintergrund des Verzeichnisses zurück. KliC++

Programme in C++. Entwicklerforum
Anonymous
 IEXPLORECOMMAND -Kontextmenü mit Submenus gibt leeres iShellItemArray für den Hintergrund des Verzeichnisses zurück. Kli

Post by Anonymous »

Ich habe einen Kontextmenü -Handler implementiert, basierend auf dem Beispiel von Microsoft, das IEXploreCommand . Modernes und klassisches Kontextmenü. Es gibt also kein Problem mit meinem MSIX-Paket oder meiner Datei von AppxManMest.xml. Verwenden Sie das klassische Kontextmenü. Es funktioniert korrekt, wenn das moderne Kontextmenü verwendet wird. Klassisches oder modernes Kontextmenü. Es ist nur leer, wenn das Kontextmenü einen oder mehrere Untermenüs im klassischen Kontextmenü enthält. Beachten Sie auch, dass die rechte Klicken Sie mit der rechten Maustaste auf Dateien und Ordner, die IShellItemArray wie erwartet bevölkern, unabhängig davon, ob es Untermenüs gibt oder nicht. />

Code: Select all

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

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post