添加文本输入窗口时WIN32GUI菜单栏不呈现

问题描述 投票:0回答:2

剧情简介

当在下面的行中调用

AppendMenu
时,使用
CreateWindowW
实例化的 GUI 菜单栏会消失。

CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 200, 152, 100, 50, hWnd, NULL, NULL, NULL);

CreateWindowW
的调用会创建一个文本输入框。

以下两张图显示了 GUI 窗口,其中 (1) 和 (2) 没有注释掉上述代码行。

不冒犯 CreateWindowW 调用的 GUI:

带有违规 CreateWindowW 调用的 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
中的不同行,但这也没有效果。

这是怎么回事?

感谢您的帮助。

c++ windows user-interface winapi win32gui
2个回答
2
投票

你的窗口程序被严重破坏了。它具有非 void 返回类型,但到达末尾时不会沿除

default:
之外的所有路径返回任何内容。

窗口过程的正确结构是在函数末尾无条件地调用默认窗口过程。任何不应传递给默认窗口过程的消息都需要通过

case
(并指定返回值)而不是
return
退出其
break

改变

case WM_DESTROY:
    PostQuitMessage(0);
    break;
default:
    return DefMDIChildProcW(hWnd, msg, wp, lp);
}

case WM_DESTROY:
    PostQuitMessage(0);
    break;
}
return DefWindowProcW(hWnd, msg, wp, lp);

我还修复了您对要调用的默认窗口过程的选择,因为您的 WinMain 似乎将此窗口用作顶级框架,而不是 MDI 子窗口。 因为当焦点更改时,MDI 子控件会自动将其菜单迁移到 MDI 父控件,并且因为您要添加一个能够接收焦点的新子控件(在框架获得焦点之前),所以很可能发送与焦点相关的消息到你的窗口更改,并且由于你尽职尽责地转发了它们,你得到了你所要求的 MDI 菜单行为(即使你不想要它)。如果您没有 MDI,请勿使用

DefMDIChildProcW

    


0
投票

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; } break; ///THIS WAS CAUSING ERROR ADD THIS BREAK; case WM_CREATE: //AddControls(hWnd); //AddMenus(hWnd); AddMenusAndControls(hWnd); break;

© www.soinside.com 2019 - 2024. All rights reserved.