// Create a menu system with cascading menus
// Also: add a menu system to any window
// NOTE: CA-dBFast cannot determine on which window
//  a menu item was selected.  Therefore, do not create
//  a menu system on more than one window, or make sure
//  that the ID numbers are different.
// See the Windows SDK for more information.

// Windows API function calls
declare pfunc CreateMenu returning integer in dll user.exe
declare pfunc CreatePopupMenu returning integer in dll user.exe
declare pfunc AppendMenu returning integer in dll user.exe
declare pfunc SetMenu returning integer in dll user.exe
declare pfunc FindWindow returning integer in dll user.exe
// Must use DestroyMenu if the menu is attached to a CREATE WINDOW
// otherwise system resources will be lost.
declare pfunc DestroyMenu returning integer in dll user.exe
declare pfunc ModifyMenu returning integer in dll user.exe
declare pfunc DeleteMenu returning integer in dll user.exe
declare pfunc EnableMenuItem returning integer in dll user.exe
declare pfunc DrawMenuBar returning integer in dll user.exe

#define MF_STRING		0
#define MF_POPUP		16
#define MF_SEPARATOR	2048

// Changes that can be made to menu items with ModifyMenu
// Note: MF_ENABLED and MF_UNCHECKED are both zero.
// Therefore, if a checked itemed is grayed, then it will have to be 
// checked again when enabled.
#define MF_ENABLED		0
#define MF_GRAYED		1
#define MF_UNCHECKED	0
#define MF_CHECKED		8

#define MF_BYPOSITION	1024

// identification numbers for the menu items
#define IDM_FILE		100
#define IDM_OPEN		101
#define IDM_SAVE		102
#define IDM_SAVEFILE	150
#define IDM_SAVEPREFS	151
#define IDM_EXIT		103
#define IDM_NEW			104

#define IDM_EDIT		201

// Get the window handle for CA-dBFast itself.
// 'CA-dBFast' can be replaced by a linked apps window name
// The 'tolong(0)' is used to pass a NULL to the function
// so it looks through all classes
//hWnd = FindWindow(tolong(0), 'CA-dBFast')

// OPTION: create a window. See NOTE at the top of this file
create window 'Window 1' from 2,2 to 20,40
// Get window handle of 'Window 1'
hWnd = HWND()

// handle to the popup 
hPopup = CreatePopupMenu()

// Add menu items to the popup
// Note: the "&" is to add an underscore to the menu item
// It must be in quotes by itself, or CA-dBFast will interpret it as a macro
// Also use chr(9) to use a TAB; used to align the accelerators
AppendMenu(toint(hPopup), toint(MF_STRING), toint(IDM_OPEN), "&"+"Open"+chr(9)+"Ctrl+O")

// handle to the cascaded popup 
hPopup2 = CreatePopupMenu()

// Add the items to the cascaded popup
AppendMenu(toint(hPopup2), toint(MF_STRING), toint(IDM_SAVEFILE), "Save "+"&"+"File")
AppendMenu(toint(hPopup2), toint(MF_STRING), toint(IDM_SAVEPREFS), "Save "+"&"+"Preferences")

// Get the menu handle to the main menu
hMenu = CreateMenu()

// Add the menu items to the main menu
AppendMenu(toint(hMenu), toint(MF_POPUP), toint(hPopup), "&"+"File")
AppendMenu(toint(hPopup), toint(MF_STRING), toint(IDM_NEW), "&"+"New")
AppendMenu(toint(hPopup), toint(MF_SEPARATOR), toint(0), tolong(0))
AppendMenu(toint(hPopup), toint(MF_POPUP), toint(hPopup2), "&"+"Save")
AppendMenu(toint(hPopup), toint(MF_SEPARATOR), toint(0), tolong(0))
AppendMenu(toint(hPopup), toint(MF_STRING), toint(IDM_EXIT), "E"+"&"+"xit")
AppendMenu(toint(hMenu), toint(MF_STRING), toint(IDM_EDIT), "&"+"Edit")

// Set the menu to the window
SetMenu(toint(hWnd), toint(hMenu))

// run until the user hits ESC
do while lastkey() <> 27
	nEvent = chkevent()
	do while nEvent = -1
		nEvent = chkevent()
	enddo
	
	// if user event of menu...
	if (nEvent = 2)
		// hmenu() will return the horizontal menu selected
		? HMENU()
		// vmenu() will return the last 2 digits of the ID number
		? VMENU()
	endif
enddo

// Gray the cascade menu, which is at position 3 (0 based) including
// the separator.
? EnableMenuItem(toint(hPopup), toint(3), toint(MF_BYPOSITION+MF_GRAYED))
// Or gray the first item (0 based) in the cascade.
//? EnableMenuItem(toint(hPopup2), toint(0), toint(MF_BYPOSITION+MF_GRAYED))

// Use DrawMenuBar() to force the immediate update of the menu bar.
// Useful when graying a top level item.
//? EnableMenuItem(toint(hMenu), toint(0), toint(MF_BYPOSITION+MF_GRAYED))
//DrawMenuBar(toint(hWnd))
wait

// Check/uncheck, enable/disable, change the contents of a menu item
// ModifyMenu returns zero if the command failed
// Parms: menu handle, item ID, change to be made, item ID, new (or maybe not) item text
? ModifyMenu(toint(hMenu), toint(IDM_EXIT), toint(MF_CHECKED), toint(IDM_EXIT), "E"+"&"+"xit now checked")
wait

// delete a menu item
DeleteMenu(toint(hMenu), toint(IDM_OPEN), toint(0))

wait

// Only needed if menu is attached to a CREATE WINDOW
//DestroyMenu(toint(hMenu))
