if( !RegisterClassEx( &wndClass ) )
return -1;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
HWND hwnd = CreateWindowA( "DIRECTX11BookWindowClass","Blank Win32 Window",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right- rc.
left,
rc.bottom - rc.top, NULL, NULL, hInstance, NULL );
if( !hwnd )
return -1;
ShowWindow( hwnd, cmdShow );
return 0;
}
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCEprevInstance,
LPWSTR cmdLine, int cmdShow )
{
UNREFERENCED_PARAMETER( prevInstance );
UNREFERENCED_PARAMETER( cmdLine );
WNDCLASSEX wndClass = { 0 };
wndClass.cbSize = sizeof( WNDCLASSEX ) ;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "DIRECTX11BookWindowClass";
if( !RegisterClassEx( &wndClass ) )
return -1;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
HWND hwnd = CreateWindowA( "DIRECTX11BookWindowClass","Blank Win32 Window",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right- rc.
left,
rc.bottom - rc.top, NULL, NULL, hInstance, NULL );
if( !hwnd )
return -1;
ShowWindow( hwnd, cmdShow );
return 0;
}
Win32宏UNREFERENCED_PARAMETER用于避免变量定义后没在函数体中使用的编译警告。虽然这在技术上来讲是毫无必要的,但是作为养成良好的编程习惯,我们在组建源代码时,要力争零warning。由于这样的宏实际上什么都没有做,Visual Studio的编译器在编译时,会将其忽视的,就像忽视喜闻乐见的注释一样。
在两句UNREFERENCED_PARAMETER宏之后,我们用WINDCLASSEX定义了一个窗口类,即用wndClass实例化了WINDCLASSEX。这个窗口类中包含很多Win32窗口的很多属性,比如窗口图标,窗口菜单,窗口的应用实例,光标的样式等等。WNDCLASSEX包含在头文件Winuser.h中,而Winuser.h又包含在windows.h中。即我们只需在头文件中包含Windows.h即可。我们可以在windows.h源代码中找到如下描述:
[cpp]
typedef struct tagWNDCLASSEX {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
typedef struct tagWNDCLASSEX {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;
WNDCLASSEX结构体中的参数详细剖析如下:
▲cbSize.结构体的字节数大小
▲style.第二个成员变量style指定这一类型窗口的样式,常用的样式如下:
ID值名称
描述
CS_HREDRAW
当窗口水平方向上的宽度发生变化时,将重新绘制整个窗口。当窗口发生重绘时,窗口中的文字和图形将被擦除。如果没有指定这一样式,那么在水平方向上调整窗口宽度时,将不会重绘窗口。
CS_VREDRAW
当窗口垂直方向上的高度发生变化时,将重新绘制整个窗口。如果没有指定这一样式,那么在垂直方向上调整窗口高度时,将不会重绘窗口。
CS_NOCLOSE
禁用系统菜单的Close命令,这将导致窗口没有关闭按钮。
CS_DBLCLKS
当用户在窗口中双击鼠标时,向窗口过程发送鼠标双击消息。
▲lpfnWndProc. 第二个成员变量lpfnWndProc是一个函数指针,指向窗口过程函数,窗口过程函数是一个回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。回调函数实现的机制是:
(1)定义一个回调函数。
(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者。
(3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
针对Windows的消息处理机制,窗口过程函数被调用的过程如下:
(1)在设计窗口类的时候,将窗口过程函数的地址赋值给lpfnWndProc成员变量。
(2)调用RegsiterClass(&wndclass)注册窗口类,那么系统就有了我们所编写的窗口过程函数的地址。
(3)当应用程序接收到某一窗口的消息时,调用DispatchMessage(&msg)将消息回传给系统。系统则利用先前注册窗口类时得到的函数指针,调用窗口过程函数对消息进行处理。
一个Windows程序可以包含多个窗口过程函数,一个窗口过程总是与某一个特定的窗口类相关联(通过WNDCLASS结构体中的lpfnWndProc成员变量指定),基于该窗口过程。
lpfnWndProc成员变量的类型是WNDPROC,我们在VC++开发环境中使用goto definition功