Windows 窗口类规定了窗口的一些基本特征,如显示方式、 名称、 风格等等。 创建的窗口是属于窗口类的一个具体的实例, 由窗口类可以创建多个窗口。 就像房子的窗户一样,窗户类定义了窗户是用来采光、通风的、有一个外框、可以用一些材 料封闭等;而窗户就是一个个窗户类的实例,当然,窗户有很多种,但是它们的基本特征就 是上面所说得。 就像在房子上开一个窗户要准备一些材料、工具一样,在创建一个 Windows 窗口之前有 一系列准备工作,要为窗口注册一个窗口类,告诉 Windows 希望创建一个什么样的窗口。 RegisterClass 函数用于注册窗口类,它的定义如下: 作用 (函数) 函数原型 ATOM RegisterClass(const WNDCLASS *lpWndClass) ; 如果调用成功,返回一个非零值,ATOM 数据类型保证其返回的值在系统中是唯一的;调用 失败,返回零。 Windows 下的 C/C++编程 RegisterClass 函数的参数只有一个, 是一个指向 WNDCLASS 数据类型的指针, WNDCLASS 数据类型是一个结构,Windows 有一个通用的定义: typedef struct _WNDCLASS { UNIT WNDPROC Int Int HINSTANCE HICON HCURSOR HBRUSH LPCTSTR LPCTSTR } WNDCLASS ; 看到这里大家因该想到些什么了吧。对了!在创建窗口之前要注册窗口,在注册窗口之 前,就是要填充上面这个结构。下面,一项项看: ◆ 首先,定义了一个 WNDCLASS 结构: WNDCLASS ◆ wndclass ; CS_HREDRAW | CS_VREDRAW ; 下面就填充这个结构 wndclass. style = 表示当窗口的水平方向或垂直方向的大小发生变化时,完全刷新窗口,这使得 Hello , Windows !一直位于窗口的正中心。 ◆ ◆ ◆ ◆ ◆ wndclass. lpfnWndProc = wndclass. cbClsExtra wndclass. cbWndExtra WndProc ; 设置窗口函数为 WndProc。这个函数处理窗口里的所有消息。 = 0 ; = 0 ; 目前不使用,设为 0 。 目前不使用,设为 0 。 wndclass. hInstance = hInstance ; 程序的句柄,也就是标识。 wndclass. hIcon = LoadIcon ( NULL , IDI_APPLICATION) ; 设置图标,就是程序的图标,比如 Windows 记事本的图标就是一个小的翻开的记 事本。 ◆ ◆ wndclass. hCursor = LoadCursor ( NULL , IDC_ARROW) ; 设置鼠标,比如说游戏中的鼠标往往是不同形状的。 wndclass.hbrBackground 指定窗口背景色 = ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ; style ; lpfnWndProc ; cbClsExtra ; cbWndExtra ; hInstance ; hIcon ; hCursor ; hbrBackground; lpszMenuName; lpszClassName ; Windows 下的 C/C++编程 ◆ ◆ wndclass. LpszMenuName = NULL ; szClassName; 指定窗口菜单,置为 NULL 表示不需要菜单。 wndclass. lpszClassName = 指定一个类名。 填充完这个结构后,就要注册窗口,而且要对返回值进行检验: if ( ! RegisterClass { MessageBox ( NULL , TEXT ( " This program requires Windows NT !") , szAppName , MB_ICONERROR ) ; return 0 ; } 注册成功,就可以创建窗口了。 3)创建窗口 好了,既然决定了窗户的样子,就可以照着作了。当然,还要决定窗户的位置等信息,这只 要调用 CreateWindows 函数就可以了: hwnd = CreateWindow ( szClassName TEXT("My Hello , World to Windows Program") , ( & wndclass ) ) WS_OVERLAPPEDWINDOW , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , hInstance , NULL ) ; 这里,CreateWindow 函数又出现了 11 个参数,来看看这些参数有些什么作用(见表 1-4) , 表中的参数从上至下的对应上面 CreateWindow 函数的参数顺序: 参数 szClassName TEXT("My Program") WS_OVERLAPPEDWINDOW CW_USEDEFAULT CW_USEDEFAULT 显示风格 Hello World to Windows 作用 字符串,表示窗口类名称 字符串,用于显示窗口标题栏中的字 窗口左上 x 坐标,这里用默认值 窗口左上 y 坐标,这里用默认值 Windows 下的 C/C++编程 CW_USEDEFAULT CW_USEDEFAULT NULL NULL hInstance NULL 窗口右下 x 坐标,这里用默认值 窗口右下 y 坐标,这里用默认值 父窗口句柄,NULL 表示最高级 菜单句柄,NULL 表示没有 应用程序实例句柄 创建参数,这里置为 NULL 表 1-4 CreateWindow 函数参数 这里说明一下,WS_OVERLAPPEDWINDOW 是标准窗口风格,包括一个标题栏、窗口图标、窗口 标题、最小化按钮、最大化按钮、关闭按钮、可调边框。下面是 WS_OVERLAPPEDWINDOW 的定义。 #define WS_OVERLAPPEDWINDOW(WS_OPVERLAPPED | | | | ) WS_CAPTION WS_SYSMENU WS_MINIMIZEBOX WS_MAXIMIZEBOX WS_THICKFRAME | 试试替换成其中的几项,看看有什么效果。 CreateWindows 函数创建个窗口, 系统为这个窗口分配一定的资源, 下一步就是在屏幕下显 示了,也就是调用 ShowWindow 函数: ShowWindow (hwnd , nCmdShow ) ; 函数的第一个参数 hwnd 表示窗口的句柄,也就是这个窗口在系统中的唯一标识。 第二个参数 nCmdShow 是显示参数,用以指定窗口初始化时的状态,决定是最小化、最大化 还是常规显示。如果要自己设置初始状态,可以参照下面的表来进行(见表 1-5) : 试一试 参数 SW_SHOWNORMAL SW_SHOWMAXIMIZED SW_ SHOWMINIMIZED SW_SHOWMININOACTIVE 作用 按常规显示窗口并激活 最大化显示窗口并激活 最小化显示窗口并激活 最小化显示窗口,不激活 表 1-5 nCmdShow 显示参数 接下来,调用 UpdateWindow 函数,通过窗口函数 WndProc 进行窗口的绘制: UpdateWindow ( hwnd ) ; 4)主循环 在 UpdateWindow ( hwnd ) 语句之后,有一段循环语句,这就是 Windows 程序的消息循环。 在这里,指定了 Windows 程序从消息队列中取数据的方式和事件与消息的转换方式。 所谓的消息循环可以这样理解:比如说,有时当连续按键盘时,屏幕上并不是同步显示, 而是有一段时间延迟。消息循环就是当触发一定的事件时(比如按键盘) ,主循环将它转换成消 Windows 下的 C/C++编程 息,也就是 Windows 可以识别的信息,放入消息队列,等待系统以一定的方式进行读取。 下面的代码就是负责接受消息,并进行转换和发送,真正处理消息的函数稍后说明。 while ( GetMessage ( & msg , NULL , 0 , 0 ) ) { TranslateMessage ( &msg ) ; DispatchMessage ( &msg) ; } GetMessage 有 4 个参数,用一个表格来说明它们的作用(见表 1-6) : 参数 msg NULL 0 0 说明 MSG 类型,就是 Windows 消息结构 窗口句柄,NULL 表示接受自己创建窗口的所用消息 提取消息的最小索引值,常与下一个参数同时置 0 提取消息的最大索引值,置 0 表示提取所用消息 表 1-6 GetMessage 参数 GetMessage ( & msg , NULL , 0 , 0 )语句有一个返回值,当不为 WM_QUIT (退出)时返 回一个非零值,这时 while 循环为 1,执行内部的语句;为 WM_QUIT 时返回一个零值,于是跳出 while 循环,执行推出程序。 当 GetMessage 返回一个非零值时,执行 while 循环内的语句,将消息传给 Windows,进行 转换:TranslateMessage ( &msg ) ; 并由 Windows 发送到窗口函数,在这个程序中是 WndProc 函数: DispatchMessage ( &msg) ; 所有的流程可以通过下面的图来表示(见图 1-10) : 图 1-10 Windows 程序流程 5)事件处理 好,现在清楚了 WinMain 函数的工作流程,那就进入到窗口函数中,看看 WndProc 函数。 Windows 下的 C/C++编程 从上面的流程图可以看出,这里,窗口函数处理所用的 Windows 消息,也就是说,这将是 程序的核心,而 WinMain 函数仅仅是搭建了一个基本的框架。