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);
}
运行 我的程序它 运行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 theWM_COMMAND
message'swParam
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);
}