Sign in to follow this  
hkBattousai

[Win32/C++] I got stuck while creating menubar wihout resources

Recommended Posts

Below is the code I'm working on. I know it is a total mess, there are too many unnecessary repetitions and casting, but they are all temporary.
	HMENU hMenu	= CreateMenu();
	HMENU hsmFile, hsmEdit, hsmView;
	hsmFile		= CreatePopupMenu();
	hsmEdit		= CreatePopupMenu();
	hsmView		= CreatePopupMenu();
	MENUITEMINFO mii;
	MENUITEMINFO fmii;
	MENUITEMINFO emii;
	MENUITEMINFO vmii;

	/*** FILE *****************************************************************/
	memset(&fmii, 0, sizeof(MENUITEMINFO));
	fmii.cbSize	= sizeof(MENUITEMINFO);
	fmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	fmii.fType	= MIIM_STRING;
	fmii.dwTypeData	= TEXT("New");
	fmii.cch	= 3;
	InsertMenuItem(hsmFile, 0, TRUE, (LPCMENUITEMINFO) &fmii);

	memset(&fmii, 0, sizeof(MENUITEMINFO));
	fmii.cbSize	= sizeof(MENUITEMINFO);
	fmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	fmii.fType	= MIIM_STRING;
	fmii.dwTypeData	= TEXT("Open");
	fmii.cch	= 4;
	InsertMenuItem(hsmFile, 1, TRUE, (LPCMENUITEMINFO) &fmii);

	memset(&fmii, 0, sizeof(MENUITEMINFO));
	fmii.cbSize	= sizeof(MENUITEMINFO);
	fmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	fmii.fType	= MIIM_STRING;
	fmii.dwTypeData	= TEXT("Save");
	fmii.cch	= 4;
	InsertMenuItem(hsmFile, 2, TRUE, (LPCMENUITEMINFO) &fmii);

	/*** EDIT *****************************************************************/
	memset(&emii, 0, sizeof(MENUITEMINFO));
	emii.cbSize	= sizeof(MENUITEMINFO);
	emii.fMask	= MIIM_STRING | MIIM_FTYPE;
	emii.fType	= MIIM_STRING;
	emii.dwTypeData	= TEXT("Copy");
	emii.cch	= 4;
	InsertMenuItem(hsmEdit, 0, TRUE, (LPCMENUITEMINFO) &emii);

	memset(&emii, 0, sizeof(MENUITEMINFO));
	emii.cbSize	= sizeof(MENUITEMINFO);
	emii.fMask	= MIIM_STRING | MIIM_FTYPE;
	emii.fType	= MIIM_STRING;
	emii.dwTypeData	= TEXT("Cut");
	emii.cch	= 3;
	InsertMenuItem(hsmEdit, 1, TRUE, (LPCMENUITEMINFO) &emii);

	memset(&emii, 0, sizeof(MENUITEMINFO));
	emii.cbSize	= sizeof(MENUITEMINFO);
	emii.fMask	= MIIM_STRING | MIIM_FTYPE;
	emii.fType	= MIIM_STRING;
	emii.dwTypeData	= TEXT("Paste");
	emii.cch	= 5;
	InsertMenuItem(hsmEdit, 2, TRUE, (LPCMENUITEMINFO) &emii);

	/*** VIEW *****************************************************************/
	memset(&vmii, 0, sizeof(MENUITEMINFO));
	vmii.cbSize	= sizeof(MENUITEMINFO);
	vmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	vmii.fType	= MIIM_STRING;
	vmii.dwTypeData	= TEXT("Toolbars");
	vmii.cch	= 8;
	InsertMenuItem(hsmView, 0, TRUE, (LPCMENUITEMINFO) &vmii);

	memset(&vmii, 0, sizeof(MENUITEMINFO));
	vmii.cbSize	= sizeof(MENUITEMINFO);
	vmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	vmii.fType	= MIIM_STRING;
	vmii.dwTypeData	= TEXT("Status");
	vmii.cch	= 6;
	InsertMenuItem(hsmView, 1, TRUE, (LPCMENUITEMINFO) &vmii);

	memset(&vmii, 0, sizeof(MENUITEMINFO));
	vmii.cbSize	= sizeof(MENUITEMINFO);
	vmii.fMask	= MIIM_STRING | MIIM_FTYPE;
	vmii.fType	= MIIM_STRING;
	vmii.dwTypeData	= TEXT("Options");
	vmii.cch	= 7;
	InsertMenuItem(hsmView, 2, TRUE, (LPCMENUITEMINFO) &vmii);

	/*** MENU BAR *************************************************************/
	memset(&mii, 0, sizeof(MENUITEMINFO));
	mii.cbSize	= sizeof(MENUITEMINFO);
	mii.fMask	= MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
	mii.fType	= MIIM_STRING;
	mii.hSubMenu	= hsmFile;
	mii.dwTypeData	= TEXT("File");
	mii.cch		= 4;
	InsertMenuItem(hMenu, 0, TRUE, (LPCMENUITEMINFO) &mii);

	memset(&mii, 0, sizeof(MENUITEMINFO));
	mii.cbSize	= sizeof(MENUITEMINFO);
	mii.fMask	= MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
	mii.fType	= MIIM_STRING;
	mii.hSubMenu	= hsmEdit;
	mii.dwTypeData	= TEXT("Edit");
	mii.cch		= 4;
	InsertMenuItem(hMenu, 1, TRUE, (LPCMENUITEMINFO) &mii);

	memset(&mii, 0, sizeof(MENUITEMINFO));
	mii.cbSize	= sizeof(MENUITEMINFO);
	mii.fMask	= MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
	mii.fType	= MIIM_STRING;
	mii.hSubMenu	= hsmView;
	mii.dwTypeData	= TEXT("View");
	mii.cch		= 4;
	InsertMenuItem(hMenu, 2, TRUE, (LPCMENUITEMINFO) &mii);


	SetMenu(Main.hWnd, hMenu);
	DrawMenuBar(Main.hWnd);

It appears like this when compiled and run : The gap between the window title and the position where first menu item starts make me think that there's no menu bar associated to the main window. Even if i omit the the function DrawMenuBar(Main.hWnd);, it changes nothing? What do I have to do to correct this error? Do you have any idea, experiences or a sample code? Any help will be appreciated.

Share this post


Link to post
Share on other sites
I would probably stick to AppendMenu. See how much simpler the code is and you can do just as much with it. Like...
enum {
GX_MENUPROPERTIES = 0x100,
GX_MENUSPLIT,
GX_MENUCOPYIMG,
GX_MENUSAVEIMG,
GX_MENUPRINT,
GX_MENU3D,
GX_MENUSAVECFG,
GX_MENULOADCFG,
GX_MENUYZOOM
};

void GXGraphCtrl::CreateGXMenu() {
GXAssert(Graph, "No graph instantiated!\n");
if (!Graph) return;

if (hPopupMenu) DestroyMenu(hPopupMenu);

// Create the popup menu if this is the first time
hPopupMenu = CreatePopupMenu();
if (Graph->Is3dCapable()) {
AppendMenu(hPopupMenu, MF_STRING, GX_MENU3D, "View &3D Graph");
AppendMenu(hPopupMenu, MF_SEPARATOR, GX_MENUSPLIT, NULL);
}
else if (Graph->Is3d()) {
AppendMenu(hPopupMenu, MF_STRING, GX_MENU3D, "View &2D Graph");
AppendMenu(hPopupMenu, MF_SEPARATOR, GX_MENUSPLIT, NULL);
}
else if (Menu3dForcedNow) {
AppendMenu(hPopupMenu, MF_STRING, GX_MENU3D, "View &3D Graph");
AppendMenu(hPopupMenu, MF_SEPARATOR, GX_MENUSPLIT, NULL);
}
AppendMenu(hPopupMenu, MF_STRING, GX_MENUCOPYIMG, "&Copy");
AppendMenu(hPopupMenu, MF_STRING, GX_MENUSAVEIMG, "Save Display as &Image");
AppendMenu(hPopupMenu, MF_STRING, GX_MENUPRINT, "P&rint");
AppendMenu(hPopupMenu, MF_SEPARATOR, GX_MENUSPLIT, NULL);
if (Graph->IsZoomable()) {
AppendMenu(hPopupMenu, MF_STRING, GX_MENUYZOOM, "Zoom on &Y Axis Only");
CheckMenuItem(hPopupMenu, GX_MENUYZOOM, Graph->IsYZoomOnly()?MF_CHECKED:MF_UNCHECKED);
}
AppendMenu(hPopupMenu, MF_STRING, GX_MENUPROPERTIES, "&Properties...");
AppendMenu(hPopupMenu, MF_SEPARATOR, GX_MENUSPLIT, NULL);
AppendMenu(hPopupMenu, MF_STRING, GX_MENUSAVECFG, "&Save Configuration...");
AppendMenu(hPopupMenu, MF_STRING, GX_MENULOADCFG, "&Load Configuration...");
}


Now that is for creating a popup menu but you can do this with any menu handle... use CreateMenu instead of CreatePopupMenu and set it to the window...

Cheers
-Scott

Share this post


Link to post
Share on other sites
Oh yeah... and say we created the above menu in my last post as a popup menu, just as it is. To add it as a popup menu to a main menu, just go like this.

// We have an hPopupMenu of type HMENU, remember?
HMENU hMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, hPopupMenu, "&Graph Options");


or whatever. I suppose there is a slight possibility that won't compile because I just made it up, but the rest is straight out of code that definitely works. I'm sure there are other ways to create a menu without a resource but I found this to be the easiest!

Cheers
-Scott

Share this post


Link to post
Share on other sites
Thank you popsoftheyear.
It looks like I will have to use AppendMenu() at the end.

But I would like to know my mistake in this code. Actually I managed to run it decently yesterday. After tasting the joy of victory, I started to simplify my code like crazy; reducing repetitions, deleting unnecessary castings, etc. Then it happened; it turned out to be its current state. No matter what I tried all the day, it just doesn't run properly as it did earlier.

It's ok, i will use AppendMenu(), but I want to learn my mistake.
Thank you again.

Share this post


Link to post
Share on other sites
Well...alright...ready for this? =) Every line that says

fmii.fType = MIIM_STRING;


should be replaced with

fmii.fType = MFT_STRING;


Apparently MIIM_STRING == 0x40 and MFT_MENUBREAK == 0x40 (MFT_MENUBREAK does exactly the effect you were getting with starting on a new line...) It happens man!

Cheers
-Scott

Share this post


Link to post
Share on other sites
fType
Menu item type. This member can be one or more of the following values.
The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined with one another. Set fMask to MIIM_TYPE to use fType.

Windows 98/Me and Windows 2000/XP: fType is used only if fMask has a value of MIIM_FTYPE.

MFT_BITMAP
Displays the menu item using a bitmap. The low-order word of the dwTypeData member is the bitmap handle, and the cch member is ignored.
Windows 98/Me, Windows 2000/XP: MFT_BITMAP is replaced by MIIM_BITMAP and hbmpItem.

MFT_MENUBARBREAK
Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, a vertical line separates the new column from the old.
MFT_MENUBREAK
Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, the columns are not separated by a vertical line.
MFT_OWNERDRAW
Assigns responsibility for drawing the menu item to the window that owns the menu. The window receives a WM_MEASUREITEM message before the menu is displayed for the first time, and a WM_DRAWITEM message whenever the appearance of the menu item must be updated. If this value is specified, the dwTypeData member contains an application-defined value.
MFT_RADIOCHECK
Displays selected menu items using a radio-button mark instead of a check mark if the hbmpChecked member is NULL.
MFT_RIGHTJUSTIFY
Right-justifies the menu item and any subsequent items. This value is valid only if the menu item is in a menu bar.
MFT_RIGHTORDER
Windows 95/98/Me, Windows 2000/XP: Specifies that menus cascade right-to-left (the default is left-to-right). This is used to support right-to-left languages, such as Arabic and Hebrew.
MFT_SEPARATOR
Specifies that the menu item is a separator. A menu item separator appears as a horizontal dividing line. The dwTypeData and cch members are ignored. This value is valid only in a drop-down menu, submenu, or shortcut menu.
MFT_STRING
Displays the menu item using a text string. The dwTypeData member is the pointer to a null-terminated string, and the cch member is the length of the string.
Windows 98/Me, Windows 2000/XP: MFT_STRING is replaced by MIIM_STRING.


MSDN says "MFT_STRING is replaced by MIIM_STRING.", that was why I used MIIM_STRING instead of MFT_STRING.

Thank you for your help. Now my next goal is to detect which menu item is clicked by user.

Share this post


Link to post
Share on other sites
This is my final code, and it works great.
Thank you all for your help.

void ConstructMenu(void)
{
Main.hMenu = CreateMenu();
HMENU hsmFile, hsmEdit, hsmMessage, hsmConnection;
hsmFile = CreatePopupMenu();
hsmEdit = CreatePopupMenu();
hsmMessage = CreatePopupMenu();
hsmConnection = CreatePopupMenu();
MENUITEMINFO mii;
memset(&mii, 0, sizeof(MENUITEMINFO)); // or use mii.hSubMenu = NULL;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU;
mii.fType = MFT_STRING;

/*** File *****************************************************************/
mii.dwTypeData = TEXT("New");
mii.cch = 3;
mii.wID = 101;
InsertMenuItem(hsmFile, 0, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Open");
mii.cch = 4;
mii.wID = 102;
InsertMenuItem(hsmFile, 1, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Save");
mii.cch = 4;
mii.wID = 103;
InsertMenuItem(hsmFile, 2, TRUE, (LPCMENUITEMINFO) &mii);

/*** Edit *****************************************************************/
mii.dwTypeData = TEXT("Copy");
mii.cch = 4;
mii.wID = 201;
InsertMenuItem(hsmEdit, 0, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Cut");
mii.cch = 3;
mii.wID = 202;
InsertMenuItem(hsmEdit, 1, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Paste");
mii.cch = 5;
mii.wID = 203;
InsertMenuItem(hsmEdit, 2, TRUE, (LPCMENUITEMINFO) &mii);

/*** Message **************************************************************/
mii.dwTypeData = TEXT("New...");
mii.cch = 6;
mii.wID = 301;
InsertMenuItem(hsmMessage, 0, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Refresh");
mii.cch = 7;
mii.wID = 302;
InsertMenuItem(hsmMessage, 1, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Copy to clipboard");
mii.cch = 13;
mii.wID = 303;
InsertMenuItem(hsmMessage, 2, TRUE, (LPCMENUITEMINFO) &mii);

/*** Connection ***********************************************************/
mii.dwTypeData = TEXT("Connect");
mii.cch = strlen(mii.dwTypeData);
mii.wID = 401;
InsertMenuItem(hsmConnection, 0, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Disconnect");
mii.cch = 6;
mii.wID = 402;
InsertMenuItem(hsmConnection, 1, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Settings...");
mii.cch = 10;
mii.wID = 403;
InsertMenuItem(hsmConnection, 2, TRUE, (LPCMENUITEMINFO) &mii);

/*** MENU BAR *************************************************************/
mii.dwTypeData = TEXT("File");
mii.cch = 4;
mii.wID = 100;
mii.hSubMenu = hsmFile;
InsertMenuItem(Main.hMenu, 0, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Edit");
mii.cch = 4;
mii.wID = 200;
mii.hSubMenu = hsmEdit;
InsertMenuItem(Main.hMenu, 1, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Message");
mii.cch = 7;
mii.wID = 300;
mii.hSubMenu = hsmMessage;
InsertMenuItem(Main.hMenu, 2, TRUE, (LPCMENUITEMINFO) &mii);

mii.dwTypeData = TEXT("Connection");
mii.cch = 4;
mii.wID = 400;
mii.hSubMenu = hsmConnection;
InsertMenuItem(Main.hMenu, 3, TRUE, (LPCMENUITEMINFO) &mii);


SetMenu(Main.hWnd, Main.hMenu);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this