IContextMenu::QueryContextMenu возвращает дополнительные элементыC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 IContextMenu::QueryContextMenu возвращает дополнительные элементы

Сообщение Anonymous »

Когда мы вызываем IContextMenu::QueryContextMenu, мы передаем ему такие аргументы, как idCmdFirst и idCmdLast. Если мы передаем 1 как idCmdFirst и 5 как idCmdLast, то, насколько я знаю, идентификаторы меню должны находиться в диапазоне от 1 до 5.
Однако тесты показывают, что, например, для текстового файла мы получаем более 5 пунктов меню, идентификаторы которых находятся за пределами диапазона [1, 5]. Почему это происходит?
Вы можете увидеть мой код ниже. Чтобы запустить этот код и отобразить меню, необходимо сделать следующее:
  • Замените значение переменной path на путь к любой папке.
  • Нажмите кнопку «Показать контекстное меню», чтобы отобразить контекстное меню.
#include
#include
#include
#include

LPCWSTR path = L"C:\\Users\\Username\\file.txt";

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(nullptr, BHID_SFUIObject, IID_PPV_ARGS(&cm));
if (cm)
{
if (FAILED(cm->QueryInterface(&_cm3)))
{
cm->QueryInterface(&_cm2);
}

auto menu = CreatePopupMenu();
const int firstId = 1;
const int lastId = 5;
cm->QueryContextMenu(menu, 0, firstId, lastId, 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);
}

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


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

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

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

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

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

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