Я пытаюсь получить контекстное меню оболочки, меню не будет отображаться, так как мне нужен только HMENU, чтобы получить имя и значки пунктов меню (включая элементы в подменю).Есть много статей, рассказывающих об этом в Интернете, и после них я успешно справляюсь с большинством из них.
Предоставляя PIDL выбранного элемента и пустое HMENU, мой код может получить верхний уровеньконтекстное меню оболочки без проблем.
// Callee need to DestroyMenu(hTopMenu);
HRESULT FillContextMenuFromPIDL(LPCITEMIDLIST pidl, HMENU hTopMenu)
{
HRESULT ret = MAKE_HRESULT(SEVERITY_ERROR, 0, 0);
IContextMenu *pcm;
HRESULT hr;
IShellFolder *psf;
LPCITEMIDLIST pidlChild;
if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) {
hr = psf->GetUIObjectOf(NULL, 1, &pidlChild, IID_IContextMenu, NULL, (void**)&pcm);
// 0 was hWnd
psf->Release();
if (SUCCEEDED(hr)) {
hr = pcm->QueryContextMenu(hTopMenu, 0, 1, 0x7FFF, 0x00020490);
if (SUCCEEDED(hr)) {
IContextMenu3* hContextMenu3 = NULL;
IContextMenu2* hContextMenu2 = NULL;
if (SUCCEEDED(pcm->QueryInterface(IID_IContextMenu3, (void**)&hContextMenu3))) {
LRESULT lres;
hContextMenu3->HandleMenuMsg2(WM_INITMENUPOPUP, (WPARAM)hTopMenu, 0, &lres);
for (int pos = 0; pos < GetMenuItemCount(hTopMenu); pos++) {
HMENU subMenu = GetSubMenu(hTopMenu, pos);
if (subMenu != NULL) {
LPARAM lparam = (LPARAM)(MAKELONG(pos, FALSE));
hContextMenu3->HandleMenuMsg2(WM_INITMENUPOPUP, (WPARAM)subMenu, lparam, &lres);
}
}
//hContextMenu3->Release();
}
if (SUCCEEDED( pcm->QueryInterface(IID_IContextMenu2, (void**)&hContextMenu2) )) {
for (int pos = 0; pos < GetMenuItemCount(hTopMenu); pos++) {
HMENU subMenu = GetSubMenu(hTopMenu, pos);
if (subMenu != NULL) {
LPARAM lparam = (LPARAM)(MAKELONG(pos, FALSE));
hContextMenu2->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)subMenu, lparam);
}
}
//hContextMenu2->Release();
}
ret = MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
}
//pcm->Release();
}
}
return ret;
}
Предыдущие программисты упоминали, что для того, чтобы заставить 'Open with' и 'Send to' работать, вы должны переслать сообщение WM_INITMENUPOPUP в IContextMenu2: HandleMenuMsg и IContextMenu3: HandleMenuMsg2 вWndProc.Поскольку я не могу отобразить меню, я отправляю WM_INITMENUPOPUP этим двум интерфейсам и позволяю им добавлять динамические пункты меню.Это работает для «Открыть с помощью» и «Разрешить», но не для «Отправить».GetMenuItemCount () возвращает 1 для «Отправить».
Позже я провел эксперимент, я подключил WndProc своего рабочего стола и позволил ему отбросить все WM_INITMENUPOPUP, чтобы исходные WndProc и HandleMenuMsg не могли их видеть.«Открыть с помощью» и «Дать разрешение» перестали работать, как ожидалось, но, что интересно, пункты подменю «Отправлено» не были затронуты!Кроме того, GetMenuItemCount (HWND «Отправлено») в первом WM_INITMENUPOPUP дает 1, но дает правильное число в WM_INITMENUPOPUP «Отправлено», даже HandleMenuMsg его не получил!
Похоже на это 'Пункты меню «Отправить» добавляются после отображения меню верхнего уровня и до того, как подменю становится видимым.Есть ли обходной путь?Заранее спасибо!