window窗口详解
一、 窗口
在图形化的基于win32的应用程序,窗口是屏幕的矩形区域,应用程序显示输出并接收来自用户的输入,因此,一个图形化基于win32的应用程序的首要任务之一就是创建一个窗口。
窗口与其它窗口共享屏幕,[本事]包括来自其它应用程序的窗口,每次只有一个窗口可以接收来自用户的输入,用户可以使用鼠标、键盘或其它输入设备与此窗口以及拥有该窗口的应用程序进行交互。
二、 关于窗口
这个概述描述了应用程序用来创建和使用窗口的编程单元;管理窗口之间的关系;以及大小、移动、和显示窗口;概述包括以下主题:
三、 桌面窗口
当你启动系统时,它自动创建桌面窗口。桌面窗口是一个系统定义的窗口,它描绘了屏幕的背景,并作为所有应用程序显示的所有窗口的基础。
桌面窗口使用位图来描绘屏幕的背景。由位图创建的图案成为桌面墙纸。默认情况下,桌面窗口使用位图来自在注册表中指定的a.BMP作为桌面壁纸。
一个系统配置应用程序,例如一个控制面板小程序,使用GetDesktopWindow函数返回桌面窗口的句柄。使用SystemParametersInfo函数通过wAction参数设置为SIP_SETDESKWALLPAPER和lpvParam参数指定一个位图文件名改变桌面墙纸。SystemParametersInfo然后从指定的文件中加载位图,使用位图来绘制屏幕的背景,并在注册表输入新的文件名。
四、 应用程序窗口
每个图形化的基于win32应用程序至少创建一个窗口,成为主窗口,它充当用户和应用程序之间的主要接口。大部分应用程序也或直接或间接地创建其它窗口,以执行与主窗口相关的任务。每个窗口在显示输出和接收来自用户的输入起作用。
当你启动一个应用程序,系统还会将一个任务栏按钮与应用程序关联起来。任务栏按钮包含程序图标和标题。当应用程序处于活动状态时,它的任务栏按钮以推送状态显示。
本节包含以下主题:
1) 应用程序窗口的组件
应用程序窗口包括元素,像标题栏,菜单栏,窗口菜单(以前成为系统菜单),最小化按钮,最大化按钮,恢复按钮,关闭按钮,大小边框,客户区域,水平滚动条,和垂直滚动条。一个应用程序的主窗口通常包括所有这些组件。下面的插图显示了在一个典型的主窗口的这些组件。
标题栏显示一个应用程序定义的图标和文本行;通常,文本指定应用程序的名称或表示窗口的目的。在创建窗口时,应用程序指定图标和文本。标题栏也让用户使用鼠标或者其它指针设备来移动窗口。
大部分应用程序包含一个菜单栏列出应用程序所支持的命令,菜单栏中的项目表示命令的主要类别。点击菜单栏上的一个条目,通常会打开一个弹出菜单,它的条目对应一个给定类别中的任务,通过点击一个命令,用户指导应用程序执行任务。
窗口菜单由系统创建和管理。它包含一组标准的菜单项,当用户选择它时,设置窗口的大小或位置,关闭应用程序,或执行任务,了解更多信息,参阅菜单。
当你点击最大化或最小化按钮,这影响窗口的大小和位置。当你点击最大化按钮,系统放大窗口到屏幕大小,定位窗口的位置,因此它会覆盖整个桌面,减去任务栏。与此同时,系统用恢复按钮替换最大化按钮。恢复按钮是一个位图,当点击它时,恢复窗口到它原来的大小和位置。
当用户点击最小化按钮,系统缩小窗口到它任务栏的大小,将窗口放在任务栏按钮位置上,并以正常状态显示任务栏按钮。要恢复应用程序到以前的位置和大小,点击任务栏按钮。
大小边界是窗口周边的一个区域,允许用户能使用鼠标或指向设备调整窗口大小。
客户端区域时应用程序显示输出的窗口的一部分,像文本或图形。例如,桌面发布应用程序在客户端区域显示文档的当前页面。应用程序需提供一个函数,称窗口过程,以处理到窗口的输入和在客户区域的显示输出。更多信息,看窗口过程。
水平滚动条和垂直滚动条转换鼠标或键盘的输入成值,应用程序用以水平或垂直移动客户区域的内容。例如,一个显示冗长文档的文字处理应用程序通常提供一个垂直滚动条,使用户能在文档中上下翻页。
标题栏,菜单栏,窗口菜单,最小化和最大化按钮,大小边框和滚动条,被提及的所有作为窗口的非客户区域。系统管理非客户区域的大部分方面;应用程序管理窗口的所有其它。尤其是,每一个应用程序管理其客户端区域的外观和行为。
2) 控件、对话框和消息框
除了主窗口,应用程序还使用几种类型的窗口,包括控件、对话框、消息框。
一个控件是一个窗口,应用程序用来从用户获取指定信息,例如打开文件的名称或者文本选择的所需点大小。应用程序还使用控件获取控制应用程序特定特性所需的信息。例如,一个字处理应用程序常提供一个控件让用户打开或关闭自动换行。更多信息,参阅控件。
控件总是与另一个窗口一起使用-通常是一个对话框。一个对话框是一个包含一个或多个控件的窗口。应用程序使用对话框提示用户完成一个命令所需的输入。例如,应用程序包含一个打开文件的命令,将显示一个对话框,包含一个用户指定路径和文件名的控件。
消息框是一个窗口,显示提示,注意,或警告给用户。例如,一个消息框可以通知用户应用程序执行任务时遇到的一个问题。
对话框和消息框通常不使用与主窗口相同的一套窗口组件。大多数都有标题栏,一个窗口菜单,一个边框(不改变大小),和一个客户端区域,但是它们通常没有菜单栏,最小和最大按钮,或者滚动条。更多信息,参阅对话框。
五、 Z顺序
窗口的Z顺序表示窗口在一堆重叠窗口中的位置。这个窗口堆栈朝向沿着一个虚拟轴,z轴,从屏幕向外延伸。Z顺序顶部的窗口覆盖所有的其它窗口。Z顺序底部的窗口被所有的窗口重叠。
系统在一个列表中维护Z顺序,它添加窗口到Z顺序基于是否它们是最顶层窗口,顶层窗口或者子窗口。一个最顶层窗口覆盖所有的非最顶层窗口,不管它时活动的还是前台的窗口。一个最顶层窗口有WS_EX_TOPMOST样式,所有的最顶层窗口在Z顺序里出现在任何非最顶层窗口之前,一个子窗口在Z顺序里和它父窗口分组。
当应用程序创建一个窗口时,系统将其置于同类型窗口的Z顺序的顶部。你可以使用BringWindowToTop函数将一个窗口带到同类型窗口Z顺序的顶部,你能使用SetWindowPos和DeferWindowPos函数重新排列Z顺序。
用户通过激活一个不同的窗口来更改Z顺序,系统放置活动窗口在相同类型窗口的Z顺序顶部,当一个窗口出现在Z顺序的顶部时,它的子窗口也是如此。你能使用GetTopWindow函数搜索父窗口的所有子窗口,并返回一个在Z顺序中最高的子窗口的句柄,GetNextWindow函数检索在Z顺序中的下一个或前一个窗口。
六、 创建窗口
应用程序创建其窗口(包括主窗口),使用CreateWindow或CreateWindowEx函数,并提供定义窗口属性所需的信息。CreateWindowEx有一个参数dwExStyle,CreateWindow没有,否则函数相同,事实上,CreateWindow设置dwExStyle参数为0简单调用CreateWindowEx。由于这个原因,本文其余部分仅引用CreateWindowEx。
还有其它函数,包括DialogBox,CreateDialog,和MessageBox,用于创建指定用途的窗口,像对话框和消息框。要了解更多信息,看对话框。
本节包含以下主题:
3) 窗口的属性
应用程序在创建窗口时必须提供以下的信息:
a) 窗口类
每一个窗口都属于一个窗口类。应用程序必须在创建该类的任何窗口之前注册窗口类。窗口类定义一个窗口外观和行为的大部分方面。窗口类的主要部分是窗口过程,一个函数接收并处理发往到窗口的所有的输入和请求。系统以消息的形式提供输入和请求。要了解更多信息,看窗口类,窗口过程,或消息和消息队列。
b) 窗口名称
窗口名称(也称窗口文本)是一个为用户标识窗口的文本字符串。如果存在,一个主窗口对话框或消息框通常在它的标题栏显示它的窗口名称。对于控件,窗口名称的外观依赖控件的类。按钮,编辑控件,或静态控件在控件占据的矩形中显示它的窗口名称,列表框,组合框或静态控件不能显示它的窗口名称。
应用程序创建窗口后使用SetWindowText函数改变窗口名称。它使用GetWindowTextLength和GetWindowText函数函数从窗口获取当前窗口名称。
c) 窗口样式
每一个窗口有一个或多个窗口样式。窗口样式是一个命名的常量,它定义窗口外观和行为的一个方面,而不是被窗口类指定。例如,SCROLLBAR类创建一个滚动条控件,但是SBS_HORZ和SBS_VERT样式决定了是否创建水平或垂直的滚动条控件。一些窗口类型适用所有的窗口,但是大部分适用于指定窗口类的窗口。系统,某种程度上,类的窗口过程,解释窗口的样式。
d) 父母或所有者窗口
一个窗口可以有一个父窗口。有父窗口的窗口叫子窗口。父窗口提供定位子窗口的坐标系统。有父窗口影响窗口的外观面貌;例如,一个子窗口被修剪,这样子窗口没有任何部分能出现在父窗口边界之外。没有父窗口或者父窗口是桌面窗口的窗口叫顶层窗口。一个应用程序使用EnumWindows函数获取它的每一个顶层窗口的句柄。EnumWindows传递每个顶层窗口句柄给应用程序定义的回调函数EnumWindowsProc。
窗口可以拥有或被另一个窗口拥有。一个被拥有窗口一直出现在它的拥有者窗口的前面,当它的拥有者窗口被最小化时隐藏,当它的拥有者窗口被销毁时销毁。
e) 大小
f) 位置
g) Z顺序的方位
每个窗口都有个位置、大小和在Z顺序的方位。位置是窗口的左上角相对于屏幕的左上角的坐标,或子窗口的情况下,父窗口客户区域的左上角。一个窗口的大小是以像素测量的它的宽度和高度。在Z顺序中窗口的位置是在一堆层叠窗口的堆栈中的窗口的位置。更多信息,参阅Z顺序。
h) 子窗口标识或菜单句柄
一个子窗口能有一个唯一的应用程序定义值的关联到子窗口的子窗口标识。在应用程序创建多个子窗口时,子窗口标识特别有用。当创建一个子窗口,应用程序指定子窗口的标识符。创建窗口之后,应用程序能改变窗口的标识符,使用SetWindowsLong函数。也能检索标识符通过GetWindowLong函数。
除了子窗口,每个窗口都可以有一个菜单。应用程序可以通过注册窗口类时或创建窗口时提供菜单句柄来包含一个菜单。
i) 实例句柄
每个基于win32应用程序有一个实例句柄关联到它。当应用程序启动时,系统提供一个到应用的实例句柄。因为它能运行同一个应用程序的多个副本。系统在内部使用应用程序的实例句柄区分另一个。应用程序必须在多个不同的窗口指定实例句柄,包括那些创建窗口。
j) 创建数据
每个窗口可以有应用程序定义的关联到它的创建数据。当窗口被第一次创建时,系统传递一个指向数据的指针给正创建窗口的窗口过程。窗口过程使用数据初始化应用程序定义的值。
4) 窗口句柄
创建窗口之后,创建函数返回一个窗口句柄唯一的标识窗口。应用程序使用这个句柄在另一个函数指示操作到该窗口。一个窗口句柄有HWND数据类型;在声明一个变量存储窗口值时,应用程序必须使用这个值。
有一些专门的常量在某些函数能替换窗口句柄。例如,应用程序在SendMessage和SendMessageTimeout函数能使用HWND_BROADCAST,或者在MapWindowPoints函数使用HWND_DESKTIP。
尽管NULL常量不是窗口句柄,在一些函数你能使用它指定没有窗口被影响。例如,为CreateWindowEx函数的hwndParent参数使用NULL创建没有父窗口或拥有者的窗口,为MessageBox函数的hWnd参数指定NULL创建一个没有拥有者的消息框。一些函数可能返回的实例句柄为NULL,表明给定的操作不使用与任何窗口。
应用程序可以使用FindWindow函数发现是否在系统中存在指定类名或窗口名的窗口存在。如果存在这样一个窗口,FindWindow返回窗口句柄。限制搜索指定应用程序的子窗口,使用FindWindowEx函数。IsWindow函数判断是否一个窗口句柄标识一个有效的存在的窗口。
5) 创建主窗口
每个基于win32的应用程序必须有WinMain作为它的入口点函数。WinMain执行许多任务,包括为主窗口注册窗口类和创建主窗口。WinMain调用RegisterClass函数注册主窗口类,调用CreateWindowEx函数创建主窗口。
可移植性问题入口点不需要命名为WinMain。
你的WinMain函数也能限制你的应用程序为单一实例。创建一个命名互斥锁使用CreateMutex函数,如果GetLastError返回ERROR_ALREADY_EXISTS,你的应用程序的另一个实例存在(它创建了互斥锁),你应该退出WinMain。
系统不能创建主窗口之后自动的显示它,相反,应用程序必须使用ShowWindow函数显示主窗口。创建主窗口之后,应用程序的WinMain函数调用ShowWindow,传递它两个参数:一个主窗口句柄和一个标识指定是否主窗口应该被最小或最大化,当它第一次被显示时。通常,标识能被设置为任何以SW_前缀开头的常量。然而,当ShowWindow被调用以显示应用程序的主窗口,标识必须被设置为SW_SHOWDEFAULT,这个标识告诉系统根据启动应用程序的应用定向的显示窗口。
如果窗口类被RegisterClass的Unicode版本注册,那窗口只接收Unicode消息。要确定窗口是否使用了Unicode字符集,调用IsWindowUnicode。
6) 窗口创建消息
在创建任何窗口时,系统发送消息给窗口的窗口过程。系统发送WM_NCCREATE消息在正创建窗口非客户区域之后和发送WM_CREATE在正创建客户区域之后。窗口过程接收到两个消息在显示窗口之前。两个消息都包含指针到CREATESTRUCT结构,包括CreateWindowEx函数指定的所有信息。通常,窗口过程执行初始化任务在接收到这些消息。
当在创建一个子窗口时,系统发送WM_PARENTNOTIFY消息给父窗口在发送WM_NCCREATE和WM_CREATE消息,在创建窗口时还发送其它消息。这些消息的数量和顺序取决于窗口类和样式以及用于创建窗口的函数。这些消息在这个帮助文件的其它主题中描述。
7) 多线程应用程序
一个基于win32的应用程序能有多个执行线程,每个线程能创建窗口。创建窗口的线程必须包含它的窗口过程代码。
一个应用能使用EnumThreadWindows函数来枚举被一个特定线程创建的窗口。这个函数传递到每个线程窗口的句柄依次给应用程序定义的回调函数EnumThreadWndProc。
GetWindowThreadProcessId函数返回创建指定窗口的线程的标识。
要设置由另一个线程创建的窗口的状态使用ShowWindowAsync函数。
七、 一般窗口样式
有一般的窗口样式和类指定的窗口样式。一般窗口样式以WS_前缀开头的常量表示,它们能用OR操作符组合构成不同的类型的窗口,包括主窗口,对话框,和子窗口。类指定的窗口样式定义了属于预定义控件类的窗口的外观和行为,例如编辑控件和列表框。
应用程序通常设置窗口的样式在创建窗口时,它也可以设置窗口的样式在创建窗口之后用SetWindowLong函数。
本节包含下面主题:
1) 重叠窗口
重叠窗口是一个顶层窗口,有标题栏,边框,和客户区域;它的目的作为应用程序的主窗口。它也能有菜单窗口,最小化和最大化窗口,和滚动条。作为主窗口的重叠窗口通常包括所有这些组件。
通过在CreateWindowEx函数指定WS_OVERLAPPED或WS_OVERLAPPEDWINDOW样式,应用程序能创建一个层叠窗口。如果你使用WS_OVERLAPPED样式,窗口有标题栏和边框。如果你使用WS_OVERLAPPEDWINDOW样式,窗口标题栏,大小便看,窗口菜单,和最小和最大按钮。
2) 弹出窗口
弹出窗口是一个专门的重叠窗口用于对话框,消息框和其它临时窗口,出现在主窗口之外。标题栏时可选的;否则,弹出窗口和使用WS_OVERLAPPED样式的层叠窗口一样。
你可以在CreateWindowEx中指定WS_POPUP样式创建一个弹出窗口。要包含标题栏指定WS_CAPTION样式。使用WS_POPWINDOW样式创建一个弹出窗口,有边框和窗口菜单。WS_CAPTION样式必须和WS_POPUPWINDOW样式组合才使窗口菜单可见。
3) 子窗口
子窗口有WS_CHILID样式,并且被限制到父窗口的客户端区域。应用程序使用子窗口划分父窗口的客户端区域为功能区域。你指定WS_CHILD样式在CreateWindowEx函数中创建子窗口。
子窗口必须有父窗口。父窗口可以时重叠窗口,团出窗口,甚至时另一个子窗口。当你调用CreateWindowEx时指定父窗口。如果你指定了WS_CHILD样式在CreateWindowEx,但是没有指定父窗口,系统不创建窗口。
子窗口有客户端区域,但没有其它特性,除非它们被显示的请求。一个应用程序可以为子窗口请求一个标题栏,一个窗口菜单,最小化和最大化按钮,一个边框,和滚动条。但是子窗口不能有菜单。如果应用程序指定了菜单句柄,在它注册子窗口类或创建子窗口时,菜单句柄被忽略。
定位
系统总是定位一个子窗口相对于父窗口客户端区域的左上角。子窗口任何部分永远不会出现在它父窗口的边界之外。如果一个应用程序创建了一个子窗口,大于父窗口或者定位子窗口的一些或所有延伸超过父窗口的边界。系统剪辑子窗口;也就是说,在父窗口客户端区域之外的部分不被显示。影响父窗口的操作也会影响子窗口,如下。
父窗口 子窗口
销毁 父窗口被销毁之前销毁
隐藏 父窗口被隐藏之前被隐藏,子窗口仅在父窗口可见时可见
移动 和父窗口客户端区域移动移动,子窗口负责绘制它的客户端区域在移动之后
显示 在父窗口显示之后显示
剪裁
系统不会自动的从父窗口的客户端区域剪辑一个子窗口。这意味着如果它任何和子窗口在相同位置绘制父窗口绘制在子窗口之上。然而,如果父窗口有WS_CLIPCHILDREN,系统从父窗口客户区域剪辑子窗口。如果子窗口被剪辑,父窗口不能绘制在它上面。
子窗口可以在相同的客户端区域重叠其它子窗口,和一个或多个其它子窗口共享父窗口的子窗口叫兄弟窗口,兄弟窗口在每一个其它的窗口客户端区域绘制,除非一个子窗口有WS_CLIPSIBLINGS样式,如果一个子窗口有这个样式,它兄弟窗口的任何部分在子窗口内部的被裁剪。
如果窗口有WS_CLIPCHILIDREN或WS_CLIPSIBLINGS样式,轻微的性能损失,每一个窗口都占用系统资源,因此应用程序不应该不加选择的使用子窗口,为了更好的性能,应用程序需要逻辑上划分它的主窗口,这样做应该在主窗口过程中而不是使用子窗口。
父窗口的关系
应用程序可以调用SetParent函数改变现有的子窗口的父窗口。在这种情况下,系统从旧父窗口的客户端区域移除子窗口,移动到新父窗口的客户端区域。如果父窗口指定为NULL句柄。桌面窗口时新父窗口。在在这种情况,子窗口被绘制在桌面上,在任何其它窗口的边框之外。GetParent函数检索子窗口的父窗口句柄。
父窗口放手客户端区域的一部分给子窗口,子窗口从这个区域接收所有的输入。父窗口的每个子窗口的窗口类不需要一样。意思时,应用程序能看起来不同和执行不同任务的子窗口填充父窗口。例如,对话框能包含许多不同类型的控件,每个子窗口接收不同类型的用户数据。
子窗口只有一个父窗口,但是父窗口可以有许多子窗口。每个子窗口,同样能有子窗口。在这个窗口链中,每个子窗口被叫作原始父窗口的子孙窗口,应用程序使用IsChild函数发现给定的窗口时给定的父窗口的子窗口还是子孙窗口。
EnumChildWindows函数枚举父窗口的子窗口。然后,EnumChildWindows传递每个子窗口的句柄给应用程序定义的回调函数。还枚举给定父窗口的子孙窗口。
消息
系统传递一个子窗口的输入消息直接给子窗口;消息没有通过父窗口传递。唯一的例外时,如果子窗口已经被EnableWindow函数禁用了。在这种情况,系统传递原给子窗口的任何输入消息给父窗口。这允许父窗口检查输入消息,如果需要并启用子窗口。
子窗口可以有一个唯一的标识符。在使用控制窗口时,子窗口标识符时终于的。应用程序发送消息指导控件的活动。应用程序使用控件子窗口标识符指导发往控件的消息。此外,一个控件发送通知消息到它的父窗口。通知消息包含控件的子窗口标识符,父窗口通过标识符识别哪个控件发送的消息。应用程序给其它类型的子窗口指定子窗口标识符,借助设置CreateWindowEx函数的hMenu参数一个值而不是一个菜单句柄。
4) 只有消息窗口
只有消息的窗口能让你发送和接收消息,它不可见,没有Z顺序不能被枚举,也不能接收广播消息,窗口只是简单的派发消息。
要创建一个只有消息的窗口,指定HWND_MESSAGE常量或一个存在的只有消息窗口的句柄在CreateWindowEx函数的hWndParent参数里。你也能改变一个存在的窗口为只有消息窗口指定HWND_MESSAGE为SetParent函数的hWndNewParent参数。
要查询只有消息窗口,指定FindWindowEx函数的hwndParent参数为HWND_MESSAGE。此外,如果hwndParent和hwndChildAfter参数为NULLL,FindWindowEx搜索只有消息窗口和顶层窗口。
5) 窗口边框
一个窗口能有下面的边框样式的一个
边框样式 描述
WS_BORDER 创建一个细线边框窗口
WS_DLGFRAME 创建一个双边框窗口,这一样式常用语对话框,窗口有这一样式不能有标题栏。
WS_EX_DLGMODALFRAM 创建一个双边框窗口,不行WS_DLGFRAME,应用程序可以指定WS_CAPTION样式创建标题栏。
WS_EX_STATICEDGE 创建一个三维边框样式,用于不能接收用户输入的项目。
WS_THICKFRAME 创建一个带大小的边框窗口。
带WS_OVERLAPPED或WS_POPUPWINDOW样式的窗口有WS_BORDER样式。默认情况下,其它边框模式必须组合和WS_OVERLAPPED或WS_POPUPWINDOW样式以给一个重叠窗口不同的边框样式。
如果WS_POPUP或WS_CHILD样式窗口没有指定边框样式。系统创建无边框窗口。应用程序使用无边框子窗口来分割父窗口客户端区域,同时保持了对用户不可见的划分。
6) 非客户端区域组件
窗口的非客户端区域能包括标题栏,窗口菜单,最小和最大化按钮,大小边框,和水平和垂直滚动条。应用程序创建窗口是哟哦那个这些组件的一个或多个通过指定下面的样式在CreateWidnowEx函数。
样式 描述
WS_CAPTION 创建一个有标题栏(包括WS_BORDER样式)的窗口。
WS_HSCROLL 创建一个有水平滚动条的窗口
WS_MAXIMIZEBOX 创建一个有最大化按钮的窗口,不能和WS_EX_CONTEXTHELP组合
WS_MINIMIZEBOX 创建一个有最小化按钮的窗口,不能和WS_EX_CONTEXTHELP样式组合
WS_SYSMENU 创建一个在标题栏有窗口菜单的窗口,WS_CAPTION样式必须被指定
WS_VSCROLL 创建一个垂直滚动条
7) 初始状态
下面的样式决定一个窗口是启用还是禁用,可见还是不可见,最小化还是最大化
样式 描述
WS_DISBALED 创建一个最初禁用的窗口,禁用窗口不能接收用户输入消息
WS_MAXIMIZE 创建一个最初最大化的窗口
WS_MINIMIZE 创建一个最初最小化的窗口
WS_VISIBLE 创建一个最初可见的窗口
8) 父和子风格
下面的样式影响剪切关系在父窗口和它的子窗口,以及子窗口和它的兄弟窗口。
样式 描述
WS_CLIPCHILDREN 当在父窗口绘制时,排除被子窗口占据的区域,在创建父窗口时使用这个样式。
WS_CLIPSIBLINGS 剪切和子窗口有关系的窗口。也就是说,当一个特定子窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS样式剪切所有其它重叠子窗口,子窗口的该区域更新被排除之外。如果WS_CLIPSIBLINGS没有被指定,并且子窗口重叠,当在一个子窗口的客户端区域绘制,会绘制在其它邻居子窗口的客户端区域时可能的。
扩展风格
可以在CreateWindowEx函数dwExStyle参数指定下面的样式
9) 样式 描述
WS_EX_ACCEPTFILES 用这个样式创建的窗口接收拖放文件。
WS_EX_CONTEXTHELP 包含一个问号在窗口的标题栏。当用户点击问号,光标成带指针的疑问号。如果用户点击一个子窗口,子窗口接收到WM_HELP消息。子窗口应该将笑嘻嘻传递给父窗口过程,该过程应该调用WinHelp函数使用HELP_WM_HELP命令。应用程序显示一个弹出窗口,通常包含子窗口的帮助。
WS_EX_CONTEXTHELP 不能和WS_MAXMIZEBOX或WS_MINIMIZEBOX样式使用。
WS_EX_CONTROLPARENT 允许用户使用tab键在窗口的子窗口之间导航。
WS_EX_DLGMODALFRAME 创建一个双边框对话框,不像WS_DLGFRAME样式,应用也能指定WS_CAPTION样式创建窗口的标题栏。
WS_EX_NOPAENTNOTIFY 指定使用这个样式创建的子窗口在窗口创建或销毁时不会像父窗口发送WM_PARENTNOTIFY消息。
WS_EX_TOPMOST 指定使用这个样式创建的窗口应该被妨碍在所有非顶层窗口之上,即使在窗口去激活化时也在它们之上。
WS_EX_TOLLWINDOW 创建一个工具窗口;那是一个用在浮动的工具栏。一个工具栏有标题栏比普通的短。工具栏不会出现在任务栏或者在在意按下ALT+TAB出现的窗口中。如果工具栏窗口有系统菜单,它的图标不会显示在标题栏。然而你能显示系统菜单通过右击或输入alt+space。
八、 窗口的关系
窗口可以时被拥有窗口,禁用窗口,前景窗口和背景窗口。以不同的方式,窗口和用户或其它窗口关联。
被拥有的窗口
一个重叠窗口或弹出窗口能被另一个重叠窗口或弹出窗口拥有,拥有几个约束条件。
一个被拥有窗口一直在它的拥有者之上在Z顺序上。
系统自动的销毁一个拥有的窗口,在它的所有者窗口被销毁时。
拥有者隐藏被拥有者也隐藏。
只有重叠窗口或弹出窗口可以是拥有者窗口;子窗口不能时拥有者窗口。应用程序创建一个被拥有窗口指定拥有者窗口句柄在CreateWindowEx的hwndParent参数当它创建一个窗口用WS_OVERLAPPED或WS_WS_POPUP样式。hwndParent参数必须被指定为重叠窗口或弹出差un公开,如果hwndParent标识一个子窗口,系统分配所有权到子窗口的顶层窗口。创建一个被拥有窗口之后,应用不能转移窗口所有权给另一个窗口。
对话框和消息框默认都是被拥有窗口。应用程序指定拥有者窗口在调用函数创建对话框或消息框时。
应用能使用GetWindow函数GW_OWNER标识接收拥有者句柄。
禁用窗口
窗口可以别经用,禁用窗口不接收用户的键盘和鼠标输入,但是它能接收来自其它窗口和来自系统的消息。应用程序通常禁用一个窗口阻止用户使用窗口。例如,一个应用禁用一个对话框的按钮阻止用户选择它。应用能在任何时侯启用它;启用一个窗口恢复正常的输入。
默认,创建的窗口时启用的。应用指定WS_DISABLED样式,从而禁用一个新窗口。用户使用EnableWindow函数启用或禁用一个存在的窗口。系统发送WM_ENABLE消息给窗口当系统的启用状态即将被改变时。应用能判断窗口是否被启用了使用IsWindowEnable函数。
当一个子窗口被禁用时,系统传递子窗口的鼠标输入消息给父窗口。父窗口使用消息决定是否启用子窗口。更多消息看鼠标输入。
每次仅有一个窗口能接收键盘输入,那个窗口被称为有键盘焦点。如果应用程序使用EnableWindow函数禁用一个键盘焦点的窗口,窗口除了被经用还失去键盘焦点,EnableWindow设置键盘焦点为NULL,意味着没有窗口有焦点。如果子窗口或其它后代窗口有键盘交代呢,后代窗口丢失焦点当父窗口被禁用时,更多信息,看键盘输入。
前景和背景窗口
每个进程能有多个线程执行,每个线程能创建窗口。线程创建窗口,用户正在使用该窗口,该线程叫前景线程,该窗口被叫为前景窗口。其它所有线程被较为后台线程,被后台线程创建的窗口被较为后台窗口。
每个线程有一个优先级,决定了线程的接收CPU时间的总数。尽管应用程序能设置它线程的优先级,但是通常前台线程有稍高的优先级比后台线程。因为它有高优先级,前台线程接收的CPU时间更多比后台线程,前景线程有9的基础优先级,后台有7的基础优先级。
用户通过点击窗口设置前台窗口,或使用alt+tab或alt+esc组合。应用程序设置前台窗口使用SetForegroundWindow函数。如果新前景窗口时顶层窗口,系统激活它;否则,它激活关联的顶层窗口。应用程序使用GetForegroundWindow函数接收一个前景窗口的句柄。测试比较你应用窗口的句柄和GetForegroundWindow返回的句柄是否你的应用窗口被激活。
九、 显示状态
在任何一个给定的时间,一个窗口必须时活动的或非活动的;隐藏的或可见的;和最小,最大还是恢复的。这些特性被称为窗口的显示状态,下面的主题讨论窗口的显示状态。
1) 活动窗口
在系统中,同一时间只有一个顶层窗口时活动的。用户激活一个顶层窗口通过点击它(或它子窗口的一个)或使用alt+esc或alt+tab组合。一个应用程序激活一个顶层窗口是哟哦那个SetActiveWindow函数,其它函数能影响系统激活一个不同的顶层窗口,包括SetWindowPos、DeferWindowPos,SetWindowPlacement,和DestroyWindow。尽管应用程序能激活一个不同的顶层窗口在任何时候。为避免用户感觉迷惑,它只应该这样做在相应用户的动作。应用程序使用GetActiveWindow函数接收一个活动窗口的句柄。
当活动性改变从一个应用程序的顶层窗口到另一个应用程序的顶层窗口,系统发送WM_ACTIVATEAPP消息给连个应用程序,通知它们改变,当活动性改变到一个不同的顶层窗口在一个应用程序。系统发送两个WM_ACTIVATE消息。
2) 窗口的可见性
窗口时可见的或隐藏的,系统显示可见窗口在屏幕,它不绘制它隐藏一个隐藏窗口。如果窗口是可见的,用户能提供输入到窗口和显示窗口的输出。如果窗口是隐藏的,实际上它被禁用的。一个隐藏窗口能处理来自系统和其它窗口的消息,但是它不能处理用户的输入和显示输出。在创建窗口时应用程序设置窗口的可见性,稍后,应用能改变可见性状态。
当窗口被设置WS_VISIBLE样式,窗口时可见的,默认,CreateWidowEx函数创建一个隐藏的窗口,除非应用指定了WS_VISIBLE样式,通常,应用程序设置WS_VISiBLE样式在它被创建窗口之后,以保持创建过程的细节对用户隐藏。例如,应用程序在定制窗口外观时保持新窗口隐藏。如果WS_VISiBLE样式被指定在CreateWidnowEx,系统发送WM_SHOWWINDOW消息给窗口在创建窗口之后,并在显示之前。
应用程序能使用IsWindowVisible函数判断窗口是否可见。应用程序能显示(使可见)或隐藏窗口使用ShowWindow,SetWinDowPos,DeferWindowPos,或SetWindowPlacement函数,这些函数显示或隐藏窗口用设置或移除WS_VISiBLE样式为窗口。它们也发送WM_SHOWWINDOW消息给窗口在显示或隐藏之前。
当一个所有者窗口被最小化时,系统子的那个隐藏相关的所有被拥有者窗口。类似的,当所有者窗口被恢复时,系统自动的显示被关联的被拥有者窗口。两种情况。系统发送WM_SHOWWINDOW消息给被拥有者窗口在显示或隐藏之前。有事,应用程序可能需要隐藏被拥有窗口而不最小化或隐藏所有者窗口,在这种情况,应用使用ShowOwnedPopups函数。这个函数设置或移除WS_VISIBLE样式为被所有者窗口,并发送WM_SHOWWINDOW消息给被所有窗口在隐藏或显示它们之前。隐藏一个所有者窗口不影响被拥有者窗口的可见性状态。
当一个父窗口时可见的,它关联的子窗口也是可见的,类似,父窗口时隐藏的,子窗口也是隐藏的。最小化父窗口不影响子窗口的可见性状态,也就是说,子窗口随父窗口一起最小化,但是W_VISiBLE样式没有被改变。
即使一个窗口有WS_VISIBLE样式,用户可能也布恩那个看到窗口在屏幕上,其它窗口可能完全覆盖它或它被移动到屏幕边界之外了。此外,一个可见子窗口服从父窗口指定的剪裁规则。如果窗口的夫唱凯不可见,它也不可见,如果父窗口一道屏幕的边界,子窗口也移动,因为子窗口依据父窗口客户端区域左上角绘制。例如,一个用户移动父窗口包括子窗口远离屏幕的边界至用户不能看到子窗口,即使子窗口和父窗口都有WS_VISIBLE样式。
3) 最小化,最大化和恢复窗口
最大化窗口时有WS_MAXIMIZE样式的窗口。默认,系统放大最大化窗口使其填充屏幕,或在子窗口的情况下,填充父窗口客户端区域,尽管窗口大小能被设置和最大化一样的大小,有略微不同,系统自动移动窗口标题到屏幕顶部或父窗口客户端区域的顶部。同时,系统禁用窗口的大小边框和标题栏的窗口定位功能(这样用户不能通过拖动标题栏移动窗口)
一个最小化窗口时有WS_MINIMIZE样式,默认系统缩小最小化窗口到它任务栏按钮的大小,并移动最小化窗口到任务栏。一个恢复窗口是能返回到它先前大小和位置的窗口,也就是说,他在最小化和最大化之前的大小。
如果一个应用指定了WS_MAXMIZE或WS_MINIMIZE样式在CreateWindowEx函数,窗口最初时最小或最大化的。在创建窗口之后,应用可以可以使用CloseWindow函数最小化窗口,ArrangeIconicWindows函数排列在桌面的图标,或它排列在父窗口中一个父窗口最小化的子窗口。OptionIcon函数恢复最小化窗口到它先前的大小和位置。
ShowWindow函数能最小,最大,恢复一个窗口,它能设置窗口的可见性和活动状态。SetWindowPlacement函数包括一样的功能同ShowWindow,但是它能覆盖窗口默认的最小和最大和恢复位置。
IsZoomed和IsIconic函数能分别判断是否一个给定的窗口时最大或最小。GetWindowPlacement函数接收窗口的最小,最大和恢复的位置,也能判断窗口的显示状态。
当系统接收一个命令最大化和恢复最下化窗口,它发送给窗口一个WM_QUERYOPEN消息。如果窗口过程返回FALSE,系统忽略最大或恢复命令。
系统自动的设置最大化窗口的大小和位置为系统定义的为最大化窗口。覆盖这些缺省值,应用程序能调用SetWindowPlacement函数或处理在系统将最大化差窗口时从窗口接收的WM_GetMINMAXINFO消息,WM_GETMINMAXINFO包含一个指向MINMAXINFO结构的指针,包含系统使用的最大化大小和位置的值,替换这些值覆盖缺省值。
十、 窗口大小和位置
窗口的大小和位置被表示为一个矩形边框,在相对于屏幕或父窗口的坐标给出。顶层窗口的坐标相对于屏幕的左上角,子窗口的坐标相对于父窗口的左上角。当应用程序创建窗口时给定大小和位置,但是在任何时候它能改变大小和位置。更多信息看填充图形。
1) 窗口大小
窗口大小(宽度和高度)以像素为单位,窗口能有0宽度和高度,如果应用程序设置窗口的宽度和高度为0,系统设置大小为默认最小窗口大小。查看默认最小窗口大小,应用程序使用GetSystemMetrics函数用SM_CXMIN和SM_CYMIN标识。
应用程序可能需要创建特定客户区域的窗口。AdjusWindowRect和AdjusWindowRectEx函数根据要求的大小和客户区域计算窗口所需的大小。应用程序传递结果大小值给CreateWindowEx函数。
应用程序可以调整窗口大小更大,然而,它不应该大小窗口比屏幕大。设置窗口大小之前,应该检查屏幕的宽度和高度使用GetSystemMetrics用SM_CXSCREEN和SM_CYSCREEN标志。
2) 窗口位置
窗口位置被定义为左上角的坐标。这个坐标有时被叫窗口坐标,总是相对于屏幕左上角或对应子窗口,父窗口客户区域左上角。例如,顶层窗口有坐标(10,10)被放置屏幕左上角右10像素,下10像素。一个子窗口有坐标(10,10)被放在父窗口客户端区域左上角右10像素,下10像素。
WindowFromPoint函数接收一个窗口句柄,该窗口在屏幕占据指定点。类似的,ChildWindowFromPoint和ChildWindowFromPointEx函数接收一个子窗口的句柄,该子窗口占据在父窗口客户区域指定点。尽管ChildFromEx能忽略不可见,禁用,和透明的子窗口,但ChildWindowFromPoint不能。
3) 默认的大小和位置
应用程序在CreateWidnowEx中指定CW_USEDEFAULT允许系统计算初始大小和位置为顶层窗口。如果应用程序设置窗口坐标为CW_USEDEFAULT并且还没有创建其它顶层窗口,系统设置新窗口的位置相对屏幕左上角;否则,它设置位置相对应用程序最近创建的顶层窗口的位置。如果设置宽度和高度参数为CW_USEDEFAULT,系统计算新窗口的大小。如果应用程序已经创建其它顶层窗口,系统根据应用程序最近创建的顶层窗口的大小计算新窗口的大小。当创建子窗口或弹出窗口时指定CW_USEDEFAULT,系统设置窗口大小为默认最小窗口大小。
4) 跟踪大小
系统为WS_THICKFRAME样式的窗口维护最小和最大的跟踪大小;带有这样式的窗口有大小边框。最小的跟踪大小时你能拖拽窗口大小边框引起最小的窗口大小。类似最大同理。
当系统创建窗口时,窗口的最小和最大跟踪大小能被设置为系统缺省定义值。系统能通过WM_GETMINMAXINFO消息查询并覆盖它。更多信息看大小和位置消息。
5) 系统命令
有窗口菜单的应用程序能通过发送系统命令改变窗口大小和位置。当用户从窗口菜单选择命令时,系统命令被产生。应用程序能模仿用户的动作发送WM_SYSCOMMAND消息给窗口。下面的系统命令影响窗口的大小和位置。
命令 描述
SC_CLOSE 关闭窗口。这个命令发送WM_CLOSE消息给窗口,窗口会执行任何需要清理和销毁自身的步骤。
SC_MAXIMIZE 最大化窗口
SC_MINIMIZE 最小化窗口
SC_MOVE 移动窗口
SC_RESTORE 恢复最小化或最大化窗口到它之前的大小和位置。
SC_SIZE 启动一个大小命令,使用鼠标或键盘改变窗口的大小。
6) 大小和位置函数
创建窗口之后,应用程序能设置窗口的大小和位置通过调用几个不同的函数,包括SetWindowPlacement,MoveWindow,SetWindowPos,和DeferWindowPos。SetWindowPlacement设置窗口的最小位置,最大位置,恢复大小和位置,和显示状态。MoveWindow和SetWindowPos函数是相似的,都设置当应用程序窗口的大小和位置。SetWindowPos函数包括一个标志的结合,影响窗口的显示状态;MoveWidnow不包括这些标志。使用BeginDeferWindowPos,DeferWindowPos和EndDeferWindowPos函数设置多个窗口,包括大小,位置,Z顺序位置,和显示状态。
应用程序可接收窗口边框矩形的坐标使用GetWindowRect函数,填充aRect结构使用窗口左上角和右下角的坐标。坐标根据屏幕的左上角。对于子窗口,ScreenToClient或MapWindowPoint函数映射子窗口边界矩形的屏幕坐标为依据父窗口客户端区域的坐标。
GetClientRect函数接收窗口客户端区域坐标,填充RECT结构用客户端区域左上和右下坐标,但是坐标时相对于客户区域自身的。意味着可以区域左上坐标一直为(0,0),右下坐标时客户区域的宽度和高度。
CascadeWindow函数在桌面层叠窗口,或在指定的父窗口层叠子窗口。TileWindow函数
放置窗口到桌面,或放置指定的父窗口的子窗口。
7) 大小和位置消息
系统发送WM_GETMINMAXINFO消息给一个大小和位置即将要改变的窗口。例如,消息被发送当用户点击移动或大小从窗口菜单或点击大小边框或标题栏。在应用程序调用SetWindowPos移动,改变窗口大小消息也被发送。WM_GETMINMAXINFO包含指针到MINMAXINFO结构,内容为窗口的默认的最大化大小和位置,同样默认最小和最大跟踪大小,应用程序能覆盖默认值处理WM_GETMINMAXINFO并设置恰当的MINMAXINFO的成员。一个窗口接收WM_GETMINMAXINFO必须有WS_THICKFRAME或WS_CAPTION样式。有WS_THICKFRAME样式的窗口在窗口创建过程期间接收到这个消息,以及它被移动,大小改变。
系统发送WM_WINDOWPOSCHANGING消息给一个大小,位置,Z顺序的位置窗口。例如,这个消息包含一个指针到WINDOWPOS,指示窗口的新大小,位置,Z顺序位置,和显示状态。设置WINDOWPOS结构的成员对窗口没有影响,窗口必须处理WM_SIZE和WM_MOVE消息,必须传递WM_WINDOWPOSCHANGED给DefWindowProc函数,否则,系统不发送WM_SIZE和WM_MOVE消息给窗口。
当窗口被创建或大小改变,系统发送WM_NCCALCSIZE消息给窗口。系统使用这个消息计算窗口客户区域的大小和客户区域相对于窗口左上角的位置。窗口通常传递这个消息给默认窗口过程;然而,这个消息能来在应用程序中定制创客的非客户端区域或客户区域的保留部分当窗口大小改变时。更多消息看,绘制和绘图
十一、 窗口动画
使用AnimateWindow函数在显示和隐藏窗口时你能产生指定的特效。当窗口以这种方式进行动画时,系统经会滚动或滑动窗口,取决于你调用AnimateWindow函数指定的标志。
默认,系统使用滚动动画。有了这个效果,窗口以滚动打开出现(窗口显示)或者滚动关闭(隐藏窗口)你能使用dwFlags参数指定是否窗口水平、垂直、或斜着滚动。
当你指定AW_SLIDE标志,系统使用滑动动画,有了这个效果,窗口出现以滑动显示或滑动滑出(隐藏窗口),你能使用dwFlags参数指定窗口是否水平,垂直,或斜着滑动。
你也能使用AW_CENTER标志,使窗口出现为向内折叠或向外扩展。
十二、 窗口的破坏
通常应用程序必须销毁它创建的所有窗口。它使用DestroyWindow函数做这个。当窗口被销毁,系统隐藏窗口,如果它是可见的,任何移除与窗口相关的任何内部数据。这失效窗口句柄,不再被应用程序使用。
应用程序销毁了它创建了它们之后的许多窗口。例如,应用通常销毁对话框窗口一旦它有足够的用户输入然后继续其任务。应用最终销毁主窗口(在终止之前)。
在销毁窗口之前,应用应该保持或移除和窗口相关的数据,并且释放和窗口相关的系统资源。如果应用不释放资源,系统释放应用没有释放的任何资源。
销毁窗口不影响创建窗口的窗口类,新窗口仍能被创建使用该类。任何该类存在的窗口继续操作。销毁一个窗口也销毁窗口的后代窗口。DestroyWindow函数发送WM_DESTROY消息首先给窗口,任何时子窗口和后代窗口。这样,所有被销毁的窗口的后代窗口被销毁。
当用户点击Closehi,带窗口菜单的窗口接收到WM_CLOSE消息。通过处理这个消息,应用可以在销毁窗口之前提示用户确认。如何用户确认,窗口应该被销毁。应用可以调用DestroyWidnow函数销毁窗口。
如果被销毁的窗口时活动窗口,焦点状态和活动被转移到其它窗口。成为活动的窗口是下一个窗口,由alt+esc组合确认。新的活动窗口决定哪个窗口接收键盘焦点。
十三、 使用窗口
本节的实例描述如何执行以下任务。
创建一个主窗口
应用程序创建的第一个窗口通常时主窗口,你能创建主窗口使用CreateWindowEx函数,指定窗口类,窗口名,窗口样式,大小,位置,菜单句柄,实例句柄,和创建数据。主窗口属于应用程序定义的窗口类,因此你必须注册窗口类并提过一个窗口过程为类在创建窗口之前。
大部分应用程序使用WS_OVERLAPPEDWINDOW样式创建主窗口,这个样式给窗口一个标题栏,窗口菜单,大小办卡,和最小和最大按钮,CreateWidnowEx返回一个唯一标识窗口的句柄。
下面的例子创建一个属于应用程序定义窗口类的主窗口。窗口名称,主窗口,将出现在标题栏,通过组合WS_VSCROLL和WS_HSCROLL样式和WS_OVERLAPPEDWINDOW样式,应用程序创建主窗口带水平和垂直滚动条,四个CW_USEDEFAULT常量设置窗口的初始大小和位置称系统定义的默认值,指定NULL代替菜单句柄,窗口将使用窗口类默认菜单。
HINSTANCE hinst;
HWND hwndMain;
// Create the main window.
hwndMain = CreateWindowEx(
0, // no extended styles
"MainWClass", // class name
"Main Window", // window name
WS_OVERLAPPEDWINDOW | // overlapped window
WS_HSCROLL | // horizontal scroll bar
WS_VSCROLL, // vertical scroll bar
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
CW_USEDEFAULT, // default width
CW_USEDEFAULT, // default height
(HWND) NULL, // no parent or owner window
(HMENU) NULL, // class menu used
hinstance, // instance handle
NULL); // no window creation data
if (!hwndMain)
return FALSE;
// Show the window using the flag specified by the program
// that started the application, and send the application
// a WM_PAINT message.
ShowWindow(hwndMain, SW_SHOWDEFAULT);
UpdateWindow(hwndMain);
注意,在创建主窗口之后,前面的示例调用ShowWindow函数,这样做因为系统不自动的显示主窗口在创建之后。传递SW_SHOWDEFAULLT标志给ShowWindow,应用程序允许启动应用程序的程序设置主窗口的初始状态。UpdateWindow函数向窗口发送它的第一个WM_PAINT消息。
创建枚举,和大小子窗口
你能通过使用子窗口将窗口的客户区域划分为不同的功能区域。创建子窗口像创建主窗口,你使用CreateWindowEx函数。要创建一个应用程序定义的窗口类窗口,你必须注册窗口类并提供窗口过程在创建子窗口之前,你必须给子窗口WS_CHILD样式和指定父窗口为子窗口当你创建时。
下面的示例将应用程序的主窗口的客户区域划分为三个功能区域,通过创建三个相同大小的子窗口。每个子窗口和主窗口客户区域一样的高度。但是每个是它三分之一的宽。主窗口创建子窗口相应WM_CREATE消息,主窗口在其窗口创建过程时接收该消息。因为每个窗口后WS_BORDER样式,每一个有细线边框。另外,因为WS_VISIBLE样式没有指定,每个子窗口最初隐藏的。还要注意每个子窗口被分配了一个子窗口标识符。
主窗口调整大小和定位子窗口在相应WM_SIZE消息时,主窗口接收它在其大小改变时。在相应WM_SIZE主窗口通过GetWindowRect函数检索其客户端区域大小,然后传递其给EnumChildWindowss函数。其传递每个子窗口的句柄,依次给应用程序定义的EnumChildProc回调函数。这个函数调用MoveWindow对每个子窗口调整大小和位置。大小和位置基于主窗口的客户区域和子窗口的标识符。随后,调用ShowWindow函数使窗口可见。
#define ID_FIRSTCHILD 100
#define ID_SECONDCHILD 101
#define ID_THIRDCHILD 102
LONG APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
int i;
switch(uMsg)
{
case WM_CREATE: // creating main window
// Create three invisible child windows.
for (i = 0; i < 3; i++)
{
CreateWindowEx(
0,
"ChildWClass",
(LPCTSTR) NULL,
WS_CHILD | WS_BORDER,
0,0,0,0,
hwnd,
(HMENU) (int) (ID_FIRSTCHILD + i),
hinst,
NULL);
}
return 0;
case WM_SIZE: // main window changed size
// Get the dimensions of the main window's client
// area, and enumerate the child windows. Pass the
// dimensions to the child windows during enumeration.
GetClientRect(hwnd, &rcClient);
EnumChildWindows(hwnd, EnumChildProc,
(LPARAM) &rcClient);
return 0;
// Process other messages.
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
LPRECT rcParent;
int i, idChild;
// Retrieve the child-window identifier. Use it to set the
// position of the child window.
idChild = GetWindowLong(hwndChild, GWL_ID);
if (idChild == ID_FIRSTCHILD)
i = 0;
else if (idChild == ID_SECONDCHILD)
i = 1;
else
i = 2;
// Size and position the child window.
rcParent = (LPRECT) lParam;
MoveWindow(hwndChild,
(rcParent->right / 3) * i,
0,
rcParent->right / 3,
rcParent->bottom,
TRUE);
// Make sure the child window is visible.
ShowWindow(hwndChild, SW_SHOW);
return TRUE;
}
销毁一个窗口
你能使用DestroyWindow函数销毁窗口,通常,应用在销毁窗口之前发送WM_CLOSE消息,给窗口机会提示用户确认在销毁窗口之前。包含窗口菜单的窗口自动接收到WM_CLOSE消息,在用户从窗口菜单点击关闭时。如果用户确认窗口应该被销毁。应用调用DestroyWindow。系统发送WM_DESTROY消息给窗口在从屏幕移除它时。相应WM_DESTROY窗口保存它的数据和释放任何资源和它关联的。主窗口通过调用PostQuitMessage函数退出应用程序来结束对WM_DESTROY处理。
下面的示例显示了如何在销毁窗口之前提示用户确认。在对WM_CLOSE的相应中,例子显示包含Yes,Cancel按钮的对话框。用户点击YesDestroyWindow被调用,否则,窗口不被销毁,因为被销毁的是主窗口,在这个示例中调用PostQuitMessage响应WM_DESTROY。
case WM_CLOSE:
// Create the message box. If the user clicks
// the Yes button, destroy the main window.
if (MessageBox(hwnd, szConfirm, szAppName,
MB_YESNOCANCEL) == IDYES)
DestroyWindow(hwndMain);
else
return 0;
case WM_DESTROY:
// Post the WM_QUIT message to
// quit the application terminate.
PostQuitMessage(0);
return 0;