Отображать пункты меню, полученные непосредственно из расширения оболочки.C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Отображать пункты меню, полученные непосредственно из расширения оболочки.

Сообщение Anonymous »

Для отображения меню я использую функцию TrackPopupMenuEx. Меню, которое я хочу отобразить, я получаю непосредственно из расширения оболочки. Это меню для пункта «Новое» (HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers\New), которое отображается в фоновом контекстном меню папки.
Мне удалось получить само меню, но не могу его правильно отобразить. При попытке отобразить меню возникают следующие проблемы:
  • Если я напрямую передаю hNewMenu (hNewMenu — это HMENU, полученный через QueryContextMenu) в TrackPopupMenuEx, то сам элемент под названием «Новый» не отображается, а непосредственно отображаются его дочерние элементы li>
    Отображаемые пункты меню не работают (невозможно выполнить через InvokeCommand). Однако они будут работать, если вы передадите меню в TrackPopupMenuEx как GetSubMenu(hNewMenu, 0), но в этом случае, конечно, «Новое» не должно быть видно
Я пытался создать новое меню hRootMenu с корневым элементом «Новый», в котором элементы из GetSubMenu(hNewMenu, 0) может быть помещены как дети. Однако это не сработало, добавленный вручную родительский элемент «Новый» по-прежнему не отображается, а вместо него напрямую отображаются подменю из «Нового».
Мой вопрос: как я могу отобразить элемент «Новый» с его дочерними элементами внутри и чтобы элементы меню могли выполняться через IContextMenu::InvokeCommand?
Вы можете увидеть мой код ниже. Чтобы запустить этот код и отобразить меню, необходимо сделать следующее:
  • Замените значение переменной path на путь к любой папке.
  • Нажмите кнопку «Контекстное меню», чтобы отобразить контекстное меню.
#include
#include
#include

HINSTANCE hInst;

IContextMenu2* cm2;
IContextMenu3* cm3;
const wchar_t* path = L"C:\\Users\\Username\\Desktop\\folder";

bool UpdateContextMenu(LPCONTEXTMENU icm1, void** ppContextMenu)
{
*ppContextMenu = NULL;

if (icm1)
{ // since we got an IContextMenu interface we can
// now obtain the higher version interfaces via that
if (SUCCEEDED(icm1->QueryInterface(IID_IContextMenu3, ppContextMenu))) {
cm3 = (LPCONTEXTMENU3)*ppContextMenu;
}
else if (SUCCEEDED(icm1->QueryInterface(IID_IContextMenu2, ppContextMenu))) {
cm2 = (LPCONTEXTMENU2)*ppContextMenu;
}

if (*ppContextMenu) {
icm1->Release(); // we can now release version 1 interface,
// cause we got a higher one
}
else {
*ppContextMenu = icm1; // since no higher versions were found
} // redirect ppContextMenu to version 1 interface
}
else
return false; // something went wrong

return true; // success
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

if (cm3) {
LRESULT res;

if (SUCCEEDED(cm3->HandleMenuMsg2(message, wParam, lParam, &res))) {
return res;
}
}
else if (cm2) {
if (SUCCEEDED(cm2->HandleMenuMsg(message, wParam, lParam))) {
return 0;
}
}

switch (message) {

case WM_CREATE: {
CreateWindowA(
"BUTTON", "Context menu",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
100, 100, 100, 30,
hWnd, (HMENU)1, hInst, nullptr);
break;
}
case WM_COMMAND: {

if (LOWORD(wParam) == 1) {
LPITEMIDLIST pidl;

SFGAOF sfgao;
if (SUCCEEDED(SHParseDisplayName(path, NULL, &pidl, 0, &sfgao))) {
IShellFolder* psf;
LPCITEMIDLIST pidlChild;

if (SUCCEEDED(SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) {
psf->Release();
}
}

IContextMenu* outPcm = nullptr;

CLSID clsid2;
CLSIDFromString(L"{D969A300-E7FF-11d0-A93B-00A0C90F2719}", &clsid2); // CLSID_NewMenu

const int SCRATCH_QCM_FIRST = 1;
const int SCRATCH_QCM_LAST = 0x7FFF;

IShellExtInit* shExtInit;
if (SUCCEEDED(CoCreateInstance(clsid2, NULL, CLSCTX_INPROC_SERVER, IID_IShellExtInit, (LPVOID*)&shExtInit))) {
if (SUCCEEDED(shExtInit->Initialize(pidl, NULL, NULL))) {
IContextMenu* cm = NULL;
if (SUCCEEDED(shExtInit->QueryInterface(IID_IContextMenu, (void**)&cm))) {
UpdateContextMenu(cm, (void**)&outPcm);
HMENU hNewMenu = CreatePopupMenu();
HMENU hRootMenu = CreatePopupMenu();

if (SUCCEEDED(outPcm->QueryContextMenu(hNewMenu, 0, SCRATCH_QCM_FIRST, SCRATCH_QCM_LAST, CMF_NORMAL))) {
AppendMenu(hRootMenu, MF_STRING | MF_POPUP, (UINT_PTR)GetSubMenu(hNewMenu, 0), L"New");

int idCmd = TrackPopupMenuEx(hRootMenu, TPM_RETURNCMD, 100, 100, (HWND)hWnd, NULL);
CMINVOKECOMMANDINFO cmi = { 0 };
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
cmi.lpVerb = (LPSTR)MAKEINTRESOURCE(idCmd - SCRATCH_QCM_FIRST);
cmi.nShow = SW_SHOWNORMAL;
HRESULT hr = outPcm->InvokeCommand(&cmi);
if (!SUCCEEDED(hr)) {
std::stringstream ss;
ss

Подробнее здесь: https://stackoverflow.com/questions/793 ... -extension
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»