Bug in popup menu (checkmarks) C++ win api

Started by
3 comments, last by SonicD007 14 years ago
Hi, I'm trying to learn the windows api and so far things have been going pretty well. I've been figuring things out and learning more when I have time. Recently I was trying to use a windows menu to control the score limit of a Pong Clone I'm going to attempt making using c++ and the windows api. Here's what I have for the menu part:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static int iSelection = ID_GAMEPOINT_10;
	HMENU hMenu;
    switch(msg)
    {
		case WM_COMMAND:
			hMenu = GetMenu(hwnd);
			switch(LOWORD(wParam))
			{
				case ID_FILE_NEWGAME:
					NewGame();
					break;

				case ID_FILE_PAUSE:
					(g_bPause==true) ? (g_bPause=false) : (g_bPause=true);  //Pause game if unpaused, unpause if paused
					break;

				case ID_FILE_EXIT:
					PostMessage(hwnd, WM_CLOSE, 0, 0);
					break;

				case ID_GAMEPOINT_5:
					{
						CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
						iSelection = LOWORD (wParam);
						CheckMenuItem(hMenu, iSelection, MF_CHECKED);
						if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)
							g_iScoreLimit = 5;
					}
					break;

				case ID_GAMEPOINT_10:
					{
						CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
						iSelection = LOWORD (wParam);
						CheckMenuItem(hMenu, iSelection, MF_CHECKED);
						if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)
							g_iScoreLimit = 10;
					}
					break;

				case ID_GAMEPOINT_15:
					{
						CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
						iSelection = LOWORD (wParam);
						CheckMenuItem(hMenu, iSelection, MF_CHECKED);
						if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)
							g_iScoreLimit = 15;
					}
					break;

				case ID_GAMEPOINT_20:
					{
						CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
						iSelection = LOWORD (wParam);
						CheckMenuItem(hMenu, iSelection, MF_CHECKED);
						if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)
							g_iScoreLimit = 20;
					}
					break;

				case ID_HELP_HOWTOPLAY:
					DialogBox(GetModuleHandle(NULL), 
							MAKEINTRESOURCE(IDD_HOWTOPLAY), hwnd, AboutDlgProc);
				break;

				case ID_HELP_ABOUT:
					MessageBox(hwnd,"Pong Game created by ", "About", MB_OK);
				break;
			}
		 break;
		case WM_KEYDOWN:
			switch(wParam)
				{
				case W:
					g_bMoveUp[0] = true;
					break;//this is where the boolean var would go to move up

				case S:
					g_bMoveDown[0] = true;
					break;//this is where the boolean var would go to move down

				case VK_UP:
					g_bMoveUp[1] = true;
					break;//this is where the boolean var would go to move up

				case VK_DOWN:
					g_bMoveDown[1] = true;
					break;//this is where the boolean var would go to move down

				case VK_SPACE:
					g_bBallMove = true;
					break;

				case P:
					(g_bPause==true) ? (g_bPause=false) : (g_bPause=true);
					break;
				}
			break;

		case WM_KEYUP:
			switch(wParam)
				{
				case W:
					g_bMoveUp[0] = false;
					break;//this is where the boolean var would go to move up

				case S:
					g_bMoveDown[0] = false;
					break;//this is where the boolean var would go to move down

				case VK_UP:
					g_bMoveUp[1] = false;
					break;//this is where the boolean var would go to move up

				case VK_DOWN:
					g_bMoveDown[1] = false;
					break;//this is where the boolean var would go to move down
			}
			break;

        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
        break;

        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}	//end of wind proc

My code compiles and all, but when I click another menu item like Game->ScoreLimit->15, instead of check marking the menu item with 15 and unchecking the previous checked menu, it will check more than one menu and at times it doesn't do anything. I'm not sure where the bug is and I'm not very keen on using a debugger. Any help would be appreciated. Thanks. If you need any more code I'll post the rest.
Advertisement
In CheckMenuItem I believe you must use MF_BYCOMMAND | MF_CHECKED for example, to tell the API you specify menu item by command ID.
Checked the docs and MF_BYCOMMAND is default, so scratch that.
Also, I was trying to find out why it wasn't working in the code above and created another project just to test out the menus, and for some reason it works in this code but not in the above.
#include <windows.h>#include "resource.h"const char g_szClassName[] = "myWindowClass";LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){	HMENU hMenu;	static int iSelection = ID_SCORELIMIT_10;    switch(msg)    {		case WM_COMMAND:			hMenu = GetMenu(hwnd);			switch (LOWORD(wParam))			{			case ID_SCORELIMIT_5:				CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);				iSelection = LOWORD (wParam);				CheckMenuItem(hMenu, iSelection, MF_CHECKED);				if (GetMenuState(hMenu, iSelection, MF_BYCOMMAND) == MF_CHECKED)					MessageBox(hwnd, "test", "Works", MB_OK);				break;			case ID_SCORELIMIT_10:				CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);				iSelection = LOWORD (wParam);				CheckMenuItem(hMenu, iSelection, MF_CHECKED);				break;			case ID_SCORELIMIT_15:				CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);				iSelection = LOWORD (wParam);				CheckMenuItem(hMenu, iSelection, MF_CHECKED);				break;			case ID_SCORELIMIT_20:				CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);				iSelection = LOWORD (wParam);				CheckMenuItem(hMenu, iSelection, MF_CHECKED);				break;			}			break;        case WM_CLOSE:            DestroyWindow(hwnd);        break;        case WM_DESTROY:            PostQuitMessage(0);        break;        default:            return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,    LPSTR lpCmdLine, int nCmdShow){    WNDCLASSEX wc;    HWND hwnd;    MSG Msg;    wc.cbSize        = sizeof(WNDCLASSEX);    wc.style         = 0;    wc.lpfnWndProc   = WndProc;    wc.cbClsExtra    = 0;    wc.cbWndExtra    = 0;    wc.hInstance     = hInstance;    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU1);    wc.lpszClassName = g_szClassName;    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);    if(!RegisterClassEx(&wc))    {        MessageBox(NULL, "Window Registration Failed!", "Error!",            MB_ICONEXCLAMATION | MB_OK);        return 0;    }    hwnd = CreateWindowEx(        WS_EX_CLIENTEDGE,        g_szClassName,        "The title of my window",        WS_OVERLAPPEDWINDOW,        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,        NULL, NULL, hInstance, NULL);    if(hwnd == NULL)    {        MessageBox(NULL, "Window Creation Failed!", "Error!",            MB_ICONEXCLAMATION | MB_OK);        return 0;    }    ShowWindow(hwnd, nCmdShow);    UpdateWindow(hwnd);    while(GetMessage(&Msg, NULL, 0, 0) > 0)    {        TranslateMessage(&Msg);        DispatchMessage(&Msg);    }    return Msg.wParam;}


Any ideas why it works here and not up there?
In the project in which it's not working, if you put break points in all the menu command handlers, is the correct handler getting called for a given menu selection?
There we go! One of my menus had the wrong ID. Everything works now :) Thanks a lot.

This topic is closed to new replies.

Advertisement