Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
168
Добавлен:
24.05.2014
Размер:
25.78 Mб
Скачать

70

Part I

INTRODUCING VC++.NET

 

 

 

 

 

 

Y

 

 

L

 

 

F

 

 

M

 

FIGURE 3-11 Window displaying the application interface

 

A

 

 

E

 

Summary

T

 

 

 

 

 

In this chapter, you learned about creating an MFC application by using the MFC Application Wizard. The MFC Application Wizard enables you to create different types of MFC application frameworks, such as frameworks for SDI, MDI, and dialog-based applications. You also learned about the different classes that the application framework generates. Next, you learned about customizing the framework of the application that the MFC Application Wizard has generated. You learned to add controls to that form and add member variables to the form controls. Finally, you learned to transfer and validate data by using the DDX and DDV mechanism. You also learned to add event handlers for the control events.

Team-Fly®

Chapter 4

Working with

Menus, Dialog

Boxes, and

Window Controls

In Chapter 3, you were introduced to the MFC Application Wizard. In this chapter, you will learn to create menus and dialog boxes, and use different win-

dow controls in an application.

Creating Menus

In almost all applications that you have worked with, you have used menus. Hence, you can easily conclude that menus are one of the most commonly used user-interface components. A menu logically groups the functionality that an application provides. In Visual C++, such user-interface components are treated as resources and are stored in a separate file called the resource script file, which has the extension .rc. Corresponding to the .rc file, the wizard creates a resource.h file that defines the resources.

To create a menu for your application, you need to first design the menu using the resource editor and then code your application to display the menu and handle the menu commands.

Creating a Menu Resource

You will now learn how to design a menu using the resource editor. Here are the steps that you need to follow:

1.Select View, Resource View to display the Resource View pane. From the list of resources, select Menu.

2.Select Project, Add Resource to open the Add Resource dialog box, and select Menu.

3.Click the New button. A new menu resource is added to the project.

4.Enter the caption of the menu option.

5.Use the Properties window to edit the menu option’s properties, such as its ID.

MENUS, DIALOG BOXES, AND WINDOW CONTROLS

Chapter 4

 

73

 

 

 

 

 

NOTE

To display the Properties window, choose View, Properties Window.

After creating the menu resource, you need to code to display the menu.

Code to Display a Menu

MFC allows you to display a menu in two ways: by attaching it directly to the application’s frame window, or by using the CMenu class member functions. The MFC Application Wizard follows the first approach. The following is the code generated by the wizard that loads the application’s menu. I have highlighted the code that loads and displays the menu.

//MenuApp.cpp – File that defines the application class BOOL CMenuAppApp::InitInstance()

{

CWinApp::InitInstance();

CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame;

//create and load the frame with its resources pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,

NULL, NULL);

pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE;

}

Continuing the discussion about how the wizard handles menus, as listed in the preceding code, the wizard instantiates the CMainFrame class and initializes the variable m_pMainWnd to point to the application’s frame window. Using the LoadFrame member function, it creates and loads the frame window. The first parameter of the function, IDR_MAINFRAME, is the ID of the menu that needs to be displayed. This is the ID of the default menu created by the wizard that you can edit.

74

 

Part I

INTRODUCING VC++.NET

 

 

 

 

 

On the other hand, if required, you can design your own menu and load it instead of the predefined menu. It is quite simple to do this. You simply need to edit the first parameter of the LoadFrame function to specify the ID of the menu that you have created, instead of IDR_MAINFRAME.

NOTE

Even if you are coding the entire application instead of using the wizard, you can follow the same method to handle the menu.

So far, this discussion has addressed the first approach to displaying a menu, wherein the menu is attached directly to the frame window. The second approach enables you to use the CMenu class to handle the menu. The CMenu class provides you with member functions that you can use to create, load, and manipulate the menu. By using the CMenu class and the CFrameWnd class member functions, you can create a menu. These are the steps to follow:

Edit your application’s window class.

Edit the InitInstance function of the application class.

Invoke the DestroyWindow function.

You can perform the first two steps out of sequence, while invoking the DestroyWindow function should be the last step that you perform. The first two steps have subtasks that have to be performed in the given sequence, as described next.

Edit your application’s window class to do the following:

1.Create a CMenu pointer while declaring the attributes of the window class.

2.Within the constructor, allocate memory for the CMenu pointer, create the frame window (without attaching the menu here), and then use the LoadMenu member function to load the menu into the application’s memory.

3.Use the SetMenu function to set the created menu as the application’s current menu.

Edit the InitInstance function of the application class to do the following:

1.Instantiate an object for the window class and assign it to the

m_pMainWnd variable.

MENUS, DIALOG BOXES, AND WINDOW CONTROLS

Chapter 4

 

75

 

 

 

 

 

2.Invoke the ShowWindow function to display the window along with the menu.

Invoke the DestroyWindow function from within the destructor of the application’s window class to destroy the pointer to the menu, and hence the menu, before exiting the application.

The following code snippet depicts the steps just described:

//MainFrame.h

class CMainFrame : public CFrameWnd

{

// Attributes public:

CMenu *mMenu;

};

//MainFrame.cpp

CMainFrame::CMainFrame()

{

mMenu=new CMenu;

Create(0, “My Application Window”); mMenu->LoadMenu(IDR_MAINFRAME); SetMenu(mMenu);

}

CMainFrame::~CMainFrame()

{

DestroyMenu(HMENU(mMenu));

}

//MyMenu.cpp

BOOL CMenuAppApp::InitInstance()

{

CWinApp::InitInstance();

CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame;

//create and load the frame with its resources pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow();

return TRUE;

}

76

 

Part I

INTRODUCING VC++.NET

 

 

 

 

 

When you create an application using the wizard, you have the flexibility to use the default menus provided (or tailor them according to your requirements) or to create new menus, if required. A little time must be spent understanding how this works for SDI and MDI applications:

In an SDI application, the default menu created is IDR_MAINFRAME and is attached to the main window of the application. So, if required, you can either edit this menu or add a new one. To load the new menu, say

IDR_MENU1, you will need to edit the InitInstance function of the application class as follows:

pFrame->LoadFrame(IDR_MENU1, WS_OVERLAPPEDWINDOW | WS_ADDTOTITLE,

NULL,

NULL);

Since SDI applications support a single-frame window, which is the main frame, it can support only a single menu. Hence, at a time, you can either attach the default menu, IDR_MAINFRAME, or the menu that you defined, IDR_MENU1.

In an MDI application, the default menu created by the wizard is IDR_MAINFRAME, which is attached to the application’s main window. In addition, if you recall, an MDI application creates a child window for each new document that you create. For each of these child windows, the wizard creates another menu. You have the option to edit both of these menus or to create a new menu and attach it to the appropriate window. For instance, if you want the new menu to be accessible to both the main and child windows, you can attach the new menu to the main window. On the other hand, if you want to access the menu only from child windows, then you attach the menu to the child window. Here’s the code generated by the wizard that loads the appropriate menu:

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_MDIAppTYPE, RUNTIME_CLASS(CMDIAppDoc), RUNTIME_CLASS(CChildFrame),

// custom MDI child frame

RUNTIME_CLASS(CMDIAppView));

AddDocTemplate(pDocTemplate);

MENUS, DIALOG BOXES, AND WINDOW CONTROLS

Chapter 4

 

77

 

 

 

 

 

// create main MDI Frame window

CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;

In the preceding code, IDR_MAINFRAME refers to the menu that will be attached to the main application window, and IDR_MDIAppTYPE refers to the menu that will be attached to the child windows.

Handling Menu

So far, you have looked at the process of adding a menu to your application. However, the work is not complete unless your application can handle the menu. So, the next step will be to enable your application to handle the messages generated when a user makes use of the menu. To accomplish this, obviously, you need to add message handlers. With different classes involved in an MFC application, the next question that arises is, which class will handle the messages? Well, you can designate the frame window class or the application class or the view class to act as the message-handling class. Right from selecting the message-handling class to adding the message handlers can be done quickly and with ease by using the Event Handler Wizard. Here’s what you have to do:

1.Switch to Resource View.

2.Right-click the appropriate menu item.

3.Select Add Event Handler from the shortcut menu. The Event Handler Wizard, as shown in Figure 4-1, starts. The wizard consists of a Message type list, from which you choose the type of message to be trapped, and a Class list, from which you choose the class that will handle the messages. Additionally, you can edit the message handler function name that appears in the Function handler name box.

4.Click the Add and Edit button to add the message handler and edit its code. The message handler is added to the class that is designated as the message-handling class. The function declaration is added to the .h file while the function definition is added to the .cpp file. The wizard also creates the corresponding message map entry.

78

 

Part I

INTRODUCING VC++.NET

 

 

 

 

 

FIGURE 4-1 The Event Handler Wizard

Creating a Sample Menu

Now you will implement the concepts discussed thus far. You will be creating a simple application (one that is not based on the Document/View architecture) with a sample menu. You will also add the required message handlers to it. Suppose that you want to add a menu option, say Draw, which will provide some drawing functionality for your application. Instead of creating a new menu, you decide to edit the default one. Here’s the way to go:

1.Create an SDI application using the MFC Application Wizard. The application’s name in the sample code is MenuApp.

2.Switch to Resource View and open the default menu, IDR_MAINFRAME, for editing.

3.Add the options shown in Figure 4-2.

4.Right-click each of the options, for example Line, and choose Add Event Handler to start the wizard.

5.From the Class list, select the required class. In the sample code given, the application class, CMenuApp, has been designated as the message-han- dling class.

6.Click on the Add and Edit button. The wizard adds the function declaration in the header file of the view class and generates the body for

MENUS, DIALOG BOXES, AND WINDOW CONTROLS

Chapter 4

 

79

 

 

 

 

 

FIGURE 4-2 The sample menu

defining the function in the cpp class. The following are the code snippets of the message handler generated by the wizard:

//MenuApp.h

class CMenuApp : public CWinApp

{

public:

afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() afx_msg void OnDrawLine();

};

//MenuApp.cpp BEGIN_MESSAGE_MAP(CMenuApp, CWinApp)

ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

ON_COMMAND(ID_DRAW_LINE, OnDrawLine)

END_MESSAGE_MAP()

void CMenuApp::OnDrawLine()

{

// TODO: Add your command handler code here

}

You can add the required code to draw a line in the OnDrawLine function. Similarly, you can add the message handlers for the rest of the menu options. Based on the option selected, the framework invokes the appropriate message handler. For instance, when a user selects Draw, Line, the OnDrawLine message handler of the application class is invoked.

After revisiting one of the basic user-interface components, it’s now time to visit yet another basic and commonly used user-interface component — the dialog box.