menu.h

 #ifndef MENU_H
#define MENU_H

/* INCLUDED HEADERS: */
#include <windows.h>


/* MACROS */
// The move macro is used in filtering out the & character from the menu text
#define MOVE(d,s) memmove(d,s,strlen(s)+1)


/* STRUCTURES: */
// The Menu struct is used to store the positional reference points for the top menu and sub menu
struct Menu
{
int top;
int sub;

Menu()
// Menu struct constructor. Sets both positions to -1 (NULL)
{
top = sub = -1;
}
};


/* FUNCTION PROTOTYPES: */
char* GetMenuText(Menu, HWND); // Get the Caption of the top menu
char* GetSubMenuText(Menu, HWND); // Get the Caption of a menu item
UINT ConvertToID(Menu, HWND); // Convert the positional reference of a menu item
// to its actual menu ID
Menu FindMenuItem(char*, HWND); // Find the position of a menu item


/* FUNCTIONS: */
char* GetMenuText(Menu m, HWND hwnd)
// Get the caption of the top menu. This is the caption in the main menu bar, ex. File
// Arguments: Menu struct containing position reference, HWND of the window the menu is in.
// Returns: Caption of top menu.
{
MENUITEMINFO mif; // The API structure for collecting information on a menu item.
HMENU top; // The handle to a menu.

// Get the handle to the top menu:
top = GetMenu(hwnd);

// These values must be set prior to calling GetMenuItemInfo() or it will return an error:
mif.cch = 64; // Set the size of the buffer that the text will go in
mif.dwTypeData = new char[64]; // Pointer to a variable for storing the text
mif.fMask = MIIM_TYPE; // Mask specifying that mif.dwTypeData should be collected
mif.cbSize = sizeof(mif); // Size of the structure.

// Collect the information from the menu item:
GetMenuItemInfo(top, // handle to the menu,
m.top, // the position/ID of the menu item
true, // previous parameter is by position (true) or by ID (false)
&mif); // MENUITEMINFO struct to fill info into

if (mif.fType == MFT_STRING) // If the menu item has text data (important, because
// menu separators do not have text data; will not work
// correctly)
{
// Get the text and copy it into a variable:
char* text = new char[mif.cch];
strcpy (text, mif.dwTypeData);

// Format the text to remove menu "accelerators" ('&'):
char *temp;

for ( temp = text; *temp; temp++ )
{
  if ( strchr( "&", *temp ) ) // If a & character is found,
  {
MOVE( temp, temp + 1 ); // Move the rest of the string back one position
--temp;
  }
}

long pos = 0;

// Find the tab character:
// Each menu item contains two parts, the caption, and the keyboard accelerator, separated
// by a tab. Even if there is no keyboard accelerator (ie. CTRL+S for save), there is
// still a tab after the end of the menu text.
// The text gotten from the MENUITEMINFO struct contains the entire text (caption and
// accelerator). We have to parse it down to just the text (ie. up to the tab)

if (NULL != (temp = strstr(text, "\t"))) // if a tab character is found in the string
{
pos = (int)(temp - (char *)text); // get the position of the tab
char* buffer = new char[pos];
memcpy( buffer, &text[0], pos ); // copy the string up to the tab to a new var
buffer[pos] = NULL;
text = buffer;
}

return text;
}

return NULL;
}

char* GetSubMenuText(Menu m, HWND hwnd)
// Get the caption of the sub menu. This is the caption in the sub menu bar, ex. Open
// Arguments: Menu struct containing position reference, HWND of the window the menu is in.
// Returns: Caption of top menu.
// Note: Refer to GetMenuText() for redundant comments.
{
MENUITEMINFO mif;
HMENU top, sub;

top = GetMenu(hwnd);

// Get the submenu:
sub = GetSubMenu(top, // handle to the top menu
m.top); // Position of the sub menu within the top menu

mif.cch = 64;
mif.dwTypeData = new char[64];
mif.fMask = MIIM_TYPE;
mif.cbSize = sizeof(mif);

GetMenuItemInfo(sub, m.sub, true, &mif);

if (mif.fType == MFT_STRING)
{
char* text = new char[mif.cch];
strcpy (text, mif.dwTypeData);

char *temp;

for ( temp = text; *temp; temp++ )
{
  if ( strchr( "&", *temp ) )
  {
MOVE( temp, temp + 1 );
--temp;
  }
}

long pos = 0;

if (NULL != (temp = strstr(text, "\t")))
{
pos = (int)(temp - (char *)text);
char* buffer = new char[pos];
memcpy( buffer, &text[0], pos );
buffer[pos] = NULL;
text = buffer;
}

return text;
}

return NULL;
}

UINT ConvertToID(Menu m, HWND hwnd)
// Convert the Menu struct's positional reference into the single menu item ID.
// Arguments: Menu struct containing position reference, HWND of the window the menu is in.
// Returns: The ID of the menu item. An ID is a single number, compared to the position number,
// which contains two or more numbers (top menu, sub menu, sub sub menu, etc.)
{
HMENU top = GetMenu(hwnd);
HMENU sub = GetSubMenu(top, m.top);
return GetMenuItemID(sub, m.sub); // Get the ID of the menu item.
}

Menu FindMenuItem(char* find, HWND hwnd)
// Find the position of a menu item, based on its caption
// Arguments: character string containing the text caption of the menu item to find, HWND of the
// window the menu is in.
// Returns: Caption of top menu.
// Note: Refer to GetMenuText() for redundant comments.
{
Menu ret;
MENUITEMINFO mif;
HMENU top, sub;

top = GetMenu(hwnd);

// Get the number of items in the menu:
int num = GetMenuItemCount(top);

// Loop through top menu items:
for (int j = 0; j < num; j++)
{
sub = GetSubMenu(top, j); // Get Submenu Bar Handle
int subnum = GetMenuItemCount(sub); // Get the number of items in the submenu

// Loop through sub menu items:
for (int i = 0; i < subnum; i++)
{
mif.cch = 64;
mif.dwTypeData = new char[64];
mif.fMask = MIIM_TYPE;
mif.cbSize = sizeof(mif);

GetMenuItemInfo(sub, i, true, &mif);

if (mif.fType == MFT_STRING)
{
char* text = new char[mif.cch];
strcpy (text, mif.dwTypeData);

char* temp = new char[strlen(text)];

// Filter out menu "accelerators" ('&'):
for ( temp = text; *temp; temp++ )
{
  if ( strchr( "&", *temp ) )
  {
MOVE( temp, temp + 1 );
--temp;
  }
}

int n = strlen(find);

char* buffer = new char[2];
memcpy( buffer, &text[n], 1 );
buffer[1] = NULL;

// if the text matches the text to be found:
if (strncmp(strlwr(text), find, n) == 0)
// if the next character isn't a space (to distinguish between "Save" and
// "Save As", for example)
if (strncmp(buffer, " ", 1) != 0)
{
// Get positional reference:
ret.sub = i;
ret.top = j;
return ret; // If a menu item was found, return (break out of the loop)
}
}
}
}

// If no menu item was found, return a null Menu struct (positions set to -1):
Menu null;
return null;
}

#endif

Project Homepage: