Меню в WinAPI: я использую LPARAM или WPARAM для WM_COMMAND?
Я недавно начал учить себя WinAPI, так что терпите меня здесь.
Компилятор: TDM-GCC 4.9.2
ОС: Windows 8.1 64-битная
Недавно я научился создавать меню с использованием ресурсов. В связи с этим я заметил кое-что странное в обработке сообщения WM_COMMAND для меню. Документация MSDN говорит мне, что если я хочу обработать сообщение, отправленное из меню, идентификатор элемента команды можно найти в младшем слове WPARAM; поэтому я предположил, что код в моей оконной процедуре будет выглядеть так:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
{
switch (msg)
{
case WM_COMMAND:
switch (LOWORD(wParam)) //<--
{
case /*IDs go here*/:
break;
}
break;
//...
}
return 0;
}
Однако я заметил, что пункты команд в меню не работают. После некоторой отладки я обнаружил, что wParam всегда был 0, а мои идентификаторы были в lParam! Я сделал быстрое изменение следующего кода:
switch (lParam)
{
case /*IDs go here*/:
break;
}
И это работает!
Мой вопрос: почему?
Почему в документации говорится, что она в wParam, а для меня - в lParam?
Также, вот мои файлы resource.rc и resource.h на случай, если это поможет:
"Resource.h":
#define IDR_MYMENU 101
//These are appearing in LPARAM instead of WPARAM
#define ID_FILE_EXIT 9001
#define ID_STUFF_GO 9002
"Resource.rc":
#include "resource.h"
IDR_MYMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Stuff"
BEGIN
MENUITEM "&Go", ID_STUFF_GO
MENUITEM "G&o somewhere else", 0, GRAYED
END
END
Изменить 23.07.15:
Решаемые. Моя процедура окна имела неправильную подпись. Не могу поверить, что это было так тривиально! Спасибо, кремно!
2 ответа
Параметры WPARAM и LPARAM находятся в неправильном порядке в вашем коде:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
Из функции обратного вызова WindowProc в документации MSDN:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Просто поменяйте их местами, чтобы исправить ваш код:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Ваша обработка сообщений WM_COMMAND должна сначала проверить старшее слово wParam. Потому что это значение указывает, отправляет ли сообщение меню, ускоритель или дочерний элемент управления.
swtich(msg)
{
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case 0: // Menu
{
// Check LOWORD(wParam) here
break;
}
}
return 0;
}
Смотрите таблицу в документации MSDN: сообщение WM_COMMAND