VC Study Notes: Menu
SkySeraph NOV.1sh 2010 HQU
Email-zgzhaobo@gmail.com QQ-452728574
Latest Modified Date: NOV.1sh 2010 HQU
Basic operations
- Dynamic menu creation [1]
Steps:
① Create a dialog box project and declare a CMenu Class Object m_Menu in the dialog box header file.
② In the OnInitDialog function of the dialog box, add:
M_Menu.CreateMenu (); // create a menu window
CMenu m_PopMenu; // defines the menu Class Object
M_PopMenu.CreatePopupMenu (); // create a menu window
M_Menu.AppendMenu (MF_POPUP, (UINT) m_PopMenu.m_hMenu, "animal"); // Insert Menu
M_PopMenu.AppendMenu (MF_STRING, ID_MENUCAT, "cat"); // insert sub menu
M_PopMenu.AppendMenu (MF_STRING, ID_MENUDOG, "dog ");
M_PopMenu.AppendMenu (MF_STRING, ID_MENUMONKEY, "monkey ");
M_Menu.AppendMenu (MF_POPUP,-1, "plant"); // Insert the sibling menu
M_PopMenu.Detach (); // detach the menu handle
SetMenu (& m_Menu); // associate the menu with the window
③ Declare the menu handler in the header file of the dialog box
Afx_msg void OnMenucat ();
Afx_msg void OnMenudog ();
Afx_msg void OnMenumonkey ();
④ Add a message ing macro to the source file in the dialog box
ON_COMMAND (ID_MENUCAT, OnMenucat)
ON_COMMAND (ID_MENUDOG, OnMenudog)
ON_COMMAND (ID_MENUMONKEY, OnMenumonkey)
⑤ Add the message processing function implementation code to the source file in the dialog box
Void CCreateMenuDlg: OnMenucat ()
{
MessageBox ("cat menu pressed ");
}
Void CCreateMenuDlg: OnMenudog ()
{
MessageBox ("Dog menu pressed ");
}
Void CCreateMenuDlg: OnMenumonkey ()
{
MessageBox ("monkey menu pressed ");
}
Note:
Create a menu window through CreateMenu and associate it with the menu object.
Call CreatePopupmenu to create a pop-up window and associate it with the menu object.
Call AppendMenu to add a menu item.
Call Detach to Detach the menu handle from the menu object.
Finally, call SetMenu to allocate the created menu to the specified window.
Steps:
① Create a dialog box project and declare a CMenu Class Object m_Menu in the header file.
② Insert a menu resource and set the menu
③ In the OnInitDialog function of the dialog box, add:
M_Menu.LoadMenu (IDR_MENU1); // load menu Resources
④ Right-click the dlg and choose OnRButtonUp from the shortcut menu to edit the code.
Void CPopupMenuDlg: OnRButtonUp (UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CMenu * pMenu = m_Menu.GetSubMenu (0); // obtain the menu handle
CRect rect;
ClientToScreen (& point); // convert customer coordinates to screen coordinates
Rect. top = point. x; // The current horizontal coordinates of the mouse are used as the coordinates in the upper left corner of the pop-up menu.
Rect. left = point. y;
PMenu-> TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
Rect. top, rect. left, this, & rect); // display the pop-up menu
CDialog: OnRButtonUp (nFlags, point); // call the method of the base class
}
⑤ Add a menu to process events .. For example ..
Void CPopupMenuDlg: OnMenuadd ()
{
// TODO: Add your command handler code here
MessageBox ("menu pressed ");
}
Note:
First, create a menu resource and call the LoadMenu method to load the menu resource.
Call the GetSubMenu method to obtain a menu item in the pop-up menu.
Finally, call the TrackPopupMenu method to display a pop-up menu.
- Create a pop-up menu method 2 [2]
<03.rar>>
① Create a single document project, create a menu class CIconMenu, derived from CMenu
② Define menu information in the CIconMenu header file, define some member variables, and add the AttachMenu method to CIconMenu, as shown below:
/*************************************
The CMenuItemInfo structure is used to record menu item information.
*************************************/
Struct CMenuItemInfo
{
CString m_ItemText; // menu item text
Int m_IconIndex; // menu item index
Int m_ItemID; // menu tag-2 top menu,-1 pop-up menu, 0 separator bar, other common menus
};
/*************************************/
Public:
CMenuItemInfo m_ItemLists [MAX_MENUCOUNT]; // menu item information
Int m_index; // temporary Index
Int m_iconindex; // index of the menu item icon
CImageList m_imagelist; // stores the menu item icon
/*************************************/
BOOL CIconMenu: AttatchMenu (HMENU m_hmenu)
{
This-> Attach (m_hmenu );
Return TRUE;
}
③ Compile the conmenu class Constructor
CIconMenu: CIconMenu ()
{
M_index = 0;
M_iconindex = 0;
// Create an image list
M_imagelist.Create (16, 16, ILC_COLOR24 | ILC_MASK, 0, 0 );
// Add an icon
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON1 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON2 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON3 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON4 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON5 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON6 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON7 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON8 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON9 ));
M_imagelist.Add (AfxGetApp ()-> LoadIcon (IDI_ICON10 ));
}
④ Add the ChangeMenuItem method to the CIconMenu class to modify the menu item information, so that it contains the MF_OWNERDRAW style, and store the menu item information in the m_ItemLists member variable.
BOOL CIconMenu: ChangeMenuItem (CMenu * m_menu, BOOL m_Toped)
{
If (m_menu! = NULL)
{
Int m_itemcount = m_menu-> GetMenuItemCount ();
For (int I = 0; I <m_itemcount; I ++)
{
M_menu-> GetMenuString (I, m_ItemLists [m_index]. m_ItemText, MF_BYPOSITION );
Int m_itemID = m_menu-> GetMenuItemID (I );
If (m_itemID =-1 & m_Toped)
{
M_itemID =-2; // top menu
};
M_ItemLists [m_index]. m_ItemID = m_itemID;
If (m_itemID> 0)
{
M_ItemLists [m_index]. m_IconIndex = m_iconindex;
M_iconindex + = 1;
}
M_menu-> ModifyMenu (I, MF_OWNERDRAW | MF_BYPOSITION | MF_STRING, m_ItemLists [m_index]. m_ItemID, (LPSTR) & (m_ItemLists [m_index]);
M_index + = 1;
CMenu * m_subMenu = m_menu-> GetSubMenu (I );
If (m_subMenu)
{
ChangeMenuItem (m_subMenu );
}
}
}
Return TRUE;
}
⑤ Rewrite the MeasureItem virtual method of the menu class to calculate the menu item size
Void CIconMenu: MeasureItem (LPMEASUREITEMSTRUCT lpStruct)
{
If (lpStruct-> CtlType = ODT_MENU)
{
LpStruct-> itemHeight = ITEMHEIGHT;
LpStruct-> itemWidth = ITEMWIDTH;
CMenuItemInfo * m_iteminfo;
M_iteminfo = (CMenuItemInfo *) lpStruct-> itemData;
LpStruct-> itemWidth = (CMenuItemInfo *) lpStruct-> itemData)-> m_ItemText.GetLength () * 10;
Switch (m_iteminfo-> m_ItemID)
{
Case 0: // Separator
{
LpStruct-> itemHeight = 1;
Break;
}
}
}
}
⑥ Add the member function DrawItemText to draw the menu item text, DrawMenuIcon to draw the menu item icon, DrawSeparater to draw the separation bar, DrawTopMenu to draw the top menu, and DrawComMenu to draw the gradient effect in the menu item area.
/*************************************** **********************
Function Description: draws the menu item text.
Parameter description: m_pdc identifies the canvas object, str identifies the menu text, and m_rect identifies the menu area.
**************************************** *********************/
Void CIconMenu: DrawItemText (CDC * m_pdc, LPSTR str, CRect m_rect)
{
M_rect.DeflateRect (20, 0 );
M_pdc-> DrawText (str, m_rect, DT_SINGLELINE | DT_VCENTER | DT_LEFT );
}
Void CIconMenu: DrawTopMenu (CDC * m_pdc, CRect m_rect, BOOL m_selected)
{
If (m_selected)
{
M_pdc-> SelectStockObject (BLACK_PEN );
M_pdc-> Rectangle (& m_rect );
M_rect.DeflateRect (1, 1 );
M_pdc-> FillSolidRect (m_rect, RGB (150,185,255 ));
}
Else
{
CRect rect;
AfxGetMainWnd ()-> GetClientRect (rect );
Rect. top = m_rect.top;
Rect. bottom = m_rect.bottom;
Rect. left = 360;
Rect. right + = 4;
// CRect c_rect (m_rect );
M_pdc-> FillSolidRect (& rect, RGB (200,187,255 ));
M_pdc-> FillSolidRect (& m_rect, RGB (200,187,255 ));
// M_pdc-> SelectStockObject (BLACK_PEN );
// M_pdc-> FillSolidRect (m_rect, RGB (100,185,255 ));
}
}
Void CIconMenu: DrawSeparater (CDC * m_pdc, CRect m_rect)
{
If (m_pdc! = NULL)
{
M_pdc-> Draw3dRect (m_rect, RGB (255, 0), RGB ));
}
}
Void CIconMenu: DrawComMenu (CDC * m_pdc, CRect m_rect, COLORREF m_fromcolor, COLORREF m_tocolor, BOOL m_selected)
{
If (m_selected)
{
M_pdc-> Rectangle (m_rect );
M_rect.DeflateRect (1, 1 );
Int r1, g1, b1;
// Read the color value of the gradient start point
R1 = GetRValue (m_fromcolor );
G1 = GetGValue (m_fromcolor );
B1 = GetBValue (m_fromcolor );
Int r2, g2, b2;
// Read the color value of the gradient end point
R2 = GetRValue (m_tocolor );
G2 = GetGValue (m_tocolor );
B2 = GetBValue (m_tocolor );
Float r3, g3, b3; // The degree (range) in which the RGB value of each vertex changes horizontally in the menu area)
R3 = (float) (r2-r1)/(float) (m_rect.Height ());
G3 = (float) (g2-g1)/(float) (m_rect.Height ());
B3 = (float) (b2-b1)/(float) (m_rect.Height ());
COLORREF r, g, B; // color value of each vertex in the horizontal direction of the menu area
CPen * m_oldpen;
For (int I = m_rect.top; I <m_rect.bottom; I ++)
{
R = r1 + (int) r3 * (i-m_rect.top );
G = g1 + (int) g3 * (i-m_rect.top );
B = b1 + (int) b3 * (i-m_rect.top );
CPen m_pen (PS_SOLID, 1, RGB (r, g, B ));
M_oldpen = m_pdc-> SelectObject (& m_pen );
M_pdc-> MoveTo (m_rect.left, I );
M_pdc-> LineTo (m_rect.right, I );
}
M_pdc-> SelectObject (m_oldpen );
}
Else
{
M_pdc-> FillSolidRect (m_rect, RGB (0x000000F9, 0x000000F8, 0x000000F7 ));
}
}
Void CIconMenu: DrawMenuIcon (CDC * m_pdc, CRect m_rect, int m_icon)
{
M_imagelist.Draw (m_pdc, m_icon, CPoint (m_rect.left + 2, m_rect.top + 4), ILD_TRANSPARENT );
}
7. Rewrite the DrawItem virtual method of the menu and draw the menu according to the different states of the menu item. The Code is as follows:
Void CIconMenu: DrawItem (LPDRAWITEMSTRUCT lpStruct)
{
If (lpStruct-> CtlType = ODT_MENU)
{
If (lpStruct-> itemData = NULL) return;
Unsigned int m_state = lpStruct-> itemState;
CDC * m_dc = CDC: FromHandle (lpStruct-> hDC );
// M_dc.Attach (lpStruct-> hDC );
CString str = (CMenuItemInfo *) (lpStruct-> itemData)-> m_ItemText;
LPSTR m_str = str. GetBuffer (str. GetLength ());
Int m_itemID = (CMenuItemInfo *) (lpStruct-> itemData)-> m_ItemID;
Int m_itemicon = (CMenuItemInfo *) (lpStruct-> itemData)-> m_IconIndex;
CRect m_rect = lpStruct-> rcItem;
M_dc-> SetBkMode (TRANSPARENT );
Switch (m_itemID)
{
Case-2:
{
DrawTopMenu (m_dc, m_rect, (m_state & ODS_SELECTED) | (m_state & 0x0040); // 0x0040 = ODS_HOTLIGHT
DrawItemText (m_dc, m_str, m_rect );
Break;
}
Case-1:
{
DrawItemText (m_dc, m_str, m_rect );
Break;
}
Case 0:
{
DrawSeparater (m_dc, m_rect );
Break;
}
Default:
{
DrawComMenu (m_dc, m_rect, 0xfaa0, 0xf00ff, m_state & ODS_SELECTED );
DrawItemText (m_dc, m_str, m_rect );
DrawMenuIcon (m_dc, m_rect, m_itemicon );
Break;
}
}
}
}
Introduce the CIconMenu header file in the framework class to define a member m_menu of the CIconMenu type. Process WM_DRAWITEM messages of the framework class and call the MeasureItem method of the m_menu object in its message processing function. The Code is as follows:
Void CMainFrame: OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
M_menu.MeasureItem (lpMeasureItemStruct );
// CFrameWnd: OnMeasureItem (nIDCtl, lpMeasureItemStruct );
}
Combine associates the m_menu object with the menu window in the application in the OnCreate method of the framework class. The Code is as follows:
M_menu.AttatchMenu (this-> GetMenu ()-> GetSafeHmenu ());
M_menu.ChangeMenuItem (& m_menu, TRUE );
① Create a dialog box project, create a menu resource, set the menu, create a menu class CMenuIcon, derived from Cmenu
<IconMenu.rar>
Author: SKySeraph
Email/GTalk: zgzhaobo@gmail.com QQ: 452728574
From: http://www.cnblogs.com/skyseraph/
The copyright of this article is shared by the author and the blog. You are welcome to repost this article. However, you must keep this statement without the author's consent and provide the original article connection clearly on the article page. Please respect the author's Labor achievements.