windows程序设计 注册窗口类

来源:互联网 发布:c语言寄存器 编辑:程序博客网 时间:2024/04/29 23:28

Registering the Window Class

A window isalways created based on a window class. The window class identifies the windowprocedure that processes messages to the window.

Before youcreate an application window, you must register a window class by callingRegisterClass. This function

requires asingle parameter, which is a pointer to a structure of type WNDCLASS. Thisstructure includes two fields

that arepointers to character strings, so the structure is defined two different waysin the WINUSER.H header file.

First,there's the ASCII version, WNDCLASSA:

typedef struct tagWNDCLASSA

{

UINT style ;

WNDPROC lpfnWndProc ;

int cbClsExtra ;

int cbWndExtra ;

HINSTANCE hInstance ;

HICON hIcon ;

HCURSOR hCursor ;

HBRUSH hbrBackground ;

LPCSTR lpszMenuName ;

LPCSTR lpszClassName ;

}

WNDCLASSA, * PWNDCLASSA, NEAR *NPWNDCLASSA, FAR * LPWNDCLASSA ;

 

The Unicodeversion of the structure is defined like so:

typedef struct tagWNDCLASSW

{

UINT style ;

WNDPROC lpfnWndProc ;

int cbClsExtra ;

int cbWndExtra ;

HINSTANCE hInstance ;

HICON hIcon ;

HCURSOR hCursor ;

HBRUSH hbrBackground ;

LPCWSTR lpszMenuName ;

LPCWSTR lpszClassName ;

}

WNDCLASSW, * PWNDCLASSW, NEAR *NPWNDCLASSW, FAR * LPWNDCLASSW ;

 

When I showsubsequent structures in this book, I'll just show the functionally equivalentdefinition of the structure, which for WNDCLASS is this:

typedef struct

{

UINT style ;

WNDPROC lpfnWndProc ;

int cbClsExtra ;

int cbWndExtra ;

HINSTANCE hInstance ;

HICON hIcon ;

HCURSOR hCursor ;

HBRUSH hbrBackground ;

LPCTSTR lpszMenuName ;

LPCTSTR lpszClassName ;

}

WNDCLASS, * PWNDCLASS ;

In WinMain,you define a structure of type WNDCLASS, generally like this:

WNDCLASS wndclass ;

Youthen initialize the 10 fields of the structure and call RegisterClass.

The two mostimportant fields in the WNDCLASS structure are the second and the last. Thesecond field (lpfnWndProc) is the address of a window procedure used for allwindows based on this class. In HELLOWIN.C, this window procedure is WndProc.The last field is the text name of the window class. This can be whatever you want.In programs that create only one window, the window class name is commonly setto the name of the

program.

Thestatement

wndclass.style = CS_HREDRAW |CS_VREDRAW ;

combines two32-bit "class style" identifiers with a C bitwise OR operator. TheWINUSER.H header files defines a

wholecollection of identifiers with the CS prefix:

#define CS_VREDRAW 0x0001

#define CS_HREDRAW 0x0002

#define CS_KEYCVTWINDOW 0x0004

#define CS_DBLCLKS 0x0008

#define CS_OWNDC 0x0020

#define CS_CLASSDC 0x0040

#define CS_PARENTDC 0x0080

#define CS_NOKEYCVT 0x0100

#define CS_NOCLOSE 0x0200

#define CS_SAVEBITS 0x0800

#define CS_BYTEALIGNCLIENT 0x1000

#define CS_BYTEALIGNWINDOW 0x2000

#define CS_GLOBALCLASS 0x4000

#define CS_IME 0x00010000

 

wndclass.lpfnWndProc = WndProc ;

This setsthe window procedure for this window class to WndProc, which is the secondfunction in HELLOWIN.C.

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

A programcan use this extra space for its own purposes. HELLOWIN does not use thisfeature, so 0 is specified. Otherwise, as the Hungarian notation indicates, thefield would be set to a "count of bytes."

The nextfield is simply the instance handle of the program (which is one of theparameters to WinMain):

wndclass.hInstance = hInstance ;

Thestatement

wndclass.hIcon = LoadIcon (NULL,IDI_APPLICATION) ;

sets an iconfor all windows created based on this window class. The icon is a small bitmappicture that represents the program to the user. When the program is running,the icon appears in the Windows taskbar and at the left side of the programwindow's title bar.

To obtain ahandle to a predefined icon, you call LoadIconwith the first argument set toNULL. When you're loading your own customized icons that are stored in yourprogram's .EXE file on disk, this argument would be set to hInstance, theinstance handle of the program. The second argument identifies the icon. Forthe predefined icons, this argument is an identifier beginning with the prefixIDI ("ID for an icon") defined in WINUSER.H. The IDI_APPLICATION iconis simply a little picture of a window. The LoadIconfunction returns a handleto this icon. We don't really care about the actual value of the handle. It'ssimply used to set the value of the hIconfield. This field is defined in theWNDCLASS structure to be of type HICON, which stands for "handle to anicon."

Thestatement

wndclass.hCursor = LoadCursor (NULL,IDC_ARROW) ;

is similarto the previous statement. The LoadCursorfunction loads a predefined mousecursor known as IDC_ARROW and returns a handle to the cursor. This handle isassigned to the bCursorfield of the WNDCLASS structure. When the mouse cursorappears over the client area of a window that is created based on this class,the cursor becomes a small arrow.

The nextfield specifies the background color of the client area of windows createdbased on this class. The hbr prefix of the hbrBackgroundfield name stands for"handle to a brush." A brush is a graphics term that refers to a coloredpattern of pixels used to fill an area. Windows has several standard, or"stock," brushes. The GetStockObjectcall shown here returns a handleto a white brush:

wndclass.hbrBackground =GetStockObject (WHITE_BRUSH) ;

The next fieldspecifies the window class menu. HELLOWIN has no application menu, so the fieldis set to NULL:

wndclass.lpszMenuName = NULL ;

Finally theclass must be given a name. For a small program, this can be simply the name ofthe program, which is the "HelloWin" string stored in the szAppName variable.

wndclass.lpszClassName= szAppName ;

Now here's aproblem: If you have compiled the program with the UNICODE identifier defined,your program will call RegisterClassW. That's fine if you're running theprogram on Microsoft Windows NT. But if you're running the program on Windows98, the RegisterClassWfunction is not really implemented. There's an entrypoint for the function, but it just returns a zero from the function call,indicating an error. This is a good opportunity for a Unicode program runningunder Windows 98 to inform the user of the problem and terminate. Here's theway most of the programs in this book will handle the RegisterClassfunctioncall:

if(!RegisterClass (&wndclass))

{

MessageBox(NULL, TEXT ("This program requires Windows NT!"),

szAppName,MB_ICONERROR) ;

return 0 ;

}

This codefragment assumes, of course, that RegisterClassis not failing for some otherreason, such as a NULL lpfnWndProcfield of the WNDCLASS structure. TheGetLastErrorfunction helps you determine the cause of the error in cases likethis. GetLastErroris a general-purpose function in Windows to get extendederror information when a function call fails. The documentation of the variousfunctions will indicate whether you can use GetLastErrorto obtain thisinformation. In the case of calling RegisterClassWin Windows 98,  GetLastErrorreturns 120. You can look inWINERROR.H to see that the value 120 corresponds to the identifier ERROR_CALL_NOT_IMPLEMENTED.You can also look up the error in /Platform SDK/Windows Base Services/Debuggingand Error Handling/Error Codes/System Errors - Numerical Order.

Some Windowsprogrammers like to check the return value of every function call for errors.This certainly makes some sense, and here's why: I'm sure you're familiar withthe rule that you always, always check for an error when you're allocatingmemory. Well, many Windows functions need to allocate some memory. For example,RegisterClassneeds to allocate memory to store information about the windowclass. So you should be checking the function regardless. On the other hand, ifRegisterClassfails because it can't allocate the memory it needs, Windows hasprobably already ground to a halt.

0 0