【问题标题】:Win32Api Window Menu Activating issueWin32Api 窗口菜单激活问题
【发布时间】:2021-03-03 10:24:37
【问题描述】:

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

*.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 // 
} 

【问题讨论】:

  • #define EXITMENU 3 为什么? 3 是在 winuser.h 中定义的 WM_MOVE
  • EXITMENU 不是消息。恰好匹配 WM_MOVE,不是销毁窗口的好理由。使用 WM_COMMAND 检测菜单命令。
  • 谢谢 dxiv 和 @Hans Passant,没有意识到它已经覆盖了定义的值。我会看看做 WM_COMMAND 代替。仍在尝试从整体上理解 Win32Api。

标签: c++ windows winapi win32gui win32-process


【解决方案1】:

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

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

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

About Menus: Messages Used With Menus

当用户从菜单中选择命令项时,系统会向窗口过程发送WM_COMMAND 消息。 WM_COMMAND 消息的wParam 参数的低位字包含所选项目的标识符。窗口过程应该检查标识符并相应地处理消息。

试试这个:

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 处理程序来执行该操作,而不管窗口是如何关闭的(您的退出菜单, X 关闭按钮,Alt-F4 等)。 DefWindowProc() 在处理 WM_CLOSE 时破坏了一个窗口。

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);
}

【讨论】:

猜你喜欢
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 2021-08-06
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多