Menu Control Why even if the EnableMenuItem menu item is called, the menu item is still set to FALSE to false if the data member is true (default), and the workflow will automatically disable the menu of ON_UPDATE_COMMAND_UI or ON_COMMAND item. // Disable MFC from automatically disabling menu items.m_bAuoMenuEnable = FALSE; // Now enable the menu item.CMenu * pMenu = GetMenu (); ASSERT_VALID (pMenu); pMenu-> EnableMenuItem (ID_MENU_ITEM, MF_BYCOMMAND | MF_ENABLED); how the system Menu Add a menu item to add a menu item to the system menu requires the following three steps: First, use the Resource Symbols Dialog (Select Resource Symbols ... You can display the dialog in the View menu) Define the menu item ID, the ID should More than 0x0f and less than 0xF000; Second, call CWnd :: GetSystemMenu Get the pointer to the system menu and call CWnd :: Appendmenu to add the menu item to the menu. The following example adds two new menu items to the system menu: int CMainFrame :: OnCreate (LPCREATESTRUCT lpCreateStruct) {... // Make sure system menu item is in the right range.ASSERT (IDM_MYSYSITEM & 0xFFF0) == IDM_MYSYSITEM); ASSERT (IDM -MYSYSITEM <0xF000); // Get pointer to system menu.CMenu * pSysmenu = GetSystemmenu (FALSE); ASSERT_VALID (pSysMenu); // Add a separator and our menu item to system menu.CString StrMenuItem (_T ( "New menu item ")); psysmenu-> appendmenu (mf_separator); psysmenu-> appendmenu (mf_string, idm_mysystem, strmenuitem); ...} Now, the user should detect when selecting the system menu item. Use ClassWizard WM_SYSCOMMAND message handling menus and detects user nID parameters: void CMainFrame :: OnSysCommand (UINT nID, LPARAM lParam) {// Determine if our system menu item was selected.if ((nID & 0xFFF0) == IDM_MYSYSITEM) {/ / TODO-Process System Menu Item} elsecmdiframewnd :: OnsysCommand (NID, LPARAM); The entry of the skeed table of the system menu base ID is implemented. How to determine the number of rows occupied by the top menu This can be implemented by simple subtraction and division. First, the user needs to calculate the height and customer area of the primary frame window; secondly, subtract the height of the client area, frame boundary, and title from the height of the mainframe window; finally, divide the menu bar. The following member function is a code implementation that calculates the number of rows occupied by the main box menu.
int CMainFrame :: GetMenuRows () {CRect rcFrame, rcClient; GetWindowRect (rcFrame); GetClientRect (rcClient); return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics (SM_CYCAPTION) - (:: getSystemMetrics (SM_CYFRAME ) * 2)) / :: getSystemMetrics (SM_CYMENU);} The self-painted menu will provide a C class (CCUSTomMenu), which is a subclass of CMenu and has self-painting capabilities. It provides you with the following features: set font color. Set high brightness colors. Set the style of high brightness. Set the icon that is selected and in a menu in a normal state. Set the display icon size. The structure Menudata is defined in the CCustomU, you must fill this structure according to your needs, and provide the pointer to the structure (call Appendmenu, InsertMenu) when adding menus. Here is an example: 1. Define the instance of CCUSTomMenu, and the Menudata structure variable. CCUSTOMMENU M_CCUSTOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUDATA [8]; // AS MANY MENU ITEMS ARE Present, You Should Be Aable To Use // NEW AND DO THE SAME2, CreateMenu () Sets the relevant parameters. M_CustomMenu.createMenu (); M_CustomMenu.seticonsize (25, 25); // this is to set the size of the icon. // this kind be used only for any menu // in Order To Resize It, Destroy and Create THE, DESTROY AND CREATE menu again with different size m_customMenu.SetHighlightStyle (Normal);.. // Or TextOnly, if you want the // background color to remain the same // and the Text color to change to the Highlight color // The following setXXXColor sets the . menu colors If you dont want to change any, dont call these member functions m_customMenu.SetTextColor (RGB (255,0,0));. m_customMenu.SetBackColor (RGB (255,255,255)); m_customMenu.SetHighlightColor (RGB (0,0,255 ))); 3, set the menudata variable and increase the menu item. LSTRCPY (Menudata [0]); menudata [0] .Menuiconnormal = IDi_ICON1; M_CUSTomMenu.Appendmenu (MF_OWNERDRAW, 3, (LPCTSTSTSTSTS MENUDATA); 3, overMeasure Item in your window. .)function.
void CMyView :: OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) {if (lpMeasureItemStruct-> CtlType == ODT_MENU && IsMenu ((HMENU) lpMeasureItemStruct-> itemID) && (lpMeasureItemStruct-> itemID == (UINT) m_hMenuSub)) {m_customMenu. MeasureItem (LPMeasureItemstruct);} else // let mfc's self-drawing handle ipview :: OnMeasureItem (NidctL, lpMeasureItemstructure);} The following function will help you set the menu properties.
void SetTextColor (COLORREF); void SetBackColor (COLORREF); void SetHighlightColor (COLORREF); void SetIconSize (int, int); void SetHighlightStyle (HIGHLIGHTSTYLE); // HIGHLIGHTSTYLE: enum {Normal, TextOnly} void SetHighlightTextColor (COLORREF); The following is File code: // *************************************************** **************************** // CustomMenu.h:! header file // # if defined (AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED _) # define AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_ # if _MSC_VER> = 1000 # pragma once # endif // _MSC_VER> = 1000class MENUDATA {public: MENUDATA () {menuIconNormal = -1; menuIconSelected = -1;}; char menuText [32]; UINT menuIconNormal; UINT menuIconSelected;}; typedef enum {Normal, TextOnly} HIGHLIGHTSTYLE; //// CCustomMenu windowclass CCustomMenu: public CMenu {// Constructionpublic: CCustomMenu (); // Attributespublic: // Operationspublic: // Overrides // ClassWizard generated virtual function overrides / / {{AFX_VIRTUAL (CCustomMenu) //}} AFX_VIRTUAL // Implementationpublic: virtual ~ CCustomMenu (); virtual void DrawItem (LPDRAWITEMSTRUCT); virtual void MeasureItem (LPMEASUREITEMSTRUCT); void SetTextColor (COLORREF); void SetBackColor (COLORREF); void SetHighlightColor (COLORREF); void SetIconSize (int, int); void SetHighlightStyle (HIGHLIGHTSTYLE); void SetHighlightTextColor (COLORREF); // Generated message map functionsprotected: COLORREF m_crText; COLORREF m_clrBack; COLORREF m_clrText; COLORREF m_clrHilight; COLORREF m_clrHilightText; LOGFONT m_lf; CFont M_FontMenu; uint m_imenuheight; bool m_blbtndown; cbrush m_brbackground, m_brselect;
CPen m_penBack; int m_iconX, m_iconY; HIGHLIGHTSTYLE m_hilightStyle; // {{AFX_MSG (CCustomMenu) // NOTE - the ClassWizard will add and remove member functions here //}.} AFX_MSG}; /////// {{AFX_INSERT_LOCATION }} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. # endif //! defined (AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED _) // ********************** *********************************************************** * // CustomMenu.cpp: implementation file // # include "stdafx.h" #include "CustomMenu.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILEstatic char THIS_FILE [] = __FILE __; # endif //// CCustomMenuCCustomMenu: : CCustomMenu () {m_clrText = GetSysColor (COLOR_MENUTEXT); m_clrBack = GetSysColor (COLOR_MENU); m_brBackground.CreateSolidBrush (m_clrBack); m_penBack.CreatePen (PS_SOLID, 0, m_clrBack); m_crText = m_clrText; m_bLBtnDown = FALSE; m_iconX = GetSystemMetrics (SM_CXMENUCHECK M_ICONY = GETS ystemMetrics (SM_CYMENUCHECK); m_clrHilight = GetSysColor (COLOR_HIGHLIGHT); m_brSelect.CreateSolidBrush (m_clrHilight); m_clrHilightText = GetSysColor (COLOR_HIGHLIGHTTEXT); ZeroMemory ((PVOID) & m_lf, sizeof (LOGFONT)); NONCLIENTMETRICS nm; nm.cbSize = sizeof (NONCLIENTMETRICS) ; // Get the system metrics for the Captionfromhere VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, & nm, 0)); m_lf = nm.lfMenuFont; m_iMenuHeight = nm.iMenuHeight; m_fontMenu.CreateFontIndirect (& m_lf);} CCustomMenu :: ~ CCustomMenu ( ) {IF ((hbrush) m_brbackground! = Null) m_brbackground.deleteObject (); if ((hfont) m_fontmenu! =
NULL) m_fontMenu.DeleteObject (); if ((HBRUSH) m_brSelect = NULL) m_brSelect.DeleteObject ();!!} //// CCustomMenu message handlersvoid CCustomMenu :: DrawItem (LPDRAWITEMSTRUCT lpDIS) {ASSERT (lpDIS = NULL); CDC * PDC = CDC :: fromHandle (LPDIS-> HDC); CRECT Rect; Hicon Hicon; ColorRef crText = m_crtext; // Draw the color (& lpdis-> rcitem); // Draw the Up / DOWN / focused / disabled state UINT action = lpDIS-> itemAction; UINT state = lpDIS-> itemState; CString strText; LOGFONT lf; lf = m_lf; CFont dispFont; CFont * pFont; // GetWindowText (strText); if (lpDIS-> itemData ! = Null) {strText = ((Menudata *) (LPDITA *)) -> Menutext); if (((((MenuData *) (LPDITA *)) -> MenuiconNormal) == -1) Hicon = NULL; Else IF (state & ods_selected) {IF (((MenuData *) (LPDITA *)) -> MenuiconSelected)! = -1) Hicon = AFXGetApp () -> Loadicon (((Menu) Data *) (lpdis-> itemdata)) -> Menuiconselected; else Hicon = AFXGetApp () -> Loadicon ((Menudata *) (LPDITA *) ((MenuDis-> ItemData)) -> MenuiconNormal);} else Hicon = AFXGetApp () - > Loadicon ((Menudata *) (LPDITA *)) -> Menuiconnormal); Trace1 ("DRAW for% S / N", strText);} else {straText.empty (); hicon = null;} (State & ODS_SELECTED) {// DRAW The Down Edges CPEN * POLDPEN = PDC-> SelectObject (& M_Penback);
// You need only Text highlight and thats what you get if (m_hilightStyle = Normal!) {PDC-> FillRect (rect, & m_brBackground);} else {pDC-> FillRect (rect, & m_brSelect);} pDC-> SelectObject (pOldPen ); pDC-> draw3dRect (rect, GetSysColor (COLOR_3DHILIGHT), GetSysColor (COLOR_3DSHADOW)); lf.lfWeight = FW_BOLD;! if ((HFONT) dispFont = NULL) dispFont.DeleteObject (); dispFont.CreateFontIndirect (& lf); crText = m_clrHilightText; // While selected move the text a bit TRACE0 ( "SELECT, SELECTED / n");} else {CPen * pOldPen = pDC-> SelectObject (& m_penBack); pDC-> FillRect (rect, & m_brBackground); pDC- > SelectObject (pOldPen); // draw the up edges pDC-> draw3dRect (rect, m_clrBack, m_clrBack); if (! (HFONT) dispFont = NULL) dispFont.DeleteObject (); dispFont.CreateFontIndirect (& lf); // Normal Trace0 ("SELECT, N ORMAL / N ");} // Draw the text if there is any // we have to pieint the text only if The image is nonexistantiff {ix (DrawiconeX (PDC-> getsafehdc (), Rect .lef, rect.top, hiconx: 32, (m_icony)? M_ICONY: 32, 0, NULL, DI_NORMAL) ("Wrote the icon success / n"); Else Trace0 ("Sorry. NOGO / N ");} // this is neededing Always So That We can have the space for check marks Rect.Left = Rect.Left ((m_iconx)? M_iconx: 32); if (! StrText.isempty ()) {// pfont-> getLogfont (& lf); int ioldmode = PDC->
GetBkmode (); PDC-> setBkmode (transparent); PDC-> setTextColor (CRText); PFont = PDC-> SelectObject (& Dispfont); Trace1 ("About to DrawText% S / N", Strtext); PDC-> DrawText Strtext, Rect, DT_LEFT | DT_SINGLINE | DT_VCENTER; Trace0 ("DONE / N"); PDC-> setBkmode (ioldmode); PDC-> SelectObject (PFont); // set it to the old font} dispfont.deleteObject () ;} void CCustomMenu :: MeasureItem (LPMEASUREITEMSTRUCT lpMIS) {CDC * pDC = AfxGetApp () -> m_pMainWnd-> GetDC (); CFont * pFont = pDC-> SelectObject (& m_fontMenu); int iconX = 0, iconY = 0; TEXTMETRIC TM; PDC-> GetTextMetrics (& TM); PDC-> SelectObject (pfont); AFXGetApp () -> m_pmainwnd-> releasedc (PDC); if (m_iconx) iconx = m_iconx; if (m_icony) icony = m_icony; lpmis-> itemwidth = iconx tm.tmavecharwidth * lstrlen ((Menudata *) (lpmis-> itemdata)) -> menutext) 10; lpmis-> itemHeight = (icony> (m_imenuheight 1))? Icony: m_imenuheight 1; } void ccustomMenu :: seticons ize (int width, int height) {m_iconX = width; m_iconY = height;} void CCustomMenu :: SetTextColor (COLORREF clrText) {m_crText = clrText;} void CCustomMenu :: SetBackColor (COLORREF clrBack) {m_clrBack = clrBack; if (( ! HBRUSH) m_brBackground = NULL) m_brBackground.DeleteObject (); m_brBackground.CreateSolidBrush (clrBack);} void CCustomMenu :: SetHighlightColor (COLORREF clrHilight) {m_clrHilight = clrHilight;! if ((HBRUSH) m_brSelect = NULL) m_brSelect.DeleteObject () ; M_BRSELECT.CREATESOLIDBRUSH (CLRHIGHT);