1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Giáo trình C++ P4 docx

34 359 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Introduction to C and C++
Tác giả Stan Trujillo
Trường học Game Institute
Chuyên ngành C and C++ Programming
Thể loại Bài giảng
Năm xuất bản 2001
Định dạng
Số trang 34
Dung lượng 575,64 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Each message has two optional parameters, which are represented by the WPARAM and LPARAM types, as defined here: typedef UINT WPARAM; typedef LONG LPARAM; As we’ll see later, Windows

Trang 1

4 Game Institute

Introduction to C and C++

by Stan Trujillo

Trang 2

© 2001, eInstitute, Inc

You may print one copy of this document for your own personal use

You agree to destroy any worn copy prior to printing another You may

not distribute this document in paper, fax, magnetic, electronic or other

telecommunications format to anyone else

This is the companion text to the www.gameinstitute.com course of the

same title With minor modifications made for print formatting, it is

identical to the viewable text, but without the audio

Trang 3

Table of Contents

Introduction to C++ 4

Lesson 4 – Application Architecture 4

The typedef Keyword 5

Handles 7

Macros 8

The HelloWin32 Sample 8

Windows Messaging 11

The Message Pump 12

Callback Functions 13

Window Creation 15

The SimpleWindow Sample 16

Class Frameworks 21

The GameApplication Class 21

The WinMain function 27

The WndProc Function 28

The SimpleWindowClass Sample 31

Message Pump Modifications 32

What’s next? 33

Trang 4

Introduction to C++

A GameInstitute course by Stan Trujillo

The console applications that we’ve been written so far are useful for game-related tools and utilities (and instructional samples), but console applications are too limited for the game application itself

What we need is a windowed application This will let us create a window in which to display graphics, and provide access to some important Windows-specific features But this isn’t the only thing that a game requires Although games have a lot in common with most windowed applications, there are some

important differences In this lesson we learn about windowed applications and high-level game

application design, and a few C++ topics that we still need to cover

This lesson is different than the previous lessons It introduces some real-world programming issues that

we haven’t had to use thus far, and it focuses on building a body of code that we can use for the

remaining lessons It also moves more briskly than the previous lessons—meaning that not all of the code presented is discussed in detail

The reason for the increased pace is that this lesson is designed to bridge the gap between the simple and educational samples from the previous lessons and the game that we’re building up to This bridge takes the form of a small class framework that encapsulates some of the more mundane elements of Windows programming The advantage is that once we’ve written this framework, we don’t have to worry about how it works This lesson moves quickly because there is a lot to cover, and because it is not necessary for you to master the Windows programming details required to implement this framework

On the other hand, it’s not enough to be given a class framework and being told not to worry how it works That’s why we’ll spend this lesson building the framework from the bottom up What is important

to take from this lesson is the basics of Windows programming, the high-level design of a game

application, and some techniques that go into good class design

Lesson 4 – Application Architecture

The console applications used in the previous lessons each had two portions: those that we provided, and those and were provided in the form of functions from the standard libraries The standard library

provided us with helpful features such as user input support, screen output support, and string

manipulation functions All of these features are still available to us now that we’re going to be writing windowed applications, but we’ll need more than just the standard libraries, which are largely platform independent What we need is Windows-specific features

Microsoft provides access to Windows-specific features through Win32, which is essentially a huge set of functions Win32 is the Application Programming Interface (API) that is used to write Windows

applications (The ‘32’ referrers to the fact that Win32 is specific to 32 bit versions of Windows.) There are other APIs for writing Windows applications, but Win32 is the most direct way to access Windows features

Win32 is the product of an evolution that began with the first version of Windows At the time, C was the language of choice, so Microsoft designed Win32 based on C programming techniques Win32 is still a C-style, function based API, partly because there are so many existing applications that Microsoft can’t change the underlying API without upsetting thousands of developers, and partly because Microsoft has been relatively slow to adopt C++ in general

Trang 5

For C++ programmers, Microsoft provides other APIs such as MFC (Microsoft Foundation Classes), and ATL (Active Template Library) Instead of a collection of functions, these packages provide a collection

of classes that can be used for Windows application development MFC in particular provides classes that are designed to be used as a generic class framework from which any type of application can be written

Both MFC and ATL are built “on top of” Win32, meaning that although they provide an alternative interface, they are in fact written using Win32 As a result, most game programmers feel that using these APIs for games is foolish because better performance can be gained by using Win32 directly This is a debatable issue, but for this course we’ll go with the status quo, and opt not to use MFC or ATL

This doesn’t mean that we won’t be using classes to build the foundation required for games It means that we’ll be using Win32 to write a small and efficient class framework that is designed specifically with games in mind This framework can be small because, although Win32 is a massive API, most games require the use of only a tiny fraction of the complete Win32 API

Before we can do any of this, however, there are some topics that need to be covered first For starters, using Win32 requires knowledge of some language features that we haven’t discussed yet

The typedef Keyword

C and C++ both support the typedef keyword, which is short for type definition A type definition is

essentially a type alias The typedef keyword can be used to define an alternative name for any data type

typedef is used extensively in Win32 For example, Win32 defines aliases for most of the intrinsic types

Consider these variable declarations:

typedef int INT;

typedef short SHORT;

typedef long LONG;

typedef float FLOAT;

typedef char CHAR;

The typedef keyword is followed by the name of an existing type, and ends with the desired alias and a semicolon typedef doesn’t create new data types—it creates new names for existing data types

The examples shown above are of dubious value They don’t provide any advantage over the native types unless you happen to prefer upper-case data type names But these are just a few of the type aliases that Win32 provides Some are useful merely because they are shorter than the alternatives For example:

typedef unsigned short USHORT;

typedef unsigned char UCHAR;

typedef unsigned int UINT;

Trang 6

These type definitions provide shorthand syntax for the unsigned variation of the intrinsic types:

USHORT index;

Instead of

unsigned short index;

But Win32 doesn’t stop there—some new terms are used to describe familiar types One example is the

term word For a 32-bit operating system like Windows, a word is a 16-bit unsigned integer, and a double word is a 32-bit unsigned integer Hence these typedefs:

typedef unsigned short WORD;

typedef unsigned long DWORD;

Win32 also uses typedef to define names for some data types that are used for specific purposes For

example, Windows is a message-based operating system Messages are used to communicate with the

application code Each message has two optional parameters, which are represented by the WPARAM and LPARAM types, as defined here:

typedef UINT WPARAM;

typedef LONG LPARAM;

As we’ll see later, Windows messages are delivered by functions that provide the message itself, which is

represented by the UINT type alias, and is accompanied by parameters, like this:

int ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam);

At first glance, this function appears to use three exotic parameter types, but each is actually just a

typedef for an integer type

Pointer types are also frequently assigned alternative type names by Win32 These typedefs have the

prefix “LP”, which is short for long pointer The “long” refers to a designation made obsolete by 32-bit

operating systems, but is nevertheless still used For example, LPDWORD is a pointer to the DWORD

type, and can be used like this:

DWORD value;

LPDWORD pValue = &value;

Despite the fact that no asterisk appears in the declaration of pValue, it is a pointer because the

LPDWORD type definition includes the asterisk Win32 defines LPDWORD like this:

typedef DWORD* LPDWORD;

A number of similar type aliases are provided for char pointers:

typedef CHAR* LPSTR;

typedef const CHAR* LPCSTR;

These definitions make the following declarations possible:

LPSTR str = “Initial Text”;

Trang 7

LPCSTR const_str = “Const Text”;

Win32 uses these alternative type names extensively, so many of the function prototypes and structures that Win32 provides for use in Windows programming look as though they are based on exotic data types, but in fact most of the types used are simply intrinsic types Nevertheless, the frequency at which these types are used makes using Win32 a bit more difficult at first

Handles

Win32 is designed around constructs that C programmers developed long before C++ was invented One

of these constructs uses handles to represent entities that, had C++ been used, would be classes instead A

handle is a data type that represents a specific entity such as a window, a bitmap, or an icon When one of these items is created, Win32 provides a handle that represents the new item This handle can then be used with functions that Win32 provides to manipulate the item

A prominent example is the HWND data type, which serves as a handle for a window (The “H” prefix

stands for handle, and WND is short for window.) When a new window is created, an instance of the

HWND type is used to store the handle value for that window This handle can be used with a number of

functions what Win32 provides to manipulate that window The ShowWindow function, for example, has

this prototype:

BOOL ShowWindow( HWND hWnd, int nCmdShow );

The first argument is the handle to the window that should be affected by the function call, and the second

argument is used to indicate the effect desired The SW_SHOW symbol, for example, is provided to indicate to ShowWindow that the window that the handle represents should be displayed if it is currently hidden Notice that the ShowWindow return type uses BOOL instead of the intrinsic type bool—yet

another type alias used by Win32

Another important handle type is HINSTANCE, which essentially represents the application itself As we’ll see soon, Win32 provides an HINSTANCE handle to the application on startup

The idea behind a handle is that it, together with the functions that accept handles as arguments,

encapsulate the functionality required for dealing with windows, applications, or any other programmatic entity Without classes, that’s the best that can be done to hide how a system works from the programmer

If Win32 had been written using C++, then handles wouldn’t have been necessary

Most of the time, handles are actually type aliases created with typedef that use either an integer or a pointer as an underlying type The HINSTANCE handle type, for example, is defined this way:

typedef void* HINSTANCE;

HINSTANCE is actually a void pointer Pointers to the void type are generic pointers they are capable

of pointing to any type of data The fact that Win32 defines HINSTANCE this way tells us that each

HINSTANCE is a pointer to a data type that is probably used by Win32 internally, but that we’re not

supposed to know about The details of how Windows handles HWND and HINSTANCE are therefore

hidden from us—providing the C version of encapsulation

Trang 8

Macros

We’ve intentionally avoided macros after mentioning them briefly in Lesson 1 In C++, macros can almost always be avoided with superior features For example, when a literal value has been required in our programs, we’ve been using const, like this:

const int MaxPlayers = 10;

This is a better solution than the macro equivalent:

SetMaxPlayers function was modified to take a float instead of an int, the macro would cause a cryptic

compiler error, but the constant would result in type-mismatched error, more correctly reporting the problem

Nevertheless, Win32 uses macros liberally Virtually every symbol used in conjunction with Win32

functions is a macro and not a constant The SW_SHOW symbol used with the previously mentioned

ShowWindow function, for example, is defined like this:

#define SW_SHOW 5

These symbols would best be constants instead, but Win32 still uses macros Luckily, programmers are unaffected most of the time

The HelloWin32 Sample

Unlike console applications, Windows applications don’t use main as a universal entry-point Instead, they use a similar function called WinMain Each Win32 application must provide a version of this function Like main, WinMain is the first function called, and the last to exit It also provides command-

line information to the application

As we mentioned in Lesson 1, a windowed application that actually displays a window requires at least 50 lines of code or so However, an application that doesn’t display a window can be much simpler All you

need is the WinMain function But Win32 applications don’t support the same output options available to console applications, so, although you can send data to cout, there’s no place to display it With no

output, there is very little point in running the resulting executable, but the code for the simplest possible Win32 application looks like this:

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow) {

// all processing occurs here

return 0;

Trang 9

}

Using Win32 requires that the windows.h header file be included This header file declares and defines the core data types and functions necessary for writing Windows applications

The WinMain function returns an int, but another symbol appears after the return type: APIENTRY

This is a macro that Win32 defines to distinguish between the two types of function calling conventions available in C and C++ These conventions define the exact manner in which a function call is performed

at the machine-language level The standard method is used by default, and the pascal style is activated

by the pascal keyword The APIENTRY macro resolves to the pascal keyword, which causes the

compiler to implement the WinMain function with the Pascal calling convention For our purposes, all

we need to know is that APIENTRY or pascal must appear before the WinMain function name

WinMain has four parameters The first is the HINSTANCE that represents the application This value

is required for some Win32 function calls, and is often stored in a global variable so that it is accessible to

all of the functions in the program The second parameter is also an HINSTANCE, but is always zero for

Win32 applications (it was used for 16-bit versions of Windows), so it can be ignored

The third argument is a string containing the command-line arguments used to launch the executable

Unlike the argv parameter provided to the main function, this is not an array of strings, but a single string

containing all of the arguments as provided on the line Windowed applications use line arguments less frequently than console applications, so this parameter is often ignored

command-The fourth and final WinMain argument is an integer that contains a value indicating the desired initial state for the application’s window Normally this value is equal to the SW_SHOWNORMAL symbol This initial version of WinMain doesn’t do anything except return zero For the WinMain function, a

return value of zero indicates that the application is terminating without processing any messages,

which—in this case—is true

This is the first point in this course in which we’ve had to implement a function that provides parameters

that we are unlikely to use The second WinMain parameter in particular is useless, and we won’t need

the command-line arguments either so we can rewrite the definition of this function so that no parameter name is given, like this:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)

Clearly, this is a pretty boring Win32 application, even if it is our first, because there is no output We

can’t use cout, but we can use another form of Window output: a message box Win32 provides the

MessageBox function for situations in which an application must display a message—usually an error

message The MessageBox function prototype looks like this:

int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);

Trang 10

The first argument that MessageBox requires is the HWND of the application window Since we don’t

have a window yet, we’ll use zero, which instructs Win32 to use the Windows desktop as the parent window for the message box The second argument is the text that is to appear inside the message box and the third argument is the text to appear on the message box title bar

The fourth argument is an integer that is used to control which icon (if any) appears on the message box,

and which buttons should appear For example, using the MB_OK symbol causes the message box to display just an “OK” button We can display a message box by adding a call to MessageBox to

WinMain, like this:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)

{

MessageBox( 0, "Hello Win32!", "WinMain", MB_OK );

return 0;

}

This version of WinMain is used in the HelloWin32 sample, which displays this output:

Before we move on, we can use the MessageBox function to discuss the bit-wise OR operator (|) This

operator combines two integer values into a single value by setting the individual bits of the resulting value according to the bits of the two source values The OR operator manipulates values at the binary level—something that we won’t get into in this course, but is an operation that is often used within an API to allow one or more options to be enabled through a single parameter

The MessageBox function uses this technique for the fourth parameter Previously, we used the MB_OK

symbol to indicate that an “OK” button should be displayed, but Win32 provides more symbols for use

with the MessageBox function The MB_ICONEXCLAMATION symbol, for example, indicates that

an icon containing an exclamation point should be displayed We can modify our call to MessageBox to

use both of these options, like this:

MessageBox( 0, "Hello Win32!", "WinMain", MB_OK | MB_ICONEXCLAMATION );

The OR operator is used to separate the MB_OK and MB_ICONEXCLAMATION symbols The result

is that the value of each symbol is combined into a single integer, which is provided to the MessageBox

function Both symbols have an effect on the results, which look like this:

Trang 11

When an API provides symbols for use in activating options, the symbols used to represent each optional

behavior are called flags In this case we added the MB_ICONEXCLAMATION flag to activate an option that the MessageBox function supports

Windows Messaging

Even with output, our first windowed application is a humble beginning We managed to display a

message box, which is a window, but one that is provided by Windows We need to create our own window so that we can control its size and contents This will require knowledge of how Win32

communicates with each window

Windows is a message-based operating system It uses messages to enable communication between the operating system and each application For example, if the user presses a key, and your application

window is currently the top-most, or active window, Windows delivers a WM_KEYDOWN message to

your application This message is accompanied by information that indicates which key was pressed

Likewise, when the user releases the key, a WM_KEYUP message is posted to your application

Windows defines hundreds of different messages Each is delivered for a different reason Some messages include extra information about the message, and some messages don’t The handling of these messages

is a vital part of any windowed application, but luckily most messages can be passed back to Windows without any processing This is because Windows provides a default message handling mechanism that will handle a message in a generic fashion

This table contains some of the messages that often warrant custom processing:

that is to be redrawn

WM_MOUSEMOVE Sent whenever the mouse is moved—includes

the new location of the mouse

WM_LBUTTONDOWN Sent whenever the left mouse button is

WM_KEYDOWN Sent whenever a key is pressed—includes the

ID of the key involved

Trang 12

WM_KEYUP Sent whenever a key is released—includes

the ID of the key involved

WM_ACTIVATE Sent to indicate any change in the application

window state, such as when the window gains

In order enable the processing of messages, a windowed application must provide three things not present

in the previous sample: a message pump, a message handling callback function, and a window

The Message Pump

A message pump is a loop that retrieves and dispatches messages Win32 applications are responsible for message pumping, but this is easy to do because Win32 provides the functions that are necessary The standard message pump involves these three Win32 functions:

GetMessage

TranslateMessage

DispatchMessage

The GetMessage function retrieves any messages that have been queued for the application If no

messages are present, GetMessage waits until a message arrives before returning This behavior isn’t well

suited for games—a subject we’ll return to later in this lesson

The TranslateMessage function is used to handle accelerators, the Windows term for “hot keys” or

keyboard shortcuts This feature allows keyboard commands to be mapped to menu commands

Finally, the DispatchMessage function instructs Win32 to deliver the message Messaging works on a window basis Each message is addressed to a window as represented by the HWND data type

The standard message pump looks like this:

Once a message has been retrieved, it is passed first to TranslateMessage and then to DispatchMessage The while loop continues to pump messages until GetMessage returns false, which happens when the

WM_QUIT message is posted

Trang 13

This message pump can be placed inside the WinMain function, like this:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)

However, since messages are addressed to specific windows, and we don’t have one yet, there’s no point

in compiling this code

Callback Functions

Software programs are all composed of functions and data In Lesson 2, when we learned about pointers,

we found that data resides in memory and can be accessed by memory address through the use of

pointers

This is also true of functions Like the data in a program, the series of instructions that are contained in functions reside in memory As such, functions have addresses, just like data items Normally it isn’t necessary to take the address of a function, or concern yourself with how function calls and definitions

actually work, but these subjects are necessary in order to use callback functions A callback function is

no different than a regular function, but how it gets called is important

Normally, with the exception of the main or WinMain functions, you are responsible for every function call in the program The program entry point function (main or WinMain) is called by the startup code,

but after that, every subsequent function call is made by the entry point function, either directly or

indirectly

A callback function is a function that is application defined, but called by system or library code The address of a callback function is provided to an API such as Win32, and the API implementation calls the function at a later time Callback functions allow a generic API to perform an application-specific task

By calling a callback function, the API is temporarily handing control over to the application for a

specific purpose

In the case of Windows messaging, callback functions are used to allow the application to respond to Windows messages The application defines a function that handles the messages of interest, and supplies Win32 with the address of this function Then, whenever a message is dispatched to the application, Window calls this function via the function pointer passing to it the message information

In order to understand how the address of a function can be determined, and how it can later be used to make a function call without using the function name, let’s take a closer look at how function calls work Consider this function:

void Func(int val)

{

cout << val << endl;

Trang 14

}

When we compile our program, the compiler converts this function into a set of instructions, and embeds these instructions into the final executable When the executable is launched, these instructions are loaded into memory at an address that is determined at run-time Each time the function is called, the execution flow is diverted to the address where the function happened to be loaded into memory

Let’s assume that Func happened to be loaded into memory at the address 0x5000 This means that when

Func is called, like this:

Func( 100 );

This function call diverts the execution flow to the memory address 0x5000 This is possible because

Func is actually a pointer—a pointer to a function The parentheses that follow each function are similar

to the de-reference operator: they access the function at the address indicated by the preceding function name In other words, a function name followed by an argument list is a function call, but a function name

by itself is the address where the function resides in memory:

cout << Func << endl; // displays 0x5000

This code displays the address of Func Taking the address of a function is easy—no “address of”

operator is required because the function name is a pointer This is actually all we need to know in order

to define a callback function, but since we’re on the subject, let’s take a look at how function pointers are declared and used

Declaring pointers to functions is not very intuitive because the return type and argument list are part of the data type Moreover, the resulting pointer name doesn’t appear after the data type, as is normally the case:

void (*pFuncPtr)(int);

This declares a pointer named pFuncPtr that is a pointer to a function that has a return type of void, and

takes a single integer argument This pointer can legally be assigned to any function that matches this description, like this:

pFuncPtr = Func;

The fact that this assignment compiles demonstrates that a function name is indeed a pointer Both

pFuncPtr and Func now contain the address where the code that implements the Func function resides

This means that either one can be used to call it, like this:

Func( 100 ); // calls Func with 100 as an argument

pFuncPtr( 200 ); // calls Func with 200 as an argument

Both of these calls result in the execution of the same code because they both point to the same function Win32 uses callback functions to deliver messages to each application Each window that an application creates is required to define a callback function and provide its address to Win32 In the example we used

previously, the function had to have a return type of void and accept an integer argument Win32 requires

that message handling callback functions have a return type and argument list that looks like this:

Trang 15

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg,

WPARAM wParam, LPARAM lParam );

The callback function that we provide must have the return type and argument list shown, but can be named whatever we want It is the address of this function that we’ll provide to Win32, not the name The

name used here, WndProc, is arbitrary, but this is the name we’ll use in this lesson

Window Creation

The final item that we need to construct a windowed application is the window itself Because of how Win32 works, creating a window actually involves two steps: registering a window class, and creating the window

Win32 requires that in order for a new window to be created, a window class—or window type—be

defined This can be done with the Win32 RegisterClass function, which is declared like this:

ATOM RegisterClass( CONST WNDCLASS *lpWndClass );

The RegisterClass function takes the address of a variable of the WNDCLASS structure type This structure contains the properties and options for the new window class The WNDCLASS structure looks

Because our goal is to create a very simple window, we don’t need to use all of the members provided by

the WNDCLASS structure We can leave several of them assigned to zero to indicate default settings

An important WNDCLASS data member is the lpfnWndProc member, which is a pointer to the message

handling callback function that Windows will invoke each time a message is to be delivered to this window class

The RegisterClass function returns a data item called an ATOM As long was this value is non-zero, the call to RegisterClass has succeeded It is not necessary to save this value for later use For our purposes,

we’ll register a window class with this code:

WNDCLASS wc;

ZeroMemory( &wc, sizeof(wc) );

wc.style = CS_HREDRAW | CS_VREDRAW;

Trang 16

initializer list, except that zero is the only value supported

The code above assigns the lpfnWndProc member of the WNDCLASS structure with WndProc This is

the name of the message handling callback function that we’ll define later

After a window class has been defined, the application is ready to create the actual window This is done

with the CreateWindow function, which is declared like this:

HWND CreateWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName,

DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, PVOID lpParam );

The CreateWindow function takes 11 arguments, the first of which is most important This is a const

string containing the name of the window class This must be the same name previously provided to the

RegisterClass function (as the lpszClassName member of the WNDCLASS structure) Notice also that

the position and size of the new window are determined by the values passed as the x, y, nWidth, and

nHeight arguments

We’ll call CreateWindow like this:

hwnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

100, 100, 320, 240, NULL, NULL, hInst, NULL);

CreateWindow returns a window handle (an HWND) that represents the new window A handle value of

zero indicates that CreateWindow has failed

The SimpleWindow Sample

Now that we know what goes into a windowed application, we’re ready to put it all together into a

sample Actually, we’re going to write two versions of this sample First, we’ll write a version that does not use classes or inheritance Then, after a discussion of how classes can be used to improve upon this version, we’ll write a class-based version

As a function-based application, the SimpleWindow sample is broken into four functions:

WinMain

RegisterWindowClass

CreateSimpleWindow

Trang 17

WndProc

The WinMain function is the application entry point function The RegisterWindowClass function performs the Win32 window type registration, and the CreateSimpleWindow function creates the actual window The WndProc function is the message-handling callback function

In addition to these four functions, this sample uses two global variables, declared like this:

HINSTANCE hInst = 0;

HWND hwnd = 0

The hInst variable is used to store the application handle provided to WinMain, and the hwnd variable

stores the window handle As global variables, these values are available to all of the functions in a program As we discussed in Lesson 2 using global variables isn’t an ideal solution, so we’ll find an alternative when we write a class-based version

We’ll start our look at the SimpleWindow sample with the first function that gets called: WinMain: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)

The WinMain function begins by assigning the global variable hInst with the value provided by

Windows as the hInstance parameter This makes the application handle available globally

Next the RegisterWindowClass function is called If this function fails and returns false, a message box

is displayed with an error message, and WinMain returns Otherwise, WinMain calls the

CreateSimpleWindow function, which creates the application window and displays it If this operation

fails, the problem is reported with a message box, and WinMain returns

Ngày đăng: 19/01/2014, 02:20

TỪ KHÓA LIÊN QUAN

w