Win32Api Window 菜单激活问题

Win32Api Window Menu Activating issue

运行 我的程序它 运行s 并且由于我有一个带有 EXIT 的菜单来销毁 window 它 运行s 并立即退出 window.不确定如何在编译程序时解决我的问题,使其不是 运行 WindowProcedure 函数并传递导致 Window 被破坏的参数 EXITMENU。

*.CPP

#include <windows.h>
#define HELPMENU 1
#define HIGHSCROREMENU 2
#define EXITMENU 3

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow) {
    WNDCLASS wc = { 0 }; // WNDCLASSW is a structure
    LPCWSTR title = L"Window"; // Long Pointer Constant Wide (UTF-16) String 

    wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // Background
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_HAND); // Sets Cursor
    wc.hInstance = hInst; // Instance of window
    wc.lpszClassName = L"windowClass"; // Class name
    wc.lpfnWndProc = WindowProcedure; // Pointer to the function // Controller of window handle

    if (!RegisterClassW(&wc)) { // Registers the window class
        return -1;
    }

    //                                                   | binary combination value, posX, posY, Width, Height

    // Creates the window
    CreateWindow(wc.lpszClassName, title, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_BORDER, 100, 100, 800, 600, NULL, NULL, NULL, NULL);

    MSG msg = { 0 };


    while (GetMessage(&msg, NULL, NULL, NULL) > 0) { // Keeps the window running
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

/* Event Paths */
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_CREATE: // On window creation
        AddControls(hWnd);
        AddMenu(hWnd);
        break;
    case WM_LBUTTONDOWN: // Left Mouse button
        break;
    case WM_DESTROY: // Makes GetMessage Function return false, closing the window
        PostQuitMessage(0);
        return 0;
    case EXITMENU:
        DestroyWindow(hWnd); // This part of the code shouldn't run on creation
        break;
    default:
        return DefWindowProc(hWnd, msg, wp, lp);
    }
}

/* Creates menu */
void AddMenu(HWND hWnd) {
    hMenu = CreateMenu(); // Creates menu object
    // AppendMenu(Menu Instance, Usage Type, Argument, String info);
    AppendMenu(hMenu, MF_STRING, HELPMENU, L"Help - F1");
    AppendMenu(hMenu, MF_STRING, HIGHSCROREMENU, L"Highscores - F2"); // Menu Created
    AppendMenu(hMenu, MF_STRING, EXITMENU, L"Exit - ESC");
    // SetMenu(Window Handle , Menu Instance);
    SetMenu(hWnd, hMenu); // Sets menu for window // 
} 

您没有正确处理 WindowProcedure() 中的菜单命令。

您已将 EXITMENU 定义为 3,与 WM_MOVE 消息的值相同。因此,在您的 switch 中,您在 window 创建期间一收到 WM_MOVE 消息就销毁了 window。

根据文档,您需要通过 WM_COMMAND 消息来处理菜单命令:

About Menus: Messages Used With Menus

When the user chooses a command item from a menu, the system sends a WM_COMMAND message to the window procedure. The low-order word of the WM_COMMAND message's wParam parameter contains the identifier of the chosen item. The window procedure should examine the identifier and process the message accordingly.

试试这个:

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
        ...
        case WM_COMMAND:
            switch (wp) {
                case HELPMENU: {
                    ...
                    return 0;
                }
                case HIGHSCROREMENU: {
                    ...
                    return 0;
                }
                case EXITMENU: {
                    DestroyWindow(hWnd);
                    return 0;
                }
            }
            break;
        }
        ...
    }

    return DefWindowProc(hWnd, msg, wp, lp);
}

更新: 也就是说,考虑让您的 EXITMENU 处理程序使用 SendMessage(WM_CLOSE) 而不是 DestroyWindow()。如果您的应用保留在用户关闭应用时应保存的数据,您可以添加一个 WM_CLOSE 处理程序来执行该操作,而不管 如何 window 正在关闭(您的退出菜单、X 关闭按钮、Alt-F4 等)。 DefWindowProc() 在处理 WM_CLOSE 时销毁一个 window。

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
        ...
        case WM_CLOSE: {
            if (data has been modified) {
                prompt user to save data...
                if (cancelled) {
                    return 0;
                }
                if (should save) {
                    save data ...
                }
            }
            break;
        }

        case WM_COMMAND:
            switch (wp) {
                ...
                case EXITMENU: {
                    SendMessage(hWnd, WM_CLOSE, 0, 0);
                    return 0;
                }
            }
            break;
        }
        ...
    }

    return DefWindowProc(hWnd, msg, wp, lp);
}