| ||
Menus also can be specified in resource files. Like dialogs, menus in programs are identified by their names (strings). Menus can be specified both in normal windows and in dialogs. For a normal window, when registering a class, it is sufficient to replace the following string:
MOV DWORD PTR [WC.CLMENNAME], 0
Replace this string with the following:
MOV DWORD PTR [WC.CLMENNAME], OFFSET MENS
Here, MENS is the name assigned to the menu in the resource file.
For dialogs, menus are set using another method, which, naturally, is also suitable for a normal window. First, the menu is loaded using the LoadMenu function; then, it is set using the setMenu function.
Now, consider this in more detail. Consider the structure of the resource file containing a menu definition. Here is the text of the file containing a menu definition:
MENUP MENU { POPUP "&First item" { MENUITEM "&First", 1 MENUITEM "S&econd", 2 POPUP "Subme&nu" { MENUITEM "Tent&h item", 6 } } POPUP "&Second item" { MENUITEM "Th&ird", 3 MENUITEM "F&ourth", 4 } MENUITEM "E&xit", 5 }
Carefully look at the menu text. As you can see, menu items have identifiers that the program can use to determine which menu item was chosen . Also note that a drop-down menu can contain a submenu.
Listing 9.3 provides an example of a program that demonstrates the use of a menu with a dialog box.
// The MENU.RC file // Definitions of constants #define WS_SYSMENU 0x00080000L #define WS_MINIMIZEBOX 0x00020000L #define WS_MAXIMIZEBOX 0x000l0000L #define WS_POPUP 0x80000000L #define WS_CAPTION 0x00C00000L MENUP MENU { POPUP "&First item" { MENUITEM "&", 1 MENUITEM "&Second", 2 } POPUP "&Second item" { MENUITEM "& Third", 3 MENUITEM "F&ourth", 4 POPUP "Another sub&menu" { MENUITEM "Te&nth subitem", 6 } } MENUITEM "E&xit", 5 } // Identifiers #define IDI_ICON1 100 // Defining the icon IDI_ICON1 ICON "ico1.ico" // Defining the dialog box DIAL1 DIALOG 0, 0, 240, 120 STYLE WS_POPUP WS_CAPTION WS_SYSMENU WS_MINIMIZEBOX WS_MAXIMIZEBOX CAPTION "An example dialog box" FONT 8, "Arial" { } ; The MENU.INC file ; Constants ; The message arrives when the window is closed WM_CLOSE equ 10h WM_INITDIALOG equ 110h WM_SETICON equ 80h WM_COMMAND equ 111h ; Prototypes of external procedures EXTERN MessageBoxA@16:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN LoadStringA@16:NEAR EXTERN LoadIconA@8:NEAR EXTERN LoadMenuA@8:NEAR EXTERN SendMessageA@16:NEAR EXTERN SetMenu@8:NEAR ; Structures ; Message structure MSGSTRUCT STRUC MSHWND DD ? MSMESSAGE DD ? MSWPARAM DD ? MSLPARAM DD ? MSTIME DD ? MSPT DD ? MSGSTRUCT ENDS ; The MENU.ASM file .586P ; Flat memory model .MODEL FLAT, stdcall include menu.inc ; INCLUDELIB directives for the linker includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;------------------------------------------- ; Data segment _DATA SEGMENT MSG MSGSTRUCT <?> HINST DD 0 ; Application descriptor PA DB "DIAL1", 0 PMENU DB "MENUP", 0 STR1 DB "Exit the program", 0 STR2 DB "Message", 0 _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the application descriptor PUSH 0 CALL GetModuleHandleA@4 MOV [HINST],' EAX ;----------------------------- PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX, -1 JNE KOL KOL: PUSH 0 CALL ExitProcess@4 ; Window procedure ; Parameter positions in the stack ; [EBP+014H] LPARAM ; [EBP+10H] WAPARAM ; [EBP+0CH] MES ; [EBP+8] HWND WNDPROC PROC PUSH EBP MOV EBP, ESP PUSH EBX PUSH ESI PUSH EDI ;------------------------- CMP DWORD PTR [EBP+0CH], WM_CLOSE JNE L1 ; Close the dialog PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH], WM_INITDIALOG JNE L2 ; Load the icon PUSH 100 ; Icon identifier PUSH [HINST]; Process identifier CALL LoadIconA@8 ; Set the icon PUSH EAX PUSH 0 ; Icon type (small) PUSH WM_SETICON PUSH DWORD PTR [EBP+08H] CALL SendMessageA@16 ; Load the menu PUSH OFFSET PMENU PUSH [HINST] CALL LoadMenuA@8 ; Set the menu PUSH EAX PUSH DWORD PTR [EBP+08H] CALL SetMenu@8 JMP FINISH L2: ; Checking whether something has happened to the ; controls in the dialog ; In this case, there is only one ; control --- the menu CMP DWORD PTR [EBP+0CH], WM_COMMAND JNE FINISH ; Determining the identifier ; In this case, this is the menu item identifier CMP WORD PTR [EBP+10H], 5 JNE FINISH ; Message PUSH 0 ; MB_OK PUSH OFFSET STR2 PUSH OFFSET STR1 PUSH 0 CALL MessageBoxA@16 ; Close the dialog PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 FINISH: MOV EAX, 0 POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START
It is necessary to provide a small comment about the program from Listing 9.3. First, pay attention to the transparent analogy between the dialog and the menu. In both cases, the resource is defined by its name instead of its identifier. Furthermore, both the dialog and the menu contain elements defined by identifiers, which have been specified in the resource file and placed into the least significant word of the WPARAM parameter.
In Listing 9.3, you load the menu programmatically. It is possible to use a different approach: Specify the menu in dialog options as follows :
// Dialog definition DIAL1 DIALOG 0, 0, 240, 120 STYLE WS_POPUP WS_CAPTION WS_SYSMENU WS_MINIMIZEBOX WS_MAXIMIZEBOX MENU MENUP CAPTION "Dialog example" FONT 8, "Arial" { }
This is sufficient to automatically load and display the menu.
Recall that in Chapter 3 an example was provided, in which a button was created as a child window. The event related to clicking this button was identified by the content of the LPARAM of the button descriptor. As you can see, the element of the dialog can be identified both by the resource descriptor and by the resource identifier.
Now, return to the menu. Menu items can contain additional parameters that define additional properties of those items. The resource compiler recognizes the following properties:
CHECKED The item is selected with a check mark.
GRAYED The element is unavailable (and displayed in gray).
HELP The element has an associated help string. Resource editors create an additional string resource. The string identifier matches that of the menu item.
MENUBARBREAK For a horizontal menu item, this means that starting from it, all further horizontal menu items are located in a new line. For a vertical item, this means that all further items start from a new column. The items are separated by a line delimiter .
MENUBREAK This is similar to the previous property, but no separating line is present.
INACTIVE This menu item doesn't work.
SEPARATOR This item creates a separator in the menu but doesn't provide an identifier.
To conclude the menu description, I'll note that Windows provides a range of functions that can be used to change menu properties (e.g., to add or remove items or to modify their properties). In the next chapter, I'll provide several examples of functions from this group .
| ||