11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 2. Menu<br />

Because the popup menu is attached to variable CMenuDoc::m_menuModified, we need to detach it<br />

before application exits. The best place of implementing this is in class MCMenu’s destructor, when the menu<br />

object is about to be destroyed:<br />

MCMenu::~MCMenu()<br />

{<br />

Detach();<br />

}<br />

Now we can compile the sample project and execute it. By executing command Edit | Insert Dynamic<br />

Menu and expanding Dynamic Menu then selecting the first two menu items, we will see that both<br />

selected and unselected states of them will be implemented by our own bitmaps.<br />

Bitmap is not restricted to only indicating selected and normal menu states. With a little effort, we<br />

could also use bitmap to implement other menu states: grayed, checked, and unchecked. This will make our<br />

menu completely different from a menu implemented by plain text.<br />

2.7 Changing the Whole Menu Dynamically<br />

If we write MDI application, we can see that the main menu may change with different type of views.<br />

Generally, when there is no client window opened, the mainframe menu will have only three sub-menus<br />

(File, View, Help). After the user opens a client window, the mainframe menu will be replaced with a new<br />

menu that has more sub-menus. Although we could call CMenu::ModifyMenu(…) to implement this, it is not<br />

efficient because with this method, we have to the change menu items one by one. Actually, there is<br />

another easy way to change the whole menu dynamically: we can prepare a new menu resource, use it to<br />

replace the menu currently associated with the window at run time.<br />

Class CWnd has a member function that can be used to set a window’s menu dynamically:<br />

CWnd::SetMenu(…). The function has only one parameter, which is a CMenu type pointer. By using this<br />

function, we can change an application’s mainframe menu at any time we want. Sample 2.7\Menu<br />

demonstrates this technique. It is a standard SDI application generated by Application Wizard with all<br />

default settings. In the sample, besides mainframe menu IDR_MAINFRAME, a new menu resource<br />

IDR_MAINFRAME_ACTIVE is prepared in the application. This menu has some new sub-menus (Options,<br />

Properties, Settings). For the purpose of demonstration, none of these sub-menus contains menu items.<br />

The default menu will be changed to this menu after we execute File | New or File | Open command. If we<br />

execute File | Close command from menu IDR_MAINFRAME_ACTIVE, the default menu will be resumed.<br />

Three WM_COMMAND message handlers for commands ID_FILE_NEW, ID_FILE_OPEN and ID_FILE_CLOSE<br />

are generated using class wizard. The member functions are named OnFileNew, OnFileOpen and<br />

OnFileClose. In the first two functions, we change the mainframe menu to IDR_MAINFRAME_ACTIVE, and in<br />

the third function, we change the menu back to IDR_MAINFRAME:<br />

void CMenuDoc::OnFileNew()<br />

{<br />

CMenu menu;<br />

}<br />

menu.LoadMenu(IDR_MAINFRAME_ACTIVE);<br />

AfxGetMainWnd()->SetMenu(&menu);<br />

AfxGetMainWnd()->DrawMenuBar();<br />

menu.Detach();<br />

void CMenuDoc::OnFileOpen()<br />

{<br />

CMenu menu;<br />

}<br />

menu.LoadMenu(IDR_MAINFRAME_ACTIVE);<br />

AfxGetMainWnd()->SetMenu(&menu);<br />

AfxGetMainWnd()->DrawMenuBar();<br />

menu.Detach();<br />

55

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!