菜单编程_静态添加
1.
新建一个MFC单文档应用程序,取名Menu
在IDM_NAINFRAME中添加一个菜单test ->右键-> ClassWizard… 分别在CMainFrame、CMenuDoc、CMenuApp、CMenuView中添加对Test菜单项的COMMAND消息。
MessageBox("ManinFrame clicked");
AfxMessageBox("Doc clicked");
AfxMessageBox("App clicked");
MessageBox("clicked");
命令消息传递顺序:view类-doc类-frame类-app类
2.
消息的分类(如下图)
创建标记菜单:
在新建菜单上创建一个标记菜单,在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:
// GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);//添加标记
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED);//添加标记第二种方法
注释:
UINT CheckMenuItem( UINT nIDCheckItem, UINT nCheck );
Return Value
The previous state of the item: MF_CHECKED or MF_UNCHECKED, or 0xFFFFFFFF if the menu item did not exist.
Parameters
nIDCheckItem
Specifies the menu item to be checked, as determined by nCheck.
nCheck
Specifies how to check the menu item and how to determine the item's position in the menu. The nCheck parameter can be a combination of MF_CHECKED or MF_UNCHECKED with MF_BYPOSITION or MF_BYCOMMAND flags. These flags can be combined by using the bitwise OR operator. They have the following meanings:
- MF_BYCOMMAND Specifies that the parameter gives the command ID of the existing menu item. This is the default.
- MF_BYPOSITION Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
- MF_CHECKED Acts as a toggle with MF_UNCHECKED to place the default check mark next to the item.
- MF_UNCHECKED Acts as a toggle with MF_CHECKED to remove a check mark next to the item.
Remarks
Adds check marks to or removes check marks from menu items in the pop-up menu. The nIDCheckItem parameter specifies the item to be modified.
The nIDCheckItem parameter may identify a pop-up menu item as well as a menu item. No special steps are required to check a pop-up menu item. Top-level menu items cannot be checked. A pop-up menu item must be checked by position since it does not have a menu-item identifier associated with it.
-------------------------------------------------------------------------------
CMenu::GetSubMenu
CMenu* GetSubMenu( int nPos ) const;
Return Value
A pointer to a CMenu object whose m_hMenu member contains a handle to the pop-up menu if a pop-up menu exists at the given position; otherwise NULL. If a CMenu object does not exist, then a temporary one is created. The CMenu pointer returned should not be stored.
Parameters
nPos
Specifies the position of the pop-up menu contained in the menu. Position values start at 0 for the first menu item. The pop-up menu's identifier cannot be used in this function.
Remarks
Retrieves the CMenu object of a pop-up menu.
----------------------------------------------------------------------------------
CheckMenuItem
The CheckMenuItem function sets the state of the specified menu item's check-mark attribute to either selected or clear.
Note The CheckMenuItem function has been superseded by the SetMenuItemInfo function. You can still use CheckMenuItem, however, if you do not need any of the extended features of SetMenuItemInfo.
DWORD CheckMenuItem(
HMENU hmenu, // handle to menu
UINT uIDCheckItem, // menu item to check or uncheck
UINT uCheck // menu item options
);
Parameters
hmenu
[in] Handle to the menu of interest.
uIDCheckItem
[in] Specifies the menu item whose check-mark attribute is to be set, as determined by the uCheck parameter.
uCheck
[in] Specifies flags that control the interpretation of the uIDCheckItem parameter and the state of the menu item's check-mark attribute. This parameter can be a combination of either MF_BYCOMMAND, or MF_BYPOSITION and MF_CHECKED or MF_UNCHECKED.
Value |
Meaning |
|
MF_BYCOMMAND |
Indicates that the uIDCheckItem parameter gives the identifier of the menu item. The MF_BYCOMMAND flag is the default, if neither the MF_BYCOMMAND nor MF_BYPOSITION flag is specified. |
|
MF_BYPOSITION |
Indicates that the uIDCheckItem parameter gives the zero-based relative position of the menu item. |
|
MF_CHECKED |
Sets the check-mark attribute to the selected state. |
|
MF_UNCHECKED |
Sets the check-mark attribute to the clear state. |
Return Values
The return value specifies the previous state of the menu item (either MF_CHECKED or MF_UNCHECKED). If the menu item does not exist, the return value is -1.
Remarks
An item in a menu bar cannot have a check mark.
The uIDCheckItem parameter identifies a item that opens a submenu or a command item. For a item that opens a submenu, the uIDCheckItem parameter must specify the position of the item. For a command item, the uIDCheckItem parameter can specify either the item's position or its identifier.
3.
设置缺省菜单,在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:
//GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);//设置缺省菜单
//GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);
GetMenu()->GetSubMenu(0)->SetDefaultItem(5,TRUE);
注释:
CMenu::SetDefaultItem
BOOL SetDefaultItem( UINT uItem, BOOL fByPos = FALSE );
Return Value
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, use the Win32 function GetLastError, as described in the Platform SDK.
Parameters
uItem
Identifier or position of the new default menu item or - 1 for no default item. The meaning of this parameter depends on the value of fByPos.
fByPos
Value specifying the meaning of uItem. If this parameter is FALSE, uItem is a menu item identifier. Otherwise, it is a menu item position.
Remarks
This member function implements the behavior of the Win32 function SetMenuDefaultItem, as described in the Platform SDK.
4.
创建一个图形标记菜单,在CMainFrame中添加成员变量:
private:
CBitmap m_bitmap;
在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:
CString str;
str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),
GetSystemMetrics(SM_CYMENUCHECK));//获取菜单图形标记的尺寸
MessageBox(str);
m_bitmap.LoadBitmap(IDB_BITMAP1);
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);
注释:
GetSystemMetrics
The GetSystemMetrics function retrieves various system metrics (widths and heights of display elements) and system configuration settings. All dimensions retrieved by GetSystemMetrics are in pixels.
int GetSystemMetrics(
int
nIndex // system metric or configuration setting
);
Parameters
nIndex
[in] Specifies the system metric or configuration setting to retrieve. All SM_CX* values are widths. All SM_CY* values are heights.
SM_CXMENUCHECK, |
Dimensions, in pixels, of the default menu check-mark bitmap. |
-----------------------------------------------------------------------------------
SetMenuItemBitmaps
The SetMenuItemBitmaps function associates the specified bitmap with a menu item. Whether the menu item is selected or clear, the system displays the appropriate bitmap next to the menu item.
BOOL SetMenuItemBitmaps(
HMENU
hMenu, // handle to menu
UINT
uPosition, // menu item
UINT
uFlags, // options
HBITMAP
hBitmapUnchecked, // handle to unchecked bitmap
HBITMAP
hBitmapChecked
// handle to checked bitmap
);
Parameters
hMenu
[in] Handle to the menu containing the item to receive new check-mark bitmaps.
uPosition
[in] Specifies the menu item to be changed, as determined by the uFlags parameter.
uFlags
[in] Specifies how the uPosition parameter is interpreted. The uFlags parameter must be one of the following values.
Value |
Meaning |
|
MF_BYCOMMAND |
Indicates that uPosition gives the identifier of the menu item. If neither MF_BYCOMMAND nor MF_BYPOSITION is specified, MF_BYCOMMAND is the default flag. |
|
MF_BYPOSITION |
Indicates that uPosition gives the zero-based relative position of the menu item. |
hBitmapUnchecked
[in] Handle to the bitmap displayed when the menu item is not selected.
hBitmapChecked
[in] Handle to the bitmap displayed when the menu item is selected.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
If either the hBitmapUnchecked or hBitmapChecked parameter is NULL, the system displays nothing next to the menu item for the corresponding check state. If both parameters are NULL, the system displays the default check-mark bitmap when the item is selected, and removes the bitmap when the item is not selected.
When the menu is destroyed, these bitmaps are not destroyed; it is up to the application to destroy them.
The selected and clear bitmaps should be monochrome. The system uses the Boolean AND operator to combine bitmaps with the menu so that the white part becomes transparent and the black part becomes the menu-item color. If you use color bitmaps, the results may be undesirable.
Use the GetSystemMetrics function with the CXMENUCHECK and CYMENUCHECK values to retrieve the bitmap dimensions.
5.
使菜单不可用,变灰
在CMainFrame::CMainFrame()函数中添加:
m_bAutoMenuEnable=FALSE;
在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);
注释:
CMenu::EnableMenuItem
UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );
Return Value
Previous state (MF_DISABLED, MF_ENABLED, or MF_GRAYED) or –1 if not valid.
Parameters
nIDEnableItem
Specifies the menu item to be enabled, as determined by nEnable. This parameter can specify pop-up menu items as well as standard menu items.
nEnable
Specifies the action to take. It can be a combination of MF_DISABLED, MF_ENABLED, or MF_GRAYED, with MF_BYCOMMAND or MF_BYPOSITION. These values can be combined by using the bitwise OR operator. These values have the following meanings:
- MF_BYCOMMAND Specifies that the parameter gives the command ID of the existing menu item. This is the default.
- MF_BYPOSITION Specifies that the parameter gives the position of the existing menu item. The first item is at position 0.
- MF_DISABLED Disables the menu item so that it cannot be selected but does not dim it.
- MF_ENABLED Enables the menu item so that it can be selected and restores it from its dimmed state.
- MF_GRAYED Disables the menu item so that it cannot be selected and dims it.
Remarks
Enables, disables, or dims a menu item. The CreateMenu, InsertMenu, ModifyMenu, and LoadMenuIndirect member functions can also set the state (enabled, disabled, or dimmed) of a menu item.
Using the MF_BYPOSITION value requires an application to use the correct CMenu. If the CMenu of the menu bar is used, a top-level menu item (an item in the menu bar) is affected. To set the state of an item in a pop-up or nested pop-up menu by position, an application must specify the CMenu of the pop-up menu.
When an application specifies the MF_BYCOMMAND flag, Windows checks all pop-up menu items that are subordinate to the CMenu; therefore, unless duplicate menu items are present, using the CMenu of the menu bar is sufficient.
Example
// The code fragment below shows how to disable (and gray out) the
// File\New menu item.
// NOTE: m_bAutoMenuEnable is set to FALSE in the constructor of
// CMainFrame so no ON_UPDATE_COMMAND_UI or ON_COMMAND handlers are
// needed, and CMenu::EnableMenuItem() will work as expected.
CMenu* mmenu = GetMenu();
CMenu* submenu = mmenu->GetSubMenu(0);
submenu->EnableMenuItem(ID_FILE_NEW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
----------------------------------------------------------------------------------------------------------
6.
如何取消整个菜单,
在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:
CMenu menu;//在这是局部变量,一般会有问题,应设置成CMainFrame的成员变量
menu.LoadMenu(IDR_MAINFRAME);//加载菜单
SetMenu(&menu);
menu.Detach();
注释:
SetMenu
The SetMenu function assigns a new menu to the specified window.
BOOL SetMenu(
HWND
hWnd, // handle to window
HMENU
hMenu
// handle to menu
);
Parameters
hWnd
[in] Handle to the window to which the menu is to be assigned.
hMenu
[in] Handle to the new menu. If this parameter is NULL, the window's current menu is removed.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
The window is redrawn to reflect the menu change. A menu can be assigned to any window that is not a child window.
The SetMenu function replaces the previous menu, if any, but it does not destroy it. An application should call the DestroyMenu function to accomplish this task.
----------------------------------------------------------------------------------------------------
The CMenu class is an encapsulation of the Windows HMENU. It provides member functions for creating, tracking, updating, and destroying a menu.
Create a CMenu object on the stack frame as a local, then call CMenu's member functions to manipulate the new menu as needed. Next, call CWnd::SetMenu to set the menu to a window, followed immediately by a call to the CMenu object's Detach member function. The CWnd::SetMenu member function sets the window's menu to the new menu, causes the window to be redrawn to reflect the menu change, and also passes ownership of the menu to the window. The call to Detach detaches the HMENU from the CMenu object, so that when the local CMenu variable passes out of scope, the CMenu object destructor does not attempt to destroy a menu it no longer owns. The menu itself is automatically destroyed when the window is destroyed.
7.
命令更新,
在View-> ClassWizard… 中添加对ID_EDIT_CUT的UPDATE_COMMAND_UI消息,然后在CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)函数中添加:
pCmdUI->Enable();//默认为TRUE
这样剪切菜单就变成了可有状态。
注释:
CCmdUI
CCmdUI does not have a base class.
The CCmdUI class is used only within an ON_UPDATE_COMMAND_UI handler in a CCmdTarget-derived class.
When a user of your application pulls down a menu, each menu item needs to know whether it should be displayed as enabled or disabled. The target of a menu command provides this information by implementing an ON_UPDATE_COMMAND_UI handler. Use ClassWizard to browse the command user-interface objects in your application and create a message-map entry and function prototype for each handler.
When the menu is pulled down, the framework searches for and calls each ON_UPDATE_COMMAND_UI handler, each handler calls CCmdUI member functions such as Enable and Check, and the framework then appropriately displays each menu item.
A menu item can be replaced with a control-bar button or other command user-interface object without changing the code within the ON_UPDATE_COMMAND_UI handler.
The following table summarizes the effect CCmdUI's member functions have on various command user-interface items.
-------------------------------------------------------------------------------------------------------
CCmdUI Class Members
Data Members
The ID of the user-interface object. |
||
The index of the user-interface object. |
||
Points to the menu represented by the CCmdUI object. |
||
Points to the contained sub-menu represented by the CCmdUI object. |
||
Points to the window object that sent the notification. |
Operations
Enables or disables the user-interface item for this command. |
||
Sets the check state of the user-interface item for this command. |
||
Like the SetCheck member function, but operates on radio groups. |
||
Sets the text for the user-interface item for this command. |
||
Tells the command-routing mechanism to continue routing the current message down the chain of handlers. |
如果我们需要将工具栏上的某个图标与某个菜单项相关联,我们只需要它们的ID号设置成同一个就可以了。
再做一个使新建菜单项不能使用状态的操作,同样对ID_FILE_NEW添加UPDATE_COMMAND_UI消息,然后在CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)函数中添加:
if(ID_FILE_NEW==PcmdUI->m_nID)//m_nID是CCmdUI的成员变量,保存了与这个UI当前相关的菜单项
pCmdUI->Enable(FALSE);
当然也可以通过索引实现,
if(0==pCmdUI->m_nIndex)
pCmdUI->Enable(FALSE);
注意:如果对前面的菜单的状态也用索引来判断,那工具栏上的剪切图标将不会变成可用状态;而用ID号来判断,则工具栏上的剪切则会变成可用状态。
8.
添加右键弹出菜单功能,首先选择Project ->Add To Project -> Components and Controls… 在弹出的对话框中选择visual C++ Components -> Pop up Menu 选择插入,"Insert the Pop-up Menu Component?" 选择确定,增加弹出菜单到CMenuView类当中,ID暂不修改,OK!
运行点右键可以看到,增加了弹出菜单!
在资源中打开CG_IDR_POPUP_MENU_VIEW,可以看到增加的三个菜单项,
下面手动创建一个弹出菜单:
新建一个菜单,添加两个菜单项 IDM_SHOW 、 IDM_EXIT ,并在视类中添加WM_RBUTTONDOWN消息响应函数,并在CMenuView::OnRButtonDown(UINT nFlags, CPoint point)函数中添加:
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *pPopup=menu.GetSubMenu(0);
ClientToScreen(&point);//把给定的点所在的客户区坐标转换成屏幕坐标
pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);//显示弹出菜单
注释:
TrackPopupMenu
The TrackPopupMenu function displays a shortcut menu at the specified location and tracks the selection of items on the menu. The shortcut menu can appear anywhere on the screen.
To specify an area of the screen the menu should not overlap, use the TrackPopupMenuEx function.
BOOL TrackPopupMenu(
HMENU
hMenu, // handle to shortcut menu
UINT
uFlags, // options
int
x, // horizontal position
int
y, // vertical position
int
nReserved, // reserved, must be zero
HWND
hWnd, // handle to owner window
CONST RECT
*prcRect
// ignored
);
Return Values
If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item identifier of the item that the user selected. If the user cancels the menu without making a selection, or if an error occurs, then the return value is zero.
If you do not specify TPM_RETURNCMD in the uFlags parameter, the return value is nonzero if the function succeeds and zero if it fails. To get extended error information, call GetLastError.
Remarks
To display a context menu for a notification icon, the current window must be the foreground window before the application calls TrackPopupMenu or TrackPopupMenuEx. Otherwise, the menu will not disappear when the user clicks outside of the menu or the window that created the menu (if it is visible). However, when the current window is the foreground window, the second time this menu is displayed, it displays and then immediately disappears. To correct this, you must force a task switch to the application that called TrackPopupMenu at some time in the near future. This is done by posting a benign message to the window or thread, as shown in the following code sample:
SetForegroundWindow(hDlg);
// Display the menu
TrackPopupMenu( hSubMenu,
TPM_RIGHTBUTTON,
pt.x,
pt.y,
0,
hDlg,
NULL);
PostMessage(hDlg, WM_NULL, 0, 0);
---------------------------------------------------------------------------------------------------------
ClientToScreen
The ClientToScreen function converts the client-area coordinates of a specified point to screen coordinates.
BOOL ClientToScreen(
HWND
hWnd, // handle to window
LPPOINT
lpPoint // screen coordinates
);
Parameters
hWnd
[in] Handle to the window whose client area is used for the conversion.
lpPoint
[in/out] Pointer to a POINT structure that contains the client coordinates to be converted. The new screen coordinates are copied into this structure if the function succeeds.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero.
Remarks
The ClientToScreen function replaces the client-area coordinates in the POINT structure with the screen coordinates. The screen coordinates are relative to the upper-left corner of the screen. Note, a screen-coordinate point that is above the window's client area has a negative y-coordinate. Similarly, a screen coordinate to the left of a client area has a negative x-coordinate.
All coordinates are device coordinates.
CView::OnRButtonDown(nFlags, point);
对IDM_SHOW菜单项做消息响应,分别在CMainFrame、CMenuView中添加WM_COMMAND消息响应,在CMenuView::OnShow()添加:
MessageBox("View Show");
MessageBox("MainFrame Show");
如果删除View类中的OnShow()函数后,运行,可以看出弹出菜单并不响应CMainFrame::OnShow()函数,如果要对它响应,则要修改CMenuView::OnRButtonDown(UINT nFlags, CPoint point)中的:
pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,GetParent());
//其中Getparent()是获取框架类窗口的指针
同样如果这样修改后,再加上View类中的OnShow()函数后,最先响应的仍然是view类中的响应函数。