c++winapimenuitemidentifierwm-command

Win32 API C++, Identifier not Received with WM_COMMAND


I'm a fairly new Win32 API C++ programmer.

I've just learned how to create menus and attach them Window instances. The trouble I'm having is, my MenuItem Identifiers don't seem to be sending.

For Example: My menu item File>>Exit is supposed to send the Identifier ID_FILE_EXIT in WM_COMMAND. But somewhere along the line, my MSG switch isn't receiving that identifier; ie my menu items don't work.

resouce.h:

// resources.h

#ifndef RESOURCE_H
#define RESOURCE_H

// Main Window: Menu ID
#define IDR_MAIN_MENU          101

// Main Window: Menu: Command IDs
#define ID_FILE_EXIT           101101

#define ID_PRIMITIVE_LINE      101201
#define ID_PRIMITIVE_RECTANGLE 101202
#define ID_PRIMITIVE_ELLIPSE   101203

#define ID_PENCOLOUR_BLACK     101301
#define ID_PENCOLOUR_WHITE     101302
#define ID_PENCOLOUR_RED       101303
#define ID_PENCOLOUR_GREEN     101304
#define ID_PENCOLOUR_BLUE      101305

#define ID_BRUSHCOLOUR_BLACK   101401
#define ID_BRUSHCOLOUR_WHITE   101402
#define ID_BRUSHCOLOUR_RED     101403
#define ID_BRUSHCOLOUR_GREEN   101404
#define ID_BRUSHCOLOUR_BLUE    101405

#define ID_PENSTYLE_SOLID      101501
#define ID_PENSTYLE_NULL       101502
#define ID_PENSTYLE_DOTTED     101503
#define ID_PENSTYLE_DASHED     101504

#define ID_BRUSHSTYLE_SOLID    101601
#define ID_BRUSHSTYLE_NULL     101602
#define ID_BRUSHSTYLE_DIAGONAL 101603
#define ID_BRUSHSTYLE_CROSS    101604

#endif // RESOURCE_H

resource.rc:

// resouce.rc

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"

IDR_MAIN_MENU MENU
{
    popup "File"
    {
        MENUITEM "Exit",        ID_FILE_EXIT
    }

    popup "Primitive"
    {
        MENUITEM "Line",        ID_PRIMITIVE_LINE
        MENUITEM "Rectangle",   ID_PRIMITIVE_RECTANGLE
        MENUITEM "Ellipse",     ID_PRIMITIVE_ELLIPSE
    }

    popup "Pen Colour"
    {
        MENUITEM "Black",       ID_PENCOLOUR_BLACK
        MENUITEM "White",       ID_PENCOLOUR_WHITE
        MENUITEM "Red",         ID_PENCOLOUR_RED
        MENUITEM "Green",       ID_PENCOLOUR_GREEN
        MENUITEM "Blue",        ID_PENCOLOUR_BLUE
    }

    popup "Brush Colour"
    {
        MENUITEM "Black",       ID_BRUSHCOLOUR_BLACK
        MENUITEM "White",       ID_BRUSHCOLOUR_WHITE
        MENUITEM "Red",         ID_BRUSHCOLOUR_RED
        MENUITEM "Green",       ID_BRUSHCOLOUR_GREEN
        MENUITEM "Blue",        ID_BRUSHCOLOUR_BLUE
    }

    popup "PenStyle"
    {
        MENUITEM "Solid",       ID_PENSTYLE_SOLID
        MENUITEM "Dotted",      ID_PENSTYLE_DOTTED
        MENUITEM "Dashed",      ID_PENSTYLE_DASHED
    }

    popup "Brush Style"
    {
        MENUITEM "Solid",       ID_BRUSHSTYLE_SOLID
        MENUITEM "Null",        ID_BRUSHSTYLE_NULL
        MENUITEM "Diagonal",    ID_BRUSHSTYLE_DIAGONAL
        MENUITEM "Cross",       ID_BRUSHSTYLE_CROSS
    }
}

main.cpp(extract) - msg switch statement:

...

switch(msg)
    {
    case WM_CREATE:
        CheckMenuItem(ghMainMenu, ID_PRIMITIVE_LINE, MF_CHECKED);
        CheckMenuItem(ghMainMenu, ID_PENCOLOUR_BLACK, MF_CHECKED);
        CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_BLACK, MF_CHECKED);
        CheckMenuItem(ghMainMenu, ID_PENSTYLE_SOLID, MF_CHECKED);
        CheckMenuItem(ghMainMenu, ID_BRUSHSTYLE_SOLID, MF_CHECKED);
        return 0;

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        //=====================================
        // File Menu
        //=====================================
        case ID_FILE_EXIT:
            DestroyWindow(ghMainWnd);
            return 0;

        //=====================================
        // Primitive Types (Shape Types)
        //=====================================
        case ID_PRIMITIVE_LINE:
            CheckMenuItem(ghMainMenu, ID_PRIMITIVE_LINE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPrimSel, MF_UNCHECKED);
            gCurrPrimSel = ID_PRIMITIVE_LINE;
            return 0;

        case ID_PRIMITIVE_RECTANGLE:
            CheckMenuItem(ghMainMenu, ID_PRIMITIVE_RECTANGLE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPrimSel, MF_UNCHECKED);
            gCurrPrimSel = ID_PRIMITIVE_RECTANGLE;
            return 0;

        case ID_PRIMITIVE_ELLIPSE:
            CheckMenuItem(ghMainMenu, ID_PRIMITIVE_ELLIPSE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPrimSel, MF_UNCHECKED);
            gCurrPrimSel = ID_PRIMITIVE_ELLIPSE;
            return 0;

        //=====================================
        // Pen Colours
        //=====================================
        case ID_PENCOLOUR_BLACK:
            CheckMenuItem(ghMainMenu, ID_PENCOLOUR_BLACK, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenColSel, MF_UNCHECKED);
            gCurrPenColSel    = ID_PENCOLOUR_BLACK;
            gLogPen.lopnColor = BLACK;
            return 0;

        case ID_PENCOLOUR_WHITE:
            CheckMenuItem(ghMainMenu, ID_PENCOLOUR_WHITE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenColSel, MF_UNCHECKED);
            gCurrPenColSel    = ID_PENCOLOUR_WHITE;
            gLogPen.lopnColor = BLACK;
            return 0;

        case ID_PENCOLOUR_RED:
            CheckMenuItem(ghMainMenu, ID_PENCOLOUR_RED, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenColSel, MF_UNCHECKED);
            gCurrPenColSel    = ID_PENCOLOUR_RED;
            gLogPen.lopnColor = BLACK;
            return 0;

        case ID_PENCOLOUR_GREEN:
            CheckMenuItem(ghMainMenu, ID_PENCOLOUR_GREEN, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenColSel, MF_UNCHECKED);
            gCurrPenColSel    = ID_PENCOLOUR_GREEN;
            gLogPen.lopnColor = GREEN;
            return 0;

        case ID_PENCOLOUR_BLUE:
            CheckMenuItem(ghMainMenu, ID_PENCOLOUR_BLUE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenColSel, MF_UNCHECKED);
            gCurrPenColSel    = ID_PENCOLOUR_BLUE;
            gLogPen.lopnColor = BLUE;
            return 0;

        //=====================================
        // Brush Colours
        //=====================================
        case ID_BRUSHCOLOUR_BLACK:
            CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_BLACK, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushColSel, MF_UNCHECKED);
            gCurrBrushColSel  = ID_BRUSHCOLOUR_BLACK;
            gLogBrush.lbColor = BLACK;
            return 0;

        case ID_BRUSHCOLOUR_WHITE:
            CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_WHITE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushColSel, MF_UNCHECKED);
            gCurrBrushColSel  = ID_BRUSHCOLOUR_WHITE;
            gLogBrush.lbColor = WHITE;
            return 0;

        case ID_BRUSHCOLOUR_RED:
            CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_RED, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushColSel, MF_UNCHECKED);
            gCurrBrushColSel  = ID_BRUSHCOLOUR_RED;
            gLogBrush.lbColor = RED;
            return 0;

        case ID_BRUSHCOLOUR_GREEN:
            CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_GREEN, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushColSel, MF_UNCHECKED);
            gCurrBrushColSel  = ID_BRUSHCOLOUR_GREEN;
            gLogBrush.lbColor = GREEN;
            return 0;

        case ID_BRUSHCOLOUR_BLUE:
            CheckMenuItem(ghMainMenu, ID_BRUSHCOLOUR_BLUE, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushColSel, MF_UNCHECKED);
            gCurrBrushColSel  = ID_BRUSHCOLOUR_BLUE;
            gLogBrush.lbColor = BLUE;
            return 0;

        //=====================================
        // Pen Styles
        //=====================================
        case ID_PENSTYLE_SOLID:
            CheckMenuItem(ghMainMenu, ID_PENSTYLE_SOLID, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenStyleSel, MF_UNCHECKED);
            gCurrPenStyleSel  = ID_PENSTYLE_SOLID;
            gLogPen.lopnStyle = PS_SOLID;
            return 0;

        case ID_PENSTYLE_DOTTED:
            CheckMenuItem(ghMainMenu, ID_PENSTYLE_DOTTED, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenStyleSel, MF_UNCHECKED);
            gCurrPenStyleSel = ID_PENSTYLE_DOTTED;
            gLogPen.lopnStyle = PS_DOT;
            return 0;

        case ID_PENSTYLE_DASHED:
            CheckMenuItem(ghMainMenu, ID_PENSTYLE_DASHED, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrPenStyleSel, MF_UNCHECKED);
            gCurrPenStyleSel  = ID_PENSTYLE_DASHED;
            gLogPen.lopnStyle = PS_DASH;
            return 0;

        //=====================================
        // Brush Styles
        //=====================================
        case ID_BRUSHSTYLE_SOLID:
            CheckMenuItem(ghMainMenu, ID_BRUSHSTYLE_SOLID, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushStyleSel, MF_UNCHECKED);
            gCurrBrushStyleSel = ID_BRUSHSTYLE_SOLID;
            gLogBrush.lbStyle  = BS_SOLID;
            return 0;

        case ID_BRUSHSTYLE_NULL:
            CheckMenuItem(ghMainMenu, ID_BRUSHSTYLE_NULL, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushStyleSel, MF_UNCHECKED);
            gCurrBrushStyleSel = ID_BRUSHSTYLE_NULL;
            gLogBrush.lbStyle  = BS_NULL;
            return 0;

        case ID_BRUSHSTYLE_DIAGONAL:
            CheckMenuItem(ghMainMenu, ID_BRUSHSTYLE_DIAGONAL, MF_CHECKED);
            CheckMenuItem(ghMainMenu, gCurrBrushStyleSel, MF_UNCHECKED);
            gCurrBrushStyleSel = ID_BRUSHSTYLE_DIAGONAL;
            gLogBrush.lbStyle  = BS_HATCHED;
            gLogBrush.lbHatch  = HS_CROSS;
            return 0;
        }

...

Solution

  • If you check out the documention of WM_COMMAND you find that the command id is 16 bits.

    2^16 = 65536, if memory serves.

    Thus, a value of, say, 101000, is a bit too large.


    By the way, it's generally a good idea to use the "message cracker" macros from <windowsx.h>, such as HANDLE_WM_COMMAND.

    Also, for WM_COMMAND, be sure to check whether it's a child window notification or a real menu selection.