Home | Step1 | Step2 | Step3 | Step4 | Step5 |
Adding a menu |
You have to add 2 files to you project. One file is called Step2.rc . The rc means "resource". Here you add your menuitems, dialogs, accelerator keys and stringtables etc. The other is a header file. It is handy when you need to share necessary information among source files. Here we use the file resource.h to define constants used in Step2.rc.
Things changed from Step1 on
Yellow background.Source for step2 here.
#include <windows.h> #include "resource.h" /* Declare Windows procedure */ LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); void HandleMenu (HWND hwnd, UINT Command); /* Make the class name into a global variable */ char szClassName[ ] = "WindowsApp"; HWND hWndMain; /* This is the handle for our window - Moved from WinMain*/ int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int cmdShow) { MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ HMENU hMenu; /* Handle for the menu */ HACCEL hAccKeys; /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); wincl.hIcon = LoadIcon (hThisInstance, MAKEINTRESOURCE (IDI_GCM)); // Get the icon from the resource wincl.hIconSm = LoadIcon (hThisInstance, MAKEINTRESOURCE (IDI_GCM)); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ /* Use Windows's default color as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hWndMain = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "GcmWin", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Load the menu */ hMenu = LoadMenu (hThisInstance, "MAINMENU"); SetMenu (hWndMain, hMenu); /* Load accelerator keys (ex. Ctrl-N) */ hAccKeys = LoadAccelerators (hThisInstance, "IDR_ACCKEYS"); /* Make the window visible on the screen */ ShowWindow (hWndMain, cmdShow); /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { if (!TranslateAccelerator(hWndMain, hAccKeys, &messages)) { TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; } /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) /* handle the messages */ { case WM_COMMAND: HandleMenu (hwnd, LOWORD (wParam)); // Handle messages in a separate function break; case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; } void HandleMenu (HWND hwnd, UINT Command) { switch (Command) { case IDM_NEW: MessageBox (NULL, "New Map", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_SAVEBMP: MessageBox (NULL, "Save Bitmap", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_SAVEBMPAS: MessageBox (NULL, "Save Bitmap AS", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_OPTIONS: MessageBox (NULL, "Options", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_DXPOS: MessageBox (NULL, "DxPos", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_ABOUT: MessageBox (NULL, "About", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_HELP: MessageBox (NULL, "Help", "Menu", MB_OK | MB_ICONINFORMATION); break; case IDM_EXIT: PostQuitMessage (0); break; } return; }
Well, a little bit nicer. Menu works ok and launches a messagebox indicating wich menu you clicked. The icon and Window name is changed. |
Below is the code for the new files.
resource.h
#define IDB_TOOL 60 #define IDI_GCM 120 #define IDR_TOOLB 800 #define IDR_STATUS 900 #define IDM_NEW 10001 #define IDM_SAVEBMP 10002 #define IDM_SAVEBMPAS 10003 #define IDM_EXIT 10005 #define IDM_OPTIONS 10006 #define IDM_DXPOS 10007 #define IDM_ABOUT 10008 #define IDM_HELP 10009
step2.rc
#include <windows.h> #include "resource.h" IDI_GCM ICON "gcmw.ico" IDR_ACCKEYS ACCELERATORS DISCARDABLE BEGIN "N", IDM_NEW, VIRTKEY, CONTROL, NOINVERT "X", IDM_EXIT, VIRTKEY, CONTROL, NOINVERT "H", IDM_HELP, VIRTKEY, CONTROL, NOINVERT END MAINMENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "&New Map (Ctrl+N)",IDM_NEW MENUITEM SEPARATOR MENUITEM "&Save Bitmap",IDM_SAVEBMP MENUITEM "Save Bitmap &As",IDM_SAVEBMPAS MENUITEM SEPARATOR MENUITEM "&Exit (Ctrl+X)",IDM_EXIT END MENUITEM "&Options", IDM_OPTIONS MENUITEM "&DxPos" , IDM_DXPOS POPUP "&Help" BEGIN MENUITEM "&Help (Ctrl+H)", IDM_HELP MENUITEM SEPARATOR MENUITEM "About &GcmWin ", IDM_ABOUT END END