home

Tutorial Index

GDI Tutorial 6: Menus and the Resource file

It's hard to find a program without at least a couple of menus. In this tutorial we will take a look at making what is referred to as main menus, those at the top of the window. This is mostly done in the Resource file, as the example project I am working with is GDI_Tactical, my resource file is GDI_Tactical.rc. You can see it in your Solution Explorer, but to open it you have to right click on it, and click "view code".

Take a moment to look through it. Here you define and declare some items, menus now, images in a later tutorial. You should easily spot the section that is devoted to the menus. Instead of curly brackets to declare code blocks, you use BEGIN and END keywords. The first item, and outmost, is IDC_<project name> MENU.

Within this, you will see the POPUP keyword, each of these defines an item placed horizontaly in the menu bar. Then you have a new BEGIN-END block, which contains the items shown when you expand that POPUP.

The items within that block not only have a name, but it is followed by a comma and then another uppercase word, such as IDM_EXIT, or IDM_ABOUT. These are what appears in this menu, and the uppercase word is a number that has been #defined in Resource.h. You can go straight to that point by placing the carriage on it and hitting F12, or right clicking on it and selecting "Go to definition".

To add a new menu to the horizontal bar, add another POPUP declaration. Follow it up with a BEGIN-END block and try adding in an item for that menu, along with an appropriate uppercase IDM_ label. If you do not put the comma, it will not make a difference, but you should try to stick to the norms set by the professionals. Now go to the definition of a previous IDM_ label and somewhere in the file, #define you own. Make sure you use a number that is not used elsewhere, else you cannot know what might be triggered by mistake. I used 200 and on, as I saw that everything was in the 100 range. Take note that the menu names have an ampersant (&) symbol up front, try to stick to this.

Compile and run, you should see your menu added up there. Now, let's get it to do something. To do that, I will first teach you how to change the window's name. This way we don't have to restart the program to retest it, and we can have a different effect for different selections. The command you need is SetWindowText(HWND, LPCTSTR). The HWND I have told you how to retrieve, thouth you will probably use an already locally defined variable hwnd, it is directly available in the WndProc function, and there is also one in the message processor of the About option, but that refers to the dialoguebox created when the option is selected, so you will have to use the less safe method of tutorial #5.

Now, the book I mostly learnt from is the Windows NT Win32 Api Superbible by Richard J. Simon, and it suggests the only message that most applications realy process is the WM_COMMAND message, as far as menus are concerned at any rate. Indeed if you check the code generated, you will see that it picks up the LOWORD() and HIWORD() parts of the wParam, the low word part (lower half) and high word part (correspondingly the other, upper half) of the wParam part of the message structure. After that it checks the LOWORD() part, stored and referred to as wmId, which contains the part we care about. In fact, what this contains, is the tag you see nect to MENUITEM declarations in the .rc file. Thus, all you have to do is plug in another case in the switch structure that checks for your own tag, IDM_CustomItem in my case. Then you can put your SetWindowText() command right below.

I have mentioned this in the past I believe, but chances are this is the first time you run into this, when you try to pass an LPCTSTR the compiler may complain, the problem is the L, which stands for long, the solution is to put an L prefix to your string, for example:
L"my string"

Dialogue boxes are the topic of another lesson, but since it's standing right in front of you, you may have noticed that the last parameter is, plainly, About. This refers to the callback function declared below the WndProc function, I made a short reference on callbacks in the first tutorial, now you see again how you can pass them as function parameters. These two will be referenced to in another tutorial, but I thought it would be interesting to point out. This is possible because essentialy calling a function is telling the computer that it continues from the memory address where the function is (it does of course store the current memory address), so as pointers point to an address for the code to retrieve a variable, they can, in a sense, point to an address for a program to execute. As has been stated in the past (see C tutorials), pointers are a ton of usefulthings, depending on what we need, such as arrays, but the GOTO function of the old programming days was a pointer of sorts itself.

So, with the ability to create menus, and to change the text in the title bar, plus some random knowledge on how things work under the hood, play a bit around with these and get familiar with the concepts, so as to be ready for the next tutorial. 'Till then, happy coding!