Мне удалось получить само меню, но не могу его правильно отобразить. При попытке отобразить меню возникают следующие проблемы:
- Если я напрямую передаю hNewMenu (hNewMenu — это HMENU, полученный через QueryContextMenu) в TrackPopupMenuEx, то сам элемент под названием «Новый» не отображается, а непосредственно отображаются его дочерние элементы li>
Отображаемые пункты меню не работают (невозможно выполнить через InvokeCommand). Однако они будут работать, если вы передадите меню в TrackPopupMenuEx как GetSubMenu(hNewMenu, 0), но в этом случае, конечно, «Новое» не должно быть видно
Мой вопрос: как я могу отобразить элемент «Новый» с его дочерними элементами внутри и чтобы элементы меню могли выполняться через IContextMenu::InvokeCommand?
Вы можете увидеть мой код ниже. Чтобы запустить этот код и отобразить меню, необходимо сделать следующее:
- Замените значение переменной path на путь к любой папке.
- Нажмите кнопку «Контекстное меню», чтобы отобразить контекстное меню.
#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
Мобильная версия