我正在尝试学习一些基本的 win32 api。我看到向菜单栏添加项目教程提到使用类似的东西:
hMenubar = CreateMenu();
hMenu = CreateMenu();
AppendMenuW(hMenu, MF_STRING, IDM_FILE_NEW, L"&New");
AppendMenuW(hMenu, MF_STRING, IDM_FILE_OPEN, L"&Open");
AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenuW(hMenu, MF_STRING, IDM_FILE_QUIT, L"&Quit");
AppendMenuW(hMenubar, MF_POPUP, (UINT_PTR)hMenu, L"&File");
但是在 VS2013 的 C++ Desktop 的默认项目中,有一个“文件”和“帮助”菜单栏,里面有“退出”和“关于”。但他们所做的只是在 WndProc 中有一个像这样的开关:
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
我有几个问题。他们是如何在不使用 createmenu() 等的情况下添加文件和帮助菜单栏以及菜单栏中的 about 和 exit 项目的? IDM_ABOUT 和 IDM_EXIT 是什么意思?它们在菜单中都有,但是只要将它们放入 switch 语句中就可以将它们添加到菜单栏中吗?什么是 wmId 和 wmEvent?为什么要在 wmId 上切换?实际上是什么将这些项目添加到菜单栏?
如果您需要查看我的程序的更多代码,它只是 VS2013 中的非空白 C++ Win32 项目
感谢您提供的任何答案,如果有人能给我指出当前尽可能好的 win32 api C++ 教程,我将不胜感激。
制作菜单有两种方法。它可以像您所展示的那样以编程方式完成,也可以使用资源编辑器完成。在解决方案资源管理器中,双击扩展名为 *.rc 的文件。您应该看到一个名为“资源视图”的窗口。打开资源节点,直到看到“菜单”。您可以添加/修改/删除菜单项。您还可以制作对话框。
每个菜单项或对话框按钮都有一个标识号,这个号码通过
WPARAM wParam
传递。上面的例子中没有使用wmEvent
,暂时不用担心。
IDM_ABOUT
是资源文件 #define IDM_ABOUT 101
中定义的数字(或者可能是不同的数字)。单击菜单项时,会发送一条带有该号码的消息。您可以捕捉消息并回复它。
这是基本的 WinApi,在过去 10 或 20 年里没有太大变化,你在 Google 上找到的任何教程都是最新的。
此外,当您使用资源编辑器创建新菜单项时,Visual Studio 会自动创建一个 ID 并将其分配给该菜单项。您需要知道这些 ID 是什么。您可以通过按 F4 键来找到“属性窗口”。
例如,如果您输入新菜单项“&File New”,则该菜单的 ID 将类似于
ID_FILE_NEWFILE
,应在“属性窗口”中可见。
这个菜单项就像
IDM_ABOUT
一样。它被发送到与该窗口关联的 Windows 过程函数。
对于菜单项消息:
message
始终设置为 WM_COMMAND
wParam
是菜单IDlParam
未使用简单回顾一下,一旦有了 hMenubar,您就可以使用 SetMenu 和 DrawMenu 将其设置在窗口上
::SetMenu(hWnd, hMenuBar);
::DrawMenu(hWnd);
此时,Windows 将向您发送有关菜单的消息。这些,您在 Windows 过程中的处理与示例中所示完全相同,但这次您使用在构建菜单时提供的 ID 来了解选择了哪个菜单。
为了完整起见,我将从上面的示例中重述这一点。
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
希望有帮助。