📄 owner_drawn_menu3.shtml
字号:
<HTML><HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> <META NAME="Author" CONTENT="Zafir Anjum"> <TITLE>Menu - Owner Drawn Menu with Icons (3)</TITLE></HEAD><body background="../fancyhome/back.gif" bgcolor="#FFFFFF" link="#B50029" vlink="#8E2323" alink="#FF0000" bgproperties="fixed"><table WIDTH="100%"><tr WIDTH="100%"><td align=center><!--#exec cgi="/cgi/ads.cgi"--><td></tr></table><CENTER><H3><FONT COLOR="#AOAO99">Owner Drawn Menu with Icons (3)</FONT></H3></CENTER><CENTER><H3><HR></H3></CENTER>This article was contributed by <A HREF="mailto:corkum@rocscience.com">Brent Corkum</A>. Brent hasalso made this page available at his web site at <A HREF="http://www.rocscience.com/~corkum/BCMenu.html">http://www.rocscience.com/~corkum/BCMenu.html</A>where it is likely to get updated earlier than this page.<P><IMG SRC="owner_drawn_menu3.gif" ALIGN="LEFT" HSPACE=12 WIDTH=154 HEIGHT=241> <A HREF="bcmenu23.zip">Download Source Code and Example</A><br><p>This class, <b>BCMenu</b>, implements owner drawn menus derived from the CMenu class. The purpose of which is to mimic the menu style used in Visual C++ 5.0 and MS Word. I can't take credit for all the code, some portions of it were taken from code supplied by BenAshley and Girish Bharadwaj. The difference between their codes and this one is quitesimple, this one makes it very easy to build those cool menus with bitmaps into your application. I've removed the Icon loading stuff and replaced it with Bitmaps. The bitmaps allow you to use the 16X15 toolbar bitmaps directly from your toolbars in theresource editor. As well, there is no scaling of the bitmaps so they always look good.You can also load Bitmap resources and define bitmaps for your check marks. I've alsoadded the default checkmark drawing stuff, separators, proper alignment of keyboard accelerator text, keyboard shortcuts, proper alignment of popup menu items, propersystem color changes when the Display Appearance changes, plus bug fixes to the BenAshley's LoadMenu function for complex submenu systems. I made quite a few othermodifications as well, too many to list or remember. I also use the disabledbitmap dithering function of Jean-Edouard Lachand-Robert to create the disabledstate bitmaps. I must admit, it does a much better job then the DrawState() function. If you find any bugs, memory leaks, or just better ways of doing things, please let me know. I used Visual C++ 5.0 and I have not tested compatibility with earlier VC versions. I've tested it on Win 95/NT at various resolutions and color palette sizes.</H4><p>Well, enough of the boring stuff, lets talk about implementation. To make it easy I'm first going to list step by step the method for implementing the menus into a MDI application:<OL><LI>Create your MDI application using the App Wizard.</LI><LI>Insert the BCMenu.cpp and BCMenu.h files into your Workspace.</LI><LI>Add the following public member functions to your CMainFrame class in the MainFrm.h header file:</LI><FONT COLOR="#990000"><PRE>HMENU NewMenu();HMENU NewDefaultMenu();</PRE></FONT><LI>Add the following public member variables to your CMainFrame class in the MainFrm.h header file:</LI><FONT COLOR="#990000"><PRE>BCMenu m_menu,m_default;</PRE></FONT><LI>Add the line:</LI><FONT COLOR="#990000"><PRE>#include "BCMenu.h"</PRE></FONT><P>to the top of the MainFrm.h header file.</P><LI>Open the Mainfrm.cpp implementation file and add the NewMenu and NewDefaultMenu member functions as listed below. <B>IMPORTANT:</B> Make sure you replace the IDR_MYMENUTYPE menu id in the below LoadMenu call to the menu id associated with the menu's in your application. Look in the menus folder of the Resources view.</LI><FONT COLOR="#990000"><TT><PRE>HMENU CMainFrame::NewMenu(){ static UINT toolbars[]={ IDR_MAINFRAME, IDR_TOOLBAR }; // Load the menu from the resources m_menu.LoadMenu(IDR_MYMENUTYPE); // ****replace IDR_MENUTYPE with your menu ID**** // Use ModifyODMenu to add a bitmap to a menu options.The first parameter // is the menu option text string.If it's NULL, keep the current text // string.The second option is the ID of the menu option, or the menu // option text (can use this for adding bitmaps to popup options) to change. // The third option is the resource ID of the bitmap.This can also be a // toolbar ID in which case the class searches the toolbar for the // appropriate bitmap.Only Bitmap and Toolbar resources are supported. m_menu.ModifyODMenu(NULL,ID_WINDOW_NEW,IDB_WINDOW_NEW); m_menu.ModifyODMenu(NULL, "&Tile",IDB_WINDOW_TILE); // Another method for adding bitmaps to menu options is through the // LoadToolbars member function.This method allows you to add all // the bitmaps in a toolbar object to menu options (if they exist). // The first function parameter is an array of toolbar id's. // The second is the number of toolbar id's. There is also a // function called LoadToolbar that just takes an id. m_menu.LoadToolbars(toolbars,2); return(m_menu.Detach());}HMENU CMainFrame::NewDefaultMenu(){ m_default.LoadMenu(IDR_MAINFRAME); m_default.LoadToolbar(IDR_MAINFRAME); return(m_default.Detach());}</PRE></FONT></tt><LI>Edit the InitInstance() member function of your CWinApp derived class and add following highlighted code in the position noted:</LI><FONT COLOR="#990000"><TT><PRE>// create main MDI Frame windowCMainFrame* pMainFrame = new CMainFrame;if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;m_pMainWnd = pMainFrame;// This code replaces the MFC created menus with the Ownerdrawn versions pDocTemplate->m_hMenuShared=pMainFrame->NewMenu();pMainFrame->m_hMenuDefault=pMainFrame->NewDefaultMenu();// This simulates a window being opened if you don't have// a default window displayed at startuppMainFrame->OnUpdateFrameMenu(pMainFrame->m_hMenuDefault);// Parse command line for standard shell commands, DDE, file openCCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);</PRE></font></tt><LI>Add the message handlers for the WM_MEASUREITEM, WM_MENUCHAR, and WM_INITMENUPOPUP messages to your CMainFrame class. Do this by right clicking on the CMainFrame class in the ClassView and selecting <I>Add Windows Message Handler</I>. Choose the <I>Window</I> option from the <I>Filter for messages available to class</I> combo box. Select the message and add the handler. Then edit the handler and add the below code.</LI><FONT COLOR="#990000"><TT><PRE>//This handler ensure that the popup menu items are drawn correctlyvoid CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) { BOOL setflag=FALSE; if(lpMeasureItemStruct->CtlType==ODT_MENU){ if(IsMenu((HMENU)lpMeasureItemStruct->itemID)){ CMenu* cmenu=CMenu::FromHandle((HMENU)lpMeasureItemStruct->itemID); if(m_menu.IsMenu(cmenu)||m_default.IsMenu(cmenu)){ m_menu.MeasureItem(lpMeasureItemStruct); setflag=TRUE; } } } if(!setflag)CMDIFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);}//This handler ensures that keyboard shortcuts workLRESULT CMainFrame::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) { LRESULT lresult; if(m_menu.IsMenu(pMenu)||m_default.IsMenu(pMenu)) lresult=BCMenu::FindKeyboardShortcut(nChar, nFlags, pMenu); else lresult=CMDIFrameWnd::OnMenuChar(nChar, nFlags, pMenu); return(lresult);}//This handler updates the menus from time to timevoid CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) { CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); if(!bSysMenu){ if(m_menu.IsMenu(pPopupMenu)||m_default.IsMenu(pPopupMenu)) BCMenu::UpdateMenu(pPopupMenu); }}</PRE></FONT></TT><LI>If you are debugging or you are mixing standard menus with the BCMenu's (maybe you have different Document templates using the standard menu's) then you should turn on RTTI in the project settings.</LI></OL><p>Well, that's it. Compile the program and look in the File menu. You should see the bitmaps.I've tried the menus with context menus and they seem to work fine. I also have a small
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -