11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 2. Menu<br />

void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)<br />

{<br />

if(nID == ID_RESUME)GetSystemMenu(TRUE);<br />

if(nID == ID_QUESTION)AfxMessageBox("Question");<br />

CFrameWnd::OnSysCommand(nID, lParam);<br />

}<br />

2.6 Owner-Draw Menu<br />

When we highlight a bitmap menu item by selecting it using mouse, the bitmap will be inversed. We<br />

have no way of modifying this property because function CMenu::ModifyMenu(…) requires only one<br />

bitmap, which will be used to implement menu item’s normal state. The other states of a bitmap menu item<br />

will be drawn using the default implementations. Normally this is good enough. However, sometimes we<br />

may want to use different bitmaps to represent a menu item’s different states: selected, unselected, checked,<br />

unchecked, grayed or enabled.<br />

Also, sometimes we may want to paint a menu item dynamically. Suppose we need to create a “Color”<br />

menu item: the menu item represents a color that the user can use, and this color can be modified to<br />

represent any available color in the system. To implement this type of menu item, we can paint it using the<br />

currently selected color. In this case it is not appropriate to create the menu item using bitmap resources:<br />

there may exist thousands of available colors in the system, and it is just too inconvenient to prepare a<br />

bitmap resource for each possible color.<br />

The owner-draw menu can help us build more powerful user interface. With this type of menu, we can<br />

draw the menu items dynamically, using different bitmaps to represent different states of the menu item.<br />

We can also change the associated bitmaps at any time.<br />

Overriding Two Functions<br />

The implementation of owner draw menu is not very difficult, all we need is to override two member<br />

functions of class CMenu: CMenu::MeasureItem(…) and CMenu::DrawItem(…).<br />

By default, the menu is drawn by the system. We can change this attribute by specifying MF_OWNERDRAW<br />

style for a menu. Any menu with this style will be drawn by its owner. Since a menu’s owner is usually the<br />

mainframe window (in SDI and MDI applications), we can add code to class CMainFrame to implement<br />

dynamic menu drawing. Actually, the menu drawing has two associated messages: WM_MEASUREITEM and<br />

WM_DRAWITEM. When a menu item with MF_OWNERDRAW style needs to be drawn, the menu sends out the<br />

above two messages to the mainframe window. The mainframe window finds out the pointer to the<br />

corresponding menu and calls functions CMenu::MeasureItem(…) and CMenu::DrawItem(…). Here, the first<br />

function is used to retrieve the dimension of the menu item, which can be used to calculate its layout. The<br />

second function implements menu drawing. We need to override it in order to implement custom interface.<br />

One simple and most commonly used way to provide graphic interface is to prepare a bitmap resource<br />

then load and draw it at run time. Please note that this is different from preparing a bitmap resource and<br />

calling CMenu::ModifyMenu(…) to associate the bitmap with a menu item. If we implement drawing by<br />

ourselves, we can manipulate drawing details. For example, when drawing the bitmap, we can change the<br />

size of the image, add a text over it. If we assign the bitmap to the menu item, we lose the control over the<br />

details of painting the bitmap.<br />

Drawing a Bitmap<br />

To draw a bitmap, we need to understand some basics on graphic device interface (GDI). This topic<br />

will be thoroughly discussed from chapter 8 through 12, here is just a simple discussion on bitmap drawing.<br />

In Windows operating system, when we want to output objects (a pixel, a line or a bitmap) to the screen,<br />

we can not write directly to the screen. Instead, we must write to the device context (DC). A device context<br />

is a data structure containing information about the drawing attributes of a device (typically a display or a<br />

printer). We can use DC to write text, draw pixels, lines and bitmaps to the devices. In <strong>MFC</strong> the device<br />

context is supported by class CDC, which has many functions that can let us draw different types of objects.<br />

50

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

Saved successfully!

Ooh no, something went wrong!