Sign in to follow this  
SonicD007

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

Recommended Posts

SonicD007    464
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.

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
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.

Share this post


Link to post
Share on other sites
SonicD007    464
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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this