6.2 Determine What Messages Will Be Handled

This section explains the fourth step in writing Phone Book: determine what messages will be handled and add the message map for class CMainWindow. This will be accomplished in several steps:

1.Plan the message handlers.

2.Add the message map for class CMainWindow.

3.Add the class declaration for CMainWindow.

4.Add a constructor definition.

·To plan the message handlers:

Determine what message handlers are needed.

The Phone Book program requires about twenty message-handlers, which fall into several categories:

Menu-command handlers will be needed. These are handler functions for WM_COMMAND messages. Windows passes a menu-command ID number with each such message. These handlers will be named after the menu commands they handle.

The program requires handler functions for Windows creation and sizing messages: WM_CREATE, and WM_SIZE.

The program requires handler functions for scrolling: WM_VSCROLL and WM_HSCROLL.

The program also requires handler functions for several specific keystrokes (including the F1 function key, which is used to summon help): the UP ARROW, DOWN ARROW, RIGHT ARROW, and LEFT ARROW keys, the PAGE UP, PAGE DOWN, HOME, and END keys. These keys allow the user to move a “selection” from line to line on the display and to scroll the display.

The program also requires message handlers for mouse clicks. If the user presses the left mouse button in the display area of the program's window, the selection is moved to the clicked line of text. This requires a message-handler function for the WM_LBUTTONDOWN message. If the user double-clicks the left mouse button in a line of the display, a WM_LBUTTONDBLCLK message invokes the Edit command in the Person menu, displaying data for the double-clicked person.

The program requires a handler function for the paint message, WM_PAINT.

Keys That Don't Need Message Handlers

The DELETE and ENTER keys are handled by mapping the keys to the IDM_DELETE and IDM_EDIT menu ID numbers. This is done in the accelerator table resource template in PHBOOK.RC. The relevant lines look like this (don't add this code to your files yet):

VK_DELETE, IDM_DELETE, VIRTKEY VK_RETURN,...IDM_EDIT, VIRTKEY

The VK_DELETE and VK_RETURN lines do the mapping. This mapping causes the message-handler functions for the Delete and Edit commands in the Person menu to be invoked when the user presses the keys. Because DELETE and ENTER can be handled this way, it's unnecessary to provide explicit handlers for these keys.

Your goal in this chapter is to create a VIEW.CPP file that matches the one in Listing 2 in Chapter 5. In that listing, the CMainWindow member functions are given in the following groupings:

Menu-command handlers for all menus

Phone Book has File, Person, and Help menus.

Creation and sizing handlers

These handle the WM_CREATE and WM_SIZE messages.

Scrolling handlers

These handle the vertical and horizontal scrollbars.

Keyboard and mouse handlers

These handle keystrokes and mouse clicks.

The paint handler

This handles the WM_PAINT message.

Utilities

These are member functions that support the message-handler functions but are not themselves message-handlers.

Occasionally you'll be asked to add a function out of this order so it can be discussed with related functions. In the few such cases, you'll be told where to add the function so your file maintains the same order as Listing 2 in Chapter 5.

·To add the message map and message-handlers:

Start adding code to your files by adding message map entries for the message-handler functions. You'll add a message map to VIEW.CPP and a main window class declaration to VIEW.H.

Replace the old message map for Hello with the following message map for class CMainWindow in your VIEW.CPP file:

BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )

// File menu commands:

ON_COMMAND( IDM_NEW, OnNew )

ON_COMMAND( IDM_OPEN, OnOpen )

ON_COMMAND( IDM_SAVE, OnSave )

ON_COMMAND( IDM_SAVEAS, OnSaveAs )

ON_COMMAND( IDM_CLOSE, OnDBClose )

ON_COMMAND( IDM_PRINT, OnPrint )

ON_COMMAND( IDM_EXIT, OnExit )

// Person menu commands:

ON_COMMAND( IDM_ADD, OnAdd )

ON_COMMAND( IDM_DELETE, OnDelete )

ON_COMMAND( IDM_EDIT, OnEdit )

ON_COMMAND( IDM_FIND, OnFind )

ON_COMMAND( IDM_FINDALL, OnFindAll )

// Help menu commands:

ON_COMMAND( IDM_HELP, OnHelp )

ON_COMMAND( IDM_ABOUT, OnAbout )

// Selection accelerators:

ON_COMMAND( VK_UP, OnUp )

ON_COMMAND( VK_DOWN, OnDown )

// Other Windows messages:

ON_WM_CREATE()

ON_WM_CLOSE()

ON_WM_SIZE()

ON_WM_VSCROLL()

ON_WM_HSCROLL()

ON_WM_LBUTTONDOWN()

ON_WM_LBUTTONDBLCLK()

ON_WM_KEYDOWN()

ON_WM_PAINT()

END_MESSAGE_MAP()

As you saw in the Hello program, this message map connects Windows messages with message-handler member functions defined by the CMainWindow class. Notice that the message map also provides the names of the message-handler functions. You'll add the handler functions for these map entries in the next several sections.

·To add the CMainWindow class declaration:

Add the following code to VIEW.H:

// CMainWindow

// The window object that WinApp creates. In this program we

// only use one window class. In that sense this object does

// all the work that makes our window a CPersonList viewer.

//

class CMainWindow : public CFrameWnd

{

private:

// Variables that contain the window size, font size and scroll

// position.

int m_cxChar;

int m_cyChar;

int m_nHscrollPos;

int m_nVscrollPos;

int m_cxCaps;

int m_nMaxWidth;

int m_cxClient;

int m_cyClient;

int m_nVscrollMax;

int m_nHscrollMax;

int m_nSelectLine;

CDataBase m_people;

// Private helpers for the other routines.

void SetMenu();

BOOL Save( BOOL bNamed=FALSE );

BOOL FileDlg( BOOL bOpen, int nMaxFile, LPSTR szFile,

int nMaxFileTitle, LPSTR szFileTitle );

BOOL CheckForSave( const char* pszTitle, const char*

pszMessage );

void InvalidateLine();

public:

// The CMainWindow constructor

CMainWindow();

// These routines are all overrides of CWnd. Windows messages

// cause these to be called.

afx_msg int OnCreate( LPCREATESTRUCT cs );

afx_msg void OnClose();

afx_msg void OnSize( UINT type, int x, int y );

afx_msg void OnHScroll( UINT wParam, UINT pos, CWnd* control );

afx_msg void OnVScroll( UINT wParam, UINT pos, CWnd* control );

afx_msg void OnLButtonDown( UINT wParam, CPoint location );

afx_msg void OnLButtonDblClk( UINT wParam, CPoint location );

afx_msg void OnKeyDown( UINT wParam, UINT, UINT );

afx_msg void OnPaint();

// These routines are all menu items. User action causes

// these to be called.

afx_msg void OnNew();

afx_msg void OnOpen();

afx_msg void OnSave();

afx_msg void OnSaveAs();

afx_msg void OnDBClose();

afx_msg void OnPrint();

afx_msg void OnExit();

afx_msg void OnAdd();

afx_msg void OnDelete();

afx_msg void OnFind();

afx_msg void OnFindAll();

afx_msg void OnEdit();

afx_msg void OnHelp();

afx_msg void OnAbout();

afx_msg void OnUp();

afx_msg void OnDown();

DECLARE_MESSAGE_MAP()

};

This class declaration replaces the CMainWindow declaration from Hello. It has the same general form as Hello's version but contains many more member variables and member functions. The declaration also completes your VIEW.H file. Make sure that the final “#endif // __VIEW_H__” line is below all other code in the file.·To add a constructor definition:

Add the following code to file VIEW.CPP below the message map:

CMainWindow() {

VERIFY( LoadAccelTable( "MainAccelTable" ) );

VERIFY( Create( NULL, "Phone Book",

WS_OVERLAPPEDWINDOW, rectDefault, NULL,

"MainMenu" ) );

m_nSelectLine = -1;

}

You can simply replace the contents of Hello's CMainWindow constructor, which you copied when you created VIEW.CPP.

The constructor demonstrates two new features. First, it's used to initialize the m_nSelectLine member variable in the CMainWindow object, something Hello's constructor didn't do.

Second, the constructor invokes the VERIFY macro on the two calls it makes. The result of each call—to LoadAccelTable and Create—is passed to the VERIFY macro. VERIFY works differently depending on whether the _DEBUG flag is set. If it is, the macro “asserts” if the result is zero (FALSE). If the flag is not set, the macro evaluates its argument but does not assert for a zero value. An assertion produces useful diagnostic information. Thus VERIFY is a handy way to check the results of functions that return a Boolean or pointer value. You can leave the VERIFY macros in place when you build a release version. For more information about the VERIFY macro and its companion, the ASSERT macro, see Chapter X in this manual.

Note:

The “afx_msg” prefix on the message-handlers in CMainWindow marks a special set of member functions. The message-map code that you provide creates a mechanism similar in effect to a C++ v-table. The mechanism maps Windows messages to the message-handlers as if they were virtual functions. Because of this mechanism, you can read “afx_msg” as if it meant “virtual,” although the prefix has no effect on compilation. These message-handlers are prototyped in the declaration for class CWnd, in file AFXWIN.H. (This file is included in your distribution disks.) To use the message-handlers in your own class declarations, copy the prototypes you need from AFXWIN.H and paste them into your code.

The message-handler functions from class CWnd are defaults. When you declare your own message-handler with the same name and parameter signature, the result is equivalent to overriding a virtual function. Some of the message-handler declarations in the CMainWindow declaration list parameter types without specifying parameter names. The omitted names mark parameters not used in the Phone Book implementation. If you omit the parameter names, the compiler does not allocate space for those parameters. If you provide names for unused parameters, you'll get compiler warnings.

You'll add the message-handler member functions themselves in subsequent sections of the tutorial. You'll probably want to check your work against Listing 2 in Chapter 5 when you finish, so the following instructions explain where to add each function in the VIEW.CPP file to duplicate the order of functions in that listing. This ordering is a matter of convenience.

To continue the tutorial, see “Add Message-Handlers for File Menu Commands” on page 205. For more information about the steps just completed, see “Discussion: Message-Handler Functions” immediately following.