HKEY_CLASSES_ROOT\Directory\Background\Shell-Kontextmenü-Handler funktionieren nicht für IContextMenu::QueryContextMenuC++

Programme in C++. Entwicklerforum
Guest
 HKEY_CLASSES_ROOT\Directory\Background\Shell-Kontextmenü-Handler funktionieren nicht für IContextMenu::QueryContextMenu

Post by Guest »

Ich versuche, mit IContextMenu::QueryContextMenu das Menü abzurufen, das angezeigt wird, wenn ich mit der rechten Maustaste auf einen leeren Bereich in einem Ordner klicke (Hintergrundmenü). Ich kann das Menü aufrufen, alle Elemente funktionieren einwandfrei, mit Ausnahme der Elemente, die hier in der Registrierung HKEY_CLASSES_ROOT\Directory\Background\shell registriert sind. Wenn ich versuche, einen Menüpunkt aus diesem Abschnitt auszuwählen, passiert nichts.
Eine der möglichen Lösungen, die ich gefunden habe, ist diese
  • Befehle aus der Registrierung analysieren
  • Verfolgen Sie das Verb des ausgewählten Befehls
  • Wenn das Verb des ausgewählten Befehls mit einem der Befehle übereinstimmt von hier HKEY_CLASSES_ROOT\Directory\Background\shell\verb\command, dann führen Sie diesen Befehl manuell mit dem Befehl aus, der in der Befehlstaste aufgezeichnet ist
Ich möchte jedoch, dass die Befehle aus dem Abschnitt HKEY_CLASSES_ROOT\Directory\Background\shell funktionieren, ohne solche Hacks zu verwenden. Wie kann ich das machen?
Um meinen Code auszuführen, ersetzen Sie den Wert der Pfadvariablen durch den Pfad zu Ihrem Ordner und klicken Sie auf die Kontextmenütaste.

Code: Select all

#include 
#include 
#include 
#include 
#include 

class Site : public IServiceProvider, public IFolderView, IOleWindow
{
HWND _hwnd;
IShellItem* _item;

public:
Site(HWND hwnd, IShellItem* item) :_hwnd(hwnd), _item(item) {}

// IUnknown
ULONG AddRef() { return 1; }
ULONG Release() { return 1; }
HRESULT QueryInterface(REFIID riid, void** ppvObject)
{
if (riid == IID_IUnknown || riid == IID_IServiceProvider)
{
*ppvObject = static_cast(this);
return S_OK;
}

if (riid == IID_IOleWindow)
{
*ppvObject = static_cast(this);
return S_OK;
}

if (riid == IID_IFolderView)
{
*ppvObject = static_cast(this);
return S_OK;
}

*ppvObject = nullptr;
return E_NOINTERFACE;
}

// IServiceProvider, defer services calls to this QI
HRESULT QueryService(REFGUID guidService, REFIID riid, void** ppvObject) { return QueryInterface(riid, ppvObject); }

// IOleWindow
HRESULT GetWindow(HWND* phwnd) { *phwnd = _hwnd; return S_OK; }
HRESULT ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; }

// IFolderView
HRESULT GetCurrentViewMode(UINT* pViewMode) { return E_NOTIMPL; }
HRESULT SetCurrentViewMode(UINT ViewMode) { return E_NOTIMPL; }
HRESULT GetFolder(REFIID riid, void** ppv) { return E_NOTIMPL; }
HRESULT Item(int iItemIndex, PITEMID_CHILD* ppidl) { return E_NOTIMPL; }
HRESULT ItemCount(UINT uFlags, int* pcItems) { return E_NOTIMPL; }
HRESULT Items(UINT uFlags, REFIID riid, void** ppv)
{
if (riid == IID_IShellItemArray)
return SHCreateShellItemArrayFromShellItem(_item, riid, ppv);

*ppv = nullptr;
return E_NOTIMPL;
}

HRESULT GetSelectionMarkedItem(int* piItem) { return E_NOTIMPL; }
HRESULT GetFocusedItem(int* piItem) { return E_NOTIMPL; }
HRESULT GetItemPosition(PCUITEMID_CHILD pidl, POINT* ppt) { return E_NOTIMPL; }
HRESULT GetSpacing(POINT* ppt) { return E_NOTIMPL; }
HRESULT GetDefaultSpacing(POINT* ppt) { return E_NOTIMPL; }
HRESULT GetAutoArrange() { return E_NOTIMPL; }
HRESULT SelectItem(int iItem, DWORD dwFlags) { return E_NOTIMPL; }
HRESULT SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT* apt, DWORD dwFlags) { return E_NOTIMPL; }
};

LPCWSTR path = L"C:\\Users\\Username\\Desktop\\folder";

IContextMenu2* _cm2 = nullptr;
IContextMenu3* _cm3 = nullptr;

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (_cm3)
{
LRESULT lr = 0;
if (SUCCEEDED(_cm3->HandleMenuMsg2(message, wParam, lParam, &lr)))
return lr;
}
else if (_cm2)
{
if (SUCCEEDED(_cm2->HandleMenuMsg(message, wParam, lParam)))
return 0;
}

const int buttonId = 1;
const int buttonX = 10;
const int buttonY = 10;
switch (message)
{
case WM_CREATE:
CreateWindow(L"BUTTON", L"Show Context menu", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, buttonX, buttonY, 200, 30, hwnd, (HMENU)(long)buttonId, nullptr, nullptr);
break;

case WM_COMMAND:
if (LOWORD(wParam) == buttonId)
{
IShellItem* item;
IBindCtx* ctx;
CreateBindCtx(0, &ctx);  // use a binding context to avoid the shell to be too smart and get back wrong items
SHCreateItemFromParsingName(path, ctx, IID_PPV_ARGS(&item));
//ctx->Release();
if (item)
{
IContextMenu* cm;
item->BindToHandler(ctx, BHID_SFViewObject, IID_PPV_ARGS(&cm));
if (cm)
{
if (FAILED(cm->QueryInterface(&_cm3)))
{
cm->QueryInterface(&_cm2);
}

// pass site to enable some menu items properly like "share"
Site site{ hwnd, item };
IObjectWithSite* ows;
cm->QueryInterface(&ows);
if (ows)
{
ows->SetSite(static_cast(&site));
}

auto menu = CreatePopupMenu();
const int firstId = 1;

cm->QueryContextMenu(menu, 0, firstId, 0x7FFF, CMF_NORMAL); // remove some flags if not needed
POINT pt{ buttonX, buttonY };
ClientToScreen(hwnd, &pt);
auto cmd = TrackPopupMenu(menu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, nullptr);
if (cmd)
{
CMINVOKECOMMANDINFO cmi{};
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
cmi.lpVerb = (LPSTR)MAKEINTRESOURCE(cmd - firstId);
cmi.nShow = SW_SHOWNORMAL;
cm->InvokeCommand(&cmi);
}

if (ows)
{
ows->SetSite(nullptr);
}

cm->Release();
DestroyMenu(menu);

if (_cm2)
{
_cm2->Release();
_cm2 = nullptr;
}

if (_cm3)
{
_cm3->Release();
_cm3 = nullptr;
}
}
item->Release();
}
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
auto hmod = LoadLibrary(L"shell32.dll");
auto fileIconInit = (BOOL(WINAPI*)(BOOL))GetProcAddress(hmod, MAKEINTRESOURCEA(660));
if (fileIconInit)
{
fileIconInit(TRUE);
}

WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"MyWindowClass";
RegisterClass(&wc);

auto hwnd = CreateWindow(wc.lpszClassName, L"Context Menu", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post