【发布时间】:2021-11-02 01:38:23
【问题描述】:
概要
当在下面的行中调用CreateWindowW 时,使用AppendMenu 实例化的GUI 菜单栏消失。
CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 200, 152, 100, 50, hWnd, NULL, NULL, NULL);
对CreateWindowW 的调用会创建一个文本输入框。
以下两张图片显示了带有 (1) 和不带 (2) 注释掉上述代码行的 GUI 窗口。
代码
#include <Windows.h>
#include <sal.h>
constexpr auto FILE_DROPDOWN_ID = 1;
constexpr auto HELP_POPUP_ID = 2;
constexpr auto LOAD_DROPDOWN_ID = 3;
constexpr auto LOAD_TSD_NO_OFFSET = 4;
constexpr auto FILE_MENU_EXIT = 5;
constexpr auto CHANGE_TITLE = 6;
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);
void AddControls(HWND);
void AddMenusAndControls(HWND);
HMENU hMenu;
//int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow) {
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
//MessageBox(NULL, L"Upconverter Start up", L"Please load your file", MB_OK);
WNDCLASSW wc = { 0 };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // Define window background
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInstance;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClassW(&wc)) // Pass as reference because arg is type pointer
return -1;
CreateWindowW(L"myWindowClass", L"My Window Name", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 200, 500, 500,
NULL, NULL, NULL, NULL);
// Event driven loop
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: // Triggered for every button or menu item. Tells us that something has been clicked.
switch (wp) // This switch statement governs the resultant behavior of a button press on the main window.
{
//case FILE_DROPDOWN_ID:
//MessageBeep(MB_DEFBUTTON1);
case HELP_POPUP_ID:
MessageBeep(MB_DEFBUTTON2);
case FILE_MENU_EXIT:
DestroyWindow(hWnd);
case LOAD_DROPDOWN_ID:
MessageBeep(MB_ICONINFORMATION);
break;
case CHANGE_TITLE:
break;
}
case WM_CREATE:
//AddControls(hWnd);
//AddMenus(hWnd);
AddMenusAndControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefMDIChildProcW(hWnd, msg, wp, lp);
}
}
void AddMenusAndControls(HWND hWnd) {
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");
AppendMenu(hFileMenu, MF_STRING, LOAD_DROPDOWN_ID, L"New");
AppendMenu(hFileMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"Open Submenu");
AppendMenu(hSubMenu, MF_STRING, CHANGE_TITLE, L"Change Title");
AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_EXIT, L"Exit");
AppendMenu(hMenu, MF_STRING, HELP_POPUP_ID, L"Help");
CreateWindowW(L"static", L"Enter text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 200, 100, 100, 50, hWnd, NULL, NULL, NULL);
CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 200, 152, 100, 50, hWnd, NULL, NULL, NULL); // WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL
SetMenu(hWnd, hMenu);
}
void AddMenus(HWND hWnd) {
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hSubMenu, MF_STRING, CHANGE_TITLE, L"Change Title");
AppendMenu(hFileMenu, MF_STRING, LOAD_DROPDOWN_ID, L"New");
AppendMenu(hFileMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"Open Submenu");
AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_EXIT, L"Exit");
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");
AppendMenu(hMenu, MF_STRING, HELP_POPUP_ID, L"Help");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd) {
CreateWindowW(L"static", L"Enter text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 200, 100, 100, 50, hWnd, NULL, NULL, NULL);
CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 200, 152, 100, 50, hWnd,
NULL, NULL, NULL); // WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL
}
讨论
我怀疑这与窗口句柄 hWnd 允许覆盖窗口内容有关。所以我改变了之前两次通过hWnd
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
到单个函数调用。
case WM_CREATE:
AddMenusAndControls(hWnd);
但这没有任何效果。它也可能与SetMenu 有关,但我不确定。我尝试将SetMenu 调用移动到AddMenusAndControls 中的不同行,这也没有效果。
这是怎么回事?
感谢您的帮助。
【问题讨论】:
-
通常当使用
WS_CHILD和父 hWnd 调用CreateWindow时,您应该提供一个子 ID。确定您需要子 ID 或从 CreateWindow 返回的 hWnd 用于编辑框,否则您将无法控制它。 -
另外,您是从哪里想到为非 MDI 子窗口调用
DefMDIChildProcW的? -
你不能因为
DefMDIChildProcW而责怪教程,因为我看到它使用DefWindowProcW。但是,我强烈建议您为自己准备一个更好的教程,因为它确实会犯返回失败的错误。 Youtube 视频通常是一种学习编程的糟糕方式,因为它们只支持一种嵌入式媒体:视频。没有源代码、正确的图表等,你根本不可能有一个编程教程。 -
微软的在线文档现在很垃圾。如果你能得到一本好书来学习 Win32,你会更好。
-
我不知道有多少次报告了关于预处理器宏的所有文档都已损坏。它似乎被置若罔闻。让 .NET 人员就如何最好地为原生平台 API 创建和交付文档发表意见是一个糟糕的决定。
标签: c++ windows user-interface winapi win32gui