菜单按钮触发另一个窗口
Posted
技术标签:
【中文标题】菜单按钮触发另一个窗口【英文标题】:Menu button triggering another window 【发布时间】:2020-01-13 20:11:21 【问题描述】:我是 C++ 新手,已经开始了解 Win32 GUI。我试图让一个子菜单按钮打开一个窗口,该窗口将显示一个计算器窗口,但是我似乎无法通过做逻辑的事情来弄清楚它,我在网上找不到任何有用的东西。请帮忙! P.S 它希望我写更多细节,所以...我尝试在 WM_COMMAND windows 过程中使用 CreateWindowW() 函数,以防命令与按钮的 ID 相同。然而,虽然它仍然在运行,但它实际上并没有做任何事情。
#include <windows.h>
#include <iostream>
#include <fstream>
#define FILE_MENU_NEW 1
#define FILE_MENU_OPEN 2
#define FILE_MENU_EXIT 3
#define ID_GO 4
#define BUTTON_CALCULATOR 5
LRESULT CALLBACK WindowProcedure(HWND,UINT,WPARAM,LPARAM);
void AddMenus(HWND);
void AddControls(HWND);
HMENU hMenu;
HWND login;
HWND button;
HWND usernameText;
HWND passwordText;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args,int ncmdshow)
WNDCLASSW wc = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProcedure;
if(!RegisterClassW(&wc))
return -1;
CreateWindowW(L"myWindowClass",L"My Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,100,100,1000,800,NULL,NULL,NULL,NULL);
MSG msg = 0;
while(GetMessage(&msg,NULL,NULL,NULL))
TranslateMessage(&msg);
DispatchMessage(&msg);
return 0;
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
switch (msg)
case WM_COMMAND:
switch(wp)
case FILE_MENU_EXIT:
DestroyWindow(hWnd);
MessageBeep(MB_OK);
break;
case FILE_MENU_NEW:
break;
case ID_GO:
//Work in progress
wchar_t usernameInput[100];
wchar_t passwordInput[100];
GetWindowTextW(usernameText,usernameInput,100);
GetWindowTextW(passwordText,passwordInput,100);
break;
case BUTTON_CALCULATOR:
MessageBeep(MB_OK);
CreateWindowW(L"calculatorClass",L"Calculator", WS_OVERLAPPEDWINDOW | WS_VISIBLE,100,100,500,500,NULL,NULL,NULL,NULL);
break;
break;
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd,msg,wp,lp);
void AddMenus(HWND hWnd)
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hToolMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hSubMenu,MF_STRING,NULL,"Note");
AppendMenu(hFileMenu,MF_POPUP,(UINT_PTR)hSubMenu,"New");
AppendMenu(hFileMenu,MF_STRING,FILE_MENU_OPEN,"Open");
AppendMenu(hFileMenu,MF_SEPARATOR,NULL,NULL);
AppendMenu(hFileMenu,MF_STRING,FILE_MENU_EXIT,"Exit");
AppendMenu(hToolMenu,MF_STRING,BUTTON_CALCULATOR,"Calculator");
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hFileMenu,"File");
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hToolMenu,"Tools");
SetMenu(hWnd,hMenu);
void AddControls(HWND hWnd)
CreateWindowW(L"static",L"Login:",WS_VISIBLE | WS_CHILD| SS_RIGHT, 50,50,80,20,hWnd,NULL,NULL,NULL);
usernameText = CreateWindowW(L"edit",L"", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 140,50,80,20,hWnd,NULL,NULL,NULL);
CreateWindowW(L"static",L"Password:",WS_VISIBLE | WS_CHILD| SS_RIGHT, 50,90,80,20,hWnd,NULL,NULL,NULL);
passwordText = CreateWindowW(L"edit",L"", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 140,90,80,20,hWnd,NULL,NULL,NULL);
button = CreateWindowW(L"button", L"GO", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,250,65,50,30,hWnd,(HMENU)ID_GO,NULL,NULL);
【问题讨论】:
您到底遇到了什么问题?目前还不清楚真正的问题是什么。 正如描述中所述,我试图在单击菜单按钮时打开一个窗口 【参考方案1】:您的WM_COMMAND
处理程序检查WPARAM
值不正确。
WPARAM
值的 LOWORD 包含正在发送 WM_COMMAND
消息的项目的 ID,HIWORD
包含通知代码,例如BN_CLICKED
等。您忽略了@987654327 @ 完全地。您的switch(wp)
语句仅适用于HIWORD
为0 的菜单项,但不适用于HIWORD 不为0 的按钮单击等操作。您的ID_GO
控件是一个按钮,而不是菜单项,因此 wp
参数永远不会完全是 ID_GO
用于您的 switch(wp)
语句来查找 case
。
至少,您需要将switch(wp)
改为switch(LOWORD(wp))
:
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
switch (msg)
case WM_COMMAND:
switch (LOWORD(wp))
case FILE_MENU_EXIT:
DestroyWindow(hWnd);
MessageBeep(MB_OK);
break;
case FILE_MENU_NEW:
break;
case ID_GO:
//Work in progress
wchar_t usernameInput[100];
wchar_t passwordInput[100];
GetWindowTextW(usernameText,usernameInput,100);
GetWindowTextW(passwordText,passwordInput,100);
break;
case BUTTON_CALCULATOR:
MessageBeep(MB_OK);
CreateWindowW(L"calculatorClass",L"Calculator", WS_OVERLAPPEDWINDOW | WS_VISIBLE,100,100,500,500,NULL,NULL,NULL,NULL);
break;
break;
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
return 0;
但是,更重要的是,"calculatorClass"
窗口类没有调用 RegisterClassW()
,例如:
WNDCLASSW wc = 0;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"calculatorClass";
wc.lpfnWndProc = CalculatorWindowProcedure;
RegisterClassW(&wc)
您如何期望CreateWindowW()
为它不知道的类创建一个窗口?您的代码也没有检查 CreateWindowW()
调用是否失败,例如:
hCalcWnd = CreateWindowW(L"calculatorClass",L"Calculator", WS_OVERLAPPEDWINDOW | WS_VISIBLE,100,100,500,500,NULL,NULL,NULL,NULL);
if (!hCalcWnd)
DWORD err = GetLastError(); // ERROR_CLASS_DOES_NOT_EXIST, etc...
...
附带说明,您没有为"Note"
子菜单上的"Note"
项目分配ID。为了与您的File
菜单项保持一致,您应该考虑将BUTTON_CALCULATOR
重命名为TOOL_MENU_CALCULATOR
。并且可能将ID_GO
重命名为BUTTON_GO
。
【讨论】:
感谢您的回答,但我认为这不能解决问题。我的 ID_GO 不是我试图打开新窗口的按钮。我正在尝试获取菜单按钮,该按钮被归类为 (BUTTON_CALCULATOR) 以触发窗口。我尝试了建议的 HIWORD 和 LOWORD,但它只是给了我错误。我知道这对于一个不熟悉 c++ 但我迷路的人来说可能是显而易见的。 p.s 谢谢你的旁注。 究竟是什么错误?请更具体。您是否使用调试器单步执行代码以确保收到WM_COMMAND
并且 switch/case
语句正在执行您所期望的操作?您在哪里注册 "calculatorClass"
窗口类?您的代码未检查 CreateWindowW()
调用是否失败。
第一个是“duplicate case value”把我带到了“case BN_CLICKED:”
没关系,我没有意识到 BN_CLICKED
被定义为 0。不过,在检查 ID 时,您仍然应该在 switch (LOWORD(wp))
中使用 LOWORD
。我更新了我的答案以上是关于菜单按钮触发另一个窗口的主要内容,如果未能解决你的问题,请参考以下文章