Some beginner questions

1) I'm trying to make the most simple menu possible just to get started with functionality. I've written IDM_GENERICMENU in the resource file, made sure that lpszMenuName is = to it for the window structure, and defined IDM_GENERICMENU in the header file, yet I cannot get it to work. It compiles just fine, but when I run the exe, the menu isn't there. I feel like I'm a hair's breadth away from getting it to work.

2) I have read that no one ever codes using the windows API. Rather, they use cross-platform tools to allow applications to run on all operating systems. Is this true? What should I use if so? I've heard of Boost. Is that good? I usually stray away from gimmicky addons because I feel they are mostly unnecessary and take a lot of functionality away from the programmer.

3) I have spent hours trying to figure this problem with my code out to no avail. I have been reading the documentation on microsoft.com for how to create menus, but their example code is sparse. I have read a few other tutorials as well. I have looked through the sample files that came with the Windows SDK to try to replicate how they do menus, but I keep arriving at this dead end. It's clear to me that I should invest in a book. Which one should I get? I do not need a C++ book. I want one that covers menus, right-click pop up menus, adding text fields, making a child window come up for opening files, etc. Windows API related things.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//main.cpp
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance,
                    LPSTR lpszArgument, int nFunsterStil)
{
    HWND hwnd;
    MSG messages; 
    WNDCLASSEX wincl;

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof(WNDCLASSEX);
    wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wincl.lpszMenuName = MAKEINTRESOURCE(IDM_GENERICMENU);
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
    //register, create, show window
    if (!RegisterClassEx(&wincl))
        return 0;
    hwnd = CreateWindowEx(0, szClassName, "Program name here.",
			WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
			544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
    ShowWindow(hwnd, nFunsterStil);
    UpdateWindow(hwnd);




//resource.h
#define IDM_EXIT                        100
#define IDM_GENERICMENU                 101




//resource.rc
#include "resource.h"
#include "windows.h"

IDM_GENERICMENU MENU DISCARDABLE 
{
    POPUP "&File"
    {
        MENUITEM "&Exit",                       IDM_EXIT
    }
}
Last edited on
I was a beginner once Darkware and I know what its like to sweat blood to get something to work. Being as you are desperate I'm posting this as fast as I can so you can resume your happy life :) This program I found in one of my development directories and I'm like 99.999 % sure it works. There will be some stuff in here you won't understand, but just ignore that, as it isn't pertinent to menues. First Mnu01.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//Mnu01.h
#ifndef Mnu01_h
#define Mnu01_h

#define dim(x) (sizeof(x) / sizeof(x[0]))

struct WndEventArgs
{
 HWND                         hWnd;
 WPARAM                       wParam;
 LPARAM                       lParam;
 HINSTANCE                    hIns;
};

long fnWndProc_OnCreate       (WndEventArgs&);
long fnWndProc_OnDestroy      (WndEventArgs&);

struct                        EVENTHANDLER
{
 unsigned int                 iMsg;
 long                         (*fnPtr)(WndEventArgs&);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,                  fnWndProc_OnCreate},
 {WM_DESTROY,                 fnWndProc_OnDestroy}
};

#define IDR_MAIN_MENU                        2000

#define IDM_FILE_OPEN                        2100
#define IDM_FILE_EXIT                        2105

#endif 


Now the main cpp file...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Mnu01.h"


long fnWndProc_OnCreate(WndEventArgs& Wea)
{
 Wea.hIns=((LPCREATESTRUCT)Wea.lParam)->hInstance;
 return 0;
}


long fnWndProc_OnDestroy(WndEventArgs& Wea)
{
 PostQuitMessage(0);
 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Mnu01");
 WNDCLASS wc;
 MSG messages;
 HWND hWnd;

 wc.style         = 0;
 wc.lpfnWndProc   = fnWndProc;
 wc.lpszClassName = szClassName;
 wc.cbClsExtra    = 0;
 wc.cbWndExtra    = 0;
 wc.hInstance     = hIns,
 wc.hIcon         = NULL;
 wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
 wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAIN_MENU);
 RegisterClass(&wc);
 hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,200,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}


See if it works. I'll retest it again, then compare what's in it to your partial listing, and see what I can come up with. I'll answer your other questions after we get this menu stuff working!

Oh! Geeez! In my haste to post I almost forgot the rc file!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Mnu01.rc  */
#define IDR_MAIN_MENU                        2000

#define IDM_FILE_OPEN                        2100
#define IDM_FILE_EXIT                        2105

IDR_MAIN_MENU MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&Open...",      IDM_FILE_OPEN
        MENUITEM "E&xit",         IDM_FILE_EXIT
    END
END
Last edited on
What development environment are you using? What compiler? Have you included your *.rc file in the project? You are using a project, aren't you, and not trying to just compile a file???

Added Later:

So far I haven't spotted what is causing your issues. The GCC C\C++ compiler has a resource compiler that compiles the *.rc file to a *.obj and that gets linked into the exe.

The MSVC compiler has a two step process involving rc.exe >>> *.res then *.res to *.obj via cvtres.exe (convert to resources). But unless you are doing command line compiling you don't need to deal with that stuff. But in whatever development environment you are using, you really do need to include the *.rc file in the project so that the IDE can do its thing and cause the correct things to happen.
Last edited on
But if the menu thing is still eluding you - not to worry. Menus can be created programatically too. Try this...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//Main.cpp
#include <windows.h>
#include <tchar.h>
#define IDR_MAIN_MENU  2000
#define IDM_FILE_OPEN  2100
#define IDM_FILE_EXIT  2105


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
    case WM_CREATE:
     {
         HMENU hMenu    = CreateMenu();
         HMENU hSubMenu = CreatePopupMenu();
         AppendMenu(hSubMenu,  MF_STRING,            IDM_FILE_OPEN,       _T("&Open"));
         AppendMenu(hSubMenu,  MF_STRING,            IDM_FILE_EXIT,       _T("E&xit"));
         AppendMenu(hMenu,     MF_STRING | MF_POPUP, (UINT)hSubMenu,      _T("&File"));
         SetMenu(hwnd, hMenu);
         return 0;
     }
    case WM_COMMAND:
     {
         switch(LOWORD(wParam))
         {
            case IDM_FILE_OPEN:
              MessageBox(hwnd,_T("You Chose File >>> Open ..."),_T("Picked Up WM_COMMAND"),MB_OK);
              break;
            case IDM_FILE_EXIT:
              MessageBox(hwnd,_T("You Chose File >>> Exit ..."),_T("Picked Up WM_COMMAND"),MB_OK);
              SendMessage(hwnd,WM_CLOSE,0,0);
              break;
         }
         return 0;
     }
    case WM_DESTROY:
     {
         PostQuitMessage(0);
         return 0;
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Mnu05");
 WNDCLASS wc;
 MSG messages;
 HWND hWnd;

 wc.style         = 0,                         wc.lpfnWndProc   = fnWndProc;
 wc.lpszClassName = szClassName,               wc.cbClsExtra    = 0;
 wc.cbWndExtra    = 0,                         wc.hInstance     = hIns,
 wc.hIcon         = NULL,                      wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW,   wc.lpszMenuName  = NULL;
 RegisterClass(&wc);
 hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,200,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
Topic archived. No new replies allowed.