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

Beginning Visual C++ 2005 (2006) [eng]-1

.pdf
Скачиваний:
108
Добавлен:
16.08.2013
Размер:
18.66 Mб
Скачать

Windows Programming Concepts

 

WINDOWS

 

 

Windows API

 

ProgramStart

API

Messages

API

Calls

Calls

 

 

WinMain()

 

WindowProc()

 

Initialize variables

 

Process messages

 

Define windows

 

 

 

Create windows

 

 

 

 

Your Program

 

Figure 11-5

 

 

 

The WinMain() function does any initialization that’s necessary and sets up the window or windows that are the primary interface to the user. It also contains the message loop for retrieving messages that are queued for the application.

The WindowProc() function handles all the messages for a given window that aren’t queued, which includes those initiated in the message loop in WinMain(). WindowProc(), therefore, ends up handling both kinds of messages. This is because the code in the message loop sorts out what kind of message it has retrieved from the queue, and then dispatches it for processing by WindowProc(). WindowProc() is where you code your application-specific response to each Windows message, which should handle all the communications with the user by processing the Windows messages generated by user actions, such as moving or clicking the mouse or entering information at the keyboard.

639

Chapter 11

The queued messages are largely those caused by user input from either the mouse or the keyboard The non-queued messages for which Windows calls your WindowProc() function directly, are either messages that your program created, typically as a result of obtaining a message from the queue and then dispatching it, or messages that are concerned with window management — such as handling menus and scrollbars, or resizing the window.

The Microsoft Foundation Classes

The Microsoft Foundation Classes (MFC) are a set of predefined classes upon which Windows programming with Visual C++ is built. These classes represent an object-oriented approach to Windows programming that encapsulates the Windows API. MFC does not adhere strictly to the object-oriented principles of encapsulation and data hiding, principally because much of the MFC code was written before such principles were well established.

The process of writing a Windows program involves creating and using MFC objects, or objects of classes derived from MFC. In the main, you’ll derive your own classes from MFC, with considerable assistance from the specialized tools in Visual C++ 2005 that make this easy. The objects of these MFCbased class types incorporate member functions for communicating with Windows, for processing Windows messages, and for sending messages to each other. These derived classes, of course, inherit all of the members of their base classes. These inherited functions do practically all of the general grunt work necessary for a Windows application to work. All you need to do is to add data and function members to customize the classes to provide the application-specific functionality that you need in your program. In doing this, you’ll apply most of the techniques that you’ve been grappling with in the preceding chapters, particularly those involving class inheritance and virtual functions.

MFC Notation

All the classes in MFC have names beginning with C, such as CDocument or CView. If you use the same convention when defining your own classes, or when deriving them from those in the MFC library, your programs will be easier to follow. Data members of an MFC class are prefixed with m_. I’ll also follow this convention in the examples that use MFC.

You’ll find that MFC uses Hungarian notation for many variable names, particularly those that originate in the Windows API. As you recall, this involves using a prefix of p for a pointer, n for an int, l for long, h for a handle, and so on. The name m_lpCmdLine, for example, refers to a data member of a class (because of the m_ prefix) that is of type ‘pointer to long’. This practice of explicitly showing the type of a variable in its name was important in the C environment because of the lack of type checking; because you could determine the type from the name, you had a fair chance of not using or interpreting its value incorrectly. The downside is that the variable names can become quite cumbersome, making the code look more complicated than it really is. Because C++ has strong type checking that picks up the sort of misuse that used to happen regularly in C, this kind of notation isn’t essential, so I won’t use it generally for variables in the examples in the book. I will, however, retain the p prefix for pointers and some of the other simple type denotations because this helps to make the code more readable.

How an MFC Program Is Structured

You know from Chapter 1 that you can produce a Windows program using the Application wizard without writing a single line of code. Of course, this uses the MFC library, but it’s quite possible to write a

640

Windows Programming Concepts

Windows program that uses MFC without using the Application wizard. If you first scratch the surface by constructing the minimum MFC-based program, you’ll get a clearer idea of the fundamental elements involved.

The simplest program that you can produce using MFC is slightly less sophisticated than the example that you wrote earlier in this chapter using the raw Windows API. The example you’ll produce here has a window, but no text displayed in it. This is sufficient to show the fundamentals, so try it out.

Try It Out

A Minimal MFC Application

Create a new project using the File > New > Project menu option, as you’ve done many times before. You won’t use the Application wizard that creates the basic code here, so select the template for the project as Win32 Project and choose the Empty project option in the second dialog. After the project is created, select Project > Ex11_02 properties from the main menu, and on the General sub-page from Configuration Properties, click the Use of MFC property to set its value to Use MFC in a Shared DLL.

With the project created you can create a new source file in the project as Ex11_02.cpp. So that you can see all the code for the program in one place, put the class definitions you need together with their implementations in this file. To achieve this, just add the code manually in the edit window — there isn’t very much of it.

To begin with, add a statement to include the header file afxwin.h, as this contains the definitions for many MFC classes. This allows you to derive your own classes from MFC.

#include <afxwin.h>

// For the class library

To produce the complete program, you’ll only need to derive two classes from MFC: an application class and a window class. You won’t even need to write a WinMain() function, as you did in the previous example in this chapter, because this is automatically provided by the MFC library behind the scenes. Take a look at how you define the two classes that you need.

The Application Class

The class CWinApp is fundamental to any Windows program written using MFC. An object of this class includes everything necessary for starting, initializing, running and closing the application. You need to produce the application to derive your own application class from CWinApp. You will define a specialized version of the class to suit your application needs. The code for this is as follows:

class COurApp: public CWinApp

{

public:

virtual BOOL InitInstance();

};

As you might expect for a simple example, there isn’t a great deal of specialization necessary in this case. You’ve only included one member in the definition of the class: the InitInstance() function. This function is defined as a virtual function in the base class, so it’s not a new function in your derived class; you are simply redefining the base class function for your application class. All the other data and function members that you need in the class you’ll inherit from CWinApp unchanged.

641

Chapter 11

The application class is endowed with quite a number of data members defined in the base, many of which correspond to variables used as arguments in Windows API functions. For example, the member m_pszAppName stores a pointer to a string that defines the name of the application. The member m_nCmdShow specifies how the application window is to be shown when the application starts up. You don’t need to go into all the inherited data members now. You’ll see how they are used as the need arises in developing application-specific code.

In deriving your own application class from CWinApp, you must override the virtual function InitInstance(). Your version is called by the version of WinMain() that’s provided for you by MFC, and you’ll include code in the function to create and display your application window. However, before you write InitInstance(), I should introduce you to a class in the MFC library that defines a window.

The Window Class

Your MFC application needs a window as the interface to the user, referred to as a frame window. You derive a window class for the application from the MFC class CFrameWnd, which is designed specifically for this purpose. Because the CFrameWnd class provides everything for creating and managing a window for your application, all you need to add to the derived window class is a constructor. This enables you to specify a title bar for the window to suit the application context:

class COurWnd: public CFrameWnd

{

public:

// Constructor COurWnd()

{

Create(0, L”Our Dumb MFC Application”);

}

};

The Create() function that you call in the constructor is inherited from the base class. It creates the window and attaches it to the COurWnd object that is being created. Note that the COurWnd object is not the same thing as the window that displayed by Windows — the class object and the physical window are distinct entities.

The first argument value for the Create() function, 0, specifies that you want to use the base class default attributes for the window — you’ll recall that you needed to define window attributes in the previous example in this chapter that used the Windows API directly. The second argument specifies the window name that is used in the window title bar. You won’t be surprised to learn that there are other parameters to the function Create(), but they all have default values which are quite satisfactory, so you can afford to ignore them here.

Completing the Program

Having defined a window class for the application, you can write the InitInstance() function in our

COurApp class:

BOOL COurApp::InitInstance(void)

{

// Construct a window object in the free store m_pMainWnd = new COurWnd;

642

Windows Programming Concepts

m_pMainWnd->ShowWindow(m_nCmdShow);

// ...

and display it

return TRUE;

 

 

}

This overrides the virtual function defined in the base class CWinApp, and as I said previously, it is called by the WinMain() function that’s automatically supplied by the MFC library. The InitInstance() function constructs a main window object for the application in the free store by using the operator new. You store the address that is returned in the variable m_pMainWnd, which is an inherited member of your class COurApp. The effect of this is that the window object is owned by the application object. You don’t even need to worry about freeing the memory for the object you have created — the supplied WinMain() function takes care of any cleanup necessary.

The only other item you need for a complete, albeit rather limited, program is to define an application object. An instance of our application class, COurApp, must exist before WinMain() is executed, so you must declare it at global scope with the statement:

COurApp AnApplication;

// Define an application object

The reason that this object needs to exist at global scope is that it is the application, and the application needs to exist before it can start executing. The WinMain() function that is provided by MFC calls the InitInstance() function member of the application object to construct the window object and, thus, implicitly assumes the application object already exists.

The Finished Product

Now that you’ve seen all the code, you can add it to the Ex11_02.cpp source file in the project. In a Windows program, the classes are usually defined in .h files, and the member functions that are not defined within the class definitions are defined in .cpp files. Your application is so short, though, that you may as well put it all in a single .cpp file. The merit of this is that you can view the whole lot together. The program code is structured as follows:

//Ex11_02.cpp

//An elementary MFC program

#include <afxwin.h>

// For the class library

//Application class definition class COurApp:public CWinApp

{

public:

virtual BOOL InitInstance();

};

//Window class definition

class COurWnd:public CFrameWnd

{

public:

// Constructor COurWnd()

{

Create(0, L”Our Dumb MFC Application”);

}

643

Chapter 11

};

// Function to create an instance of the main application window BOOL COurApp::InitInstance(void)

{

// Construct a window object in the free store m_pMainWnd = new COurWnd;

m_pMainWnd->ShowWindow(m_nCmdShow); // ...and display it return TRUE;

}

// Application object definition at global scope

COurApp AnApplication; // Define an application object

That’s all you need. It looks a bit odd because no WinMain() function appears, but as noted above, there is a WinMain() function supplied by the MFC library.

Now you’re ready to roll, so build and run the application. Select the Build > Build Ex11_02.exe menu item, click the appropriate toolbar button, or just press Ctrl+Shift+B to build the solution. You should end up with a clean compile and link, in which case you can press Ctrl+F5 to run it. Your minimum MFC program appears as shown in Figure 11-6.

Figure 11-6

You can resize the window by dragging the border, move the whole thing around, and minimize or maximize it in the usual ways. The only other function that the program supports is “close,” for which you can use the system menu, the Close button at the upper-right of the window, or just key Alt-F4. It doesn’t look like much, but, considering that there are so few lines of code, it’s quite impressive.

644

Windows Programming Concepts

Using Windows Forms

A Windows form is an entity that represents a window of some kind. By a window I mean window in its most general sense, being an area on the screen that can be a button a dialog, a regular window, or any other kind of visible GUI component. A Windows form is encapsulated by the a subclass of the System::Windows::Forms::Form class, but you don’t need to worry about this much initially, because all the code to create a form is created automatically. To see just how easy it’s going to be, create a basic window using Windows Forms that has a standard menu.

Try It Out

A Windows Forms Application

Choose the CLR project type in the New Project dialog and select the Windows Forms Application as the template for the project. The New Project dialog window is shown in Figure 11-7.

Figure 11-7

Enter the project name as Ex11_03. When you click the OK button the Application wizard generates the code for the Windows form application and displays the design window containing the form as it displays by the application the form. This is shown in Figure 11-8.

645

Chapter 11

Figure 11-8

You can now make changes to the form in the design pane graphically, and the changes are automatically reflected in the code that creates the form. For a start, you can drag the bottom corner of the form with the mouse cursor to increase the size of the form window. You can also change the text in the title bar — right-click in the client area of the form and select Properties from the context menu. This displays the Properties window that allows you to change the properties for the form. From the list of properties to the right of the design pane, select Text, and then enter the new title bar text in the adjacent column showing the property value — I entered A Simple Form Window. When you press the key, the new text appears in the title bar of the form.

Just to see how easy it really is to add to the form window, display the Toolbox pane by selecting the tab on the right of the window if it is present, or by pressing Ctrl+Alt+X or by selecting Toolbox from the View menu. Find the MenuStrip option in the list and drag it on to the form window in the Design tab pane. Right-click the MenuStrip1 that appears below the form window and select Insert Standard Items from the pop-up. You’ll then have the menu in the form window populated with the standard File, Edit, Tools, Help menus, each complete with its drop-down list of menu items. The result of this operation is shown in Figure 11-9.

646

Windows Programming Concepts

If you build the project by pressing the Ctrl+Shift+B and then execute it by pressing Ctrl+F5, you’ll see the form window displayed complete with its menus. Naturally the menu items don’t do anything because you haven’t added any code to deal with the events that result from clicking on them, but the icons at the right end of the title bar work so you can close the application. You’ll look into how to develop a Windows Form application further, including handling events, later in the book.

Figure 11-9

Summar y

In this chapter you’ve seen three different ways of creating an elementary Windows application with Visual C++ 2005 and you should now have a feel for the essential differences between these three approaches. In the remaining chapters of the book, you’ll be exploring in more depth how you develop applications using the MFC and using Windows Forms.

647

Chapter 11

The important points arising in the chapter include:

The Windows API provides a standard programming interface by which an applications communicates with the operating system.

All Windows application include a WinMain() function that is called by the operating system to begin execution of the application. The WinMain() function also includes code to retrieve messages from the operating system.

The Windows operating system calls a particular function in an application to handle processing of specific messages. An application identifies the message processing function for each window in an application by calling a Windows API function.

The MFC consists of a set of classes that encapsulate the Windows API and simplify programming using the Windows API.

A Windows Forms application executes with the CLR. The windows in a Windows Forms application can be created graphically with all the required code being generated automatically.

648