Кнопка меню, вызывающая другое окно - PullRequest
0 голосов
/ 13 января 2020

Я новичок в c ++ и начал разбираться с Win32 GUI. Я пытаюсь заставить кнопку подменю открыть окно, в котором будет отображаться окно калькулятора, однако я не могу понять это, выполняя логические действия, и не могу найти ничего полезного в Интернете. Пожалуйста помоги! PS Он хочет, чтобы я написал более подробно, поэтому ... Я попытался использовать функцию CreateWindowW () в процедуре WM_COMMAND windows в том случае, если команда совпадает с идентификатором кнопки. Однако, хотя он все еще работает, он на самом деле ничего не делает.

#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 Ответ

1 голос
/ 13 января 2020

Ваш обработчик WM_COMMAND неправильно проверяет значение WPARAM.

LOWORD значения WPARAM содержит идентификатор элемента, отправляющего сообщение WM_COMMAND, и HIWORD содержит код уведомления, такой как BN_CLICKED, et c. Вы полностью игнорируете HIWORD. Ваш оператор 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;
}

Но, что более важно, нет вызова RegisterClassW() для класса окна "calculatorClass", например:

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" на File|New подменю. И для согласованности с вашими пунктами меню File вы должны рассмотреть переименование в BUTTON_CALCULATOR во что-то вроде TOOL_MENU_CALCULATOR. И, возможно, переименуйте ID_GO в BUTTON_GO.

...