WinAPI 中的菜单:我对 WM_COMMAND 使用 LPARAM 还是 WPARAM?
Menus in WinAPI: Do I use LPARAM or WPARAM for WM_COMMAND?
我最近开始自学 WinAPI,请耐心等待。
编译器:TDM-GCC 4.9.2
OS: Windows 8.1 64 位
我最近学会了如何使用资源创建菜单。关于这一点,我注意到处理菜单的 WM_COMMAND 消息有些奇怪。 MSDN documentation 告诉我,如果我想处理从菜单发送的消息,可以在 WPARAM 的低位字中找到命令项 ID;所以我假设我的 window 程序中的代码如下所示:
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 而我的 ID 实际上在 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
编辑 2015 年 7 月 23 日:
解决了。我的 window 程序有错误的签名。不敢相信这是一件如此微不足道的事情!谢谢,cremno!
WPARAM 和 LPARAM 参数在您的代码中的顺序不正确:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
来自 WindowProc callback function 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 的高位 WORD。因为此值告诉您发送消息的是菜单、加速器还是子控件。
swtich(msg)
{
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case 0: // Menu
{
// Check LOWORD(wParam) here
break;
}
}
return 0;
}
请参阅 MSDN 文档中的 table:WM_COMMAND message
我最近开始自学 WinAPI,请耐心等待。
编译器:TDM-GCC 4.9.2
OS: Windows 8.1 64 位
我最近学会了如何使用资源创建菜单。关于这一点,我注意到处理菜单的 WM_COMMAND 消息有些奇怪。 MSDN documentation 告诉我,如果我想处理从菜单发送的消息,可以在 WPARAM 的低位字中找到命令项 ID;所以我假设我的 window 程序中的代码如下所示:
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 而我的 ID 实际上在 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
编辑 2015 年 7 月 23 日:
解决了。我的 window 程序有错误的签名。不敢相信这是一件如此微不足道的事情!谢谢,cremno!
WPARAM 和 LPARAM 参数在您的代码中的顺序不正确:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
来自 WindowProc callback function 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 的高位 WORD。因为此值告诉您发送消息的是菜单、加速器还是子控件。
swtich(msg)
{
case WM_COMMAND:
{
switch(HIWORD(wParam))
{
case 0: // Menu
{
// Check LOWORD(wParam) here
break;
}
}
return 0;
}
请参阅 MSDN 文档中的 table:WM_COMMAND message