Windows窗口的创建主要需要两个部分,一个是窗口类,一个就是处理你窗口类消息的窗口过程,可以简单理解窗口过程是用于处理Windows传递到窗口的消息,例如这消息可以是鼠标的输入。
Windows对于窗口的处理是通过它对窗口发送消息,然后借由这个消息进行窗口的窗口过程从而影响窗口。
Windows通过消息队列和非消息队列对窗口进行维护,在Windows程序开始执行时,Windows首先会为程序创建一个消息队列,该消息队列存放这应用程序可能创建的所有窗口的消息。然后通过名为“消息循环”的代码,从消息队列中检索消息,并将其发给相应的窗口过程,其他消息则不通过消息队列发给窗口过程。
下面是具体的实现代码,由Charles Petzold大师所编写,然后添加了我的注释:
编译环境:win7 64位 IDE:vs2010
/*------------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
using namespace std;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//窗口过程,可以简单理解为处理窗口的机制,如创建窗口,关闭窗口等等
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;//HWND是窗口句柄,类似的有HDC(设备环境句柄),HINSTANCE(实例句柄——程序本身)
MSG msg ;//MSG是消息结构,可以传递鼠标,键盘之类操作的消息
WNDCLASS wndclass ;//WNDCLASS是窗口类,这里定义了一个叫wndclass的窗口
/*------------------------------------------------------------
窗口类的结构
typedef struct
{
UINT style;//窗口的风格
WNDPROC lpfnWndProc;//用于基于该窗口类的所有窗口的窗口过程的地址
int cbClsExtra;//Windows系统应该预留分配给类的额外内存数量
int cbWndExtra;//Windows系统应该预留分配给窗口的额外内存数量
HINSTANCE hInstance;//
HICON hIcon;//窗口图标
HCURSOR hCursor;//窗口上鼠标样式
HBRUSH hbrBackground;//窗口背景色
LPCTSTR lpszMenuName;//窗口类的菜单
LPCTSTR lpszClassName;//窗口类的名称
}
WNDCLASS,* PWNDCLASS;
------------------------------------------------------------*/
wndclass.style = CS_HREDRAW | CS_VREDRAW ;//定义窗口的风格,CS_HREDRAW(窗口的水平尺寸),CS_VREDRAW(窗口的垂直尺寸)
//这里表示当窗口的水平尺寸或垂直尺寸改变时,基于该窗口类的所有窗口都将被重新绘制
wndclass.lpfnWndProc = WndProc ;//定义该窗口类的窗口过程
wndclass.cbClsExtra = 0 ;//这个窗口不需要额外的空间
wndclass.cbWndExtra = 0 ;//这个窗口不需要额外的空间
wndclass.hInstance = hInstance ;//应用程序的实例句柄
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;//使用LoadIcon函数创建窗口的图标
//这里使用的是预定义的图标,所以第一个参数是NULL
//如果是保存在磁盘里的应用程序中的可执行文件加载自定义图标,该参数必须为hInstance
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;//使用LoadCursor函数创建窗口上鼠标图标,如IDC_ARROW是个箭头,IDC_HAND是只手
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;//使用GetStockObject取得窗口背景色,这里WHITE_BRUSH是白色,BLACK_BRUSH是黑色
wndclass.lpszMenuName = NULL ;//这里没使用菜单,设为NULL
wndclass.lpszClassName = szAppName ;//定义类的名称
if (!RegisterClass (&wndclass))//注册一个窗口类
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;//MessageBox有ASCALL码和Unicode编码形式,当时windows1998的MessageBox似乎不支持Unicode形式的这个函数
return 0 ;
}
hwnd = CreateWindow (szAppName, // 窗口类的名称
TEXT ("The Hello Program"), // 窗口的标题
WS_OVERLAPPEDWINDOW, // 窗口的风格,overlapped是层叠窗口
CW_USEDEFAULT, // 初始x坐标,指定窗口左上角相对于屏幕左上角的初始位置,这里取默认值
CW_USEDEFAULT, // 初始y坐标,指定窗口左上角相对于屏幕左上角的初始位置,这里取默认值
CW_USEDEFAULT, // 初始x方向尺寸
CW_USEDEFAULT, // 初始y方向尺寸
NULL, // 其父窗口的句柄,这里是顶级窗口,所以为NULL
NULL, // 窗口菜单句柄,由于没有菜单,所以为NULL
hInstance, // 程序实例句柄,这里用的是WinMain传入的程序实例句柄
NULL) ; // 创建参数,这个还不懂
ShowWindow (hwnd, iCmdShow) ;//显示窗口,第一个参数是所需窗口的句柄
//第二个参数决定窗口在屏幕中的初始显示位置
//如SW_SHOWNORMAL是窗口正常显示,SW_SHOWMAXIMIZED是最大化,SW_SHOWMINNOACTIVE是显示在任务栏
UpdateWindow (hwnd) ;//这里需要绘制窗口
/*------------------------------------------------------------
MSG类的结构
typedef struct tagMSG
{
HWND hwnd;//消息所指向的窗口句柄
UINT message;//消息标识符,比如将鼠标放置在窗口的客户区按下鼠标左键就是一个消息
WPARAM wParam;//消息参数
LPARAM lParam;//另一个消息参数
DWORD time;//消息进入消息队列的时间
POINT pt;//消息进入消息队列时鼠标所在位置坐标
}
MSG,* PMSG;
POINT是另一种结构
typedef struct tagPOINT
{
LONG x;
LONG y;
}POINT,* PPOINT;
------------------------------------------------------------*/
while (GetMessage (&msg, NULL, 0, 0))//当得到的消息并不是关闭窗口时,继续进行
{
TranslateMessage (&msg) ;//将msg结构返还给Windows进行某些键盘消息的转换
DispatchMessage (&msg) ;//将msg结构再次返还给Windows
}//这里执行一段名为消息循环的代码,可以用于接受键盘输入和鼠标输入
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)//第二个参数是传递的消息
{
HDC hdc ;
PAINTSTRUCT ps ;//该结构包含一些窗口过程用来对客户区进行绘制的信息
RECT rect ;//一种矩形结构
switch (message)
{
case WM_CREATE://即创造窗口
return 0 ;
case WM_PAINT://窗口重新绘制,例如窗口的尺寸改变时需要重新绘制
hdc = BeginPaint (hwnd, &ps) ;//BeginPaint函数的第一个参数为程序的窗口句柄,第二个参数为指向PAINTSTRUCT结构的指针
//当该函数调用时,如果客户区的背景尚未擦出,Windows会对其擦除
//所使用的画刷是注册窗口类的WNDCLASS结构中的hbrBackground字段中指定的
GetClientRect (hwnd, &rect) ;//该函数第二个参数是指向类型为RECT的举行结构的指针
//RECT结构有四个类型为LONG的字段,名称为left,top,right,bottom,该函数会根据窗口尺寸对这四个字段进行设置
DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;//绘制文本,第一个参数是由BeginPaint函数返回的设备环境句柄
//第二个参数是所要绘制的文本,第三个参数设为-1,表示该文本字符串以0结尾
//第四个参数为位参数,如DT_VCENTER是将字体垂直居中
EndPaint (hwnd, &ps) ;//释放环境句柄,以使其无效
return 0 ;
case WM_DESTROY://窗口的破坏
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;//DefWindowProc函数用于对所有窗口过程没有处理的消息进行默认处理
//如果缺少该函数,窗口的其他正常行为(如结束程序)将无法进行
}//窗口过程对消息进行处理后,应返还0
实现效果,图片适当的调了大小: