有关 Windows
本主题介绍应用程序用于创建和使用窗口的编程元素;管理窗口之间的关系;和 大小、移动和显示窗口。
概述包括以下主题。
桌面窗口
启动系统时,系统会自动创建桌面窗口。 桌面窗口是系统定义的窗口,用于绘制屏幕背景,并充当所有应用程序显示的所有窗口的基础。
桌面窗口使用位图绘制屏幕背景。 位图创建的图案称为 桌面壁纸。 默认情况下,桌面窗口使用注册表中指定的.bmp文件中的位图作为桌面壁纸。
GetDesktopWindow 函数返回桌面窗口的句柄。
系统配置应用程序(如控制面板项)通过使用 SystemParametersInfo 函数(wAction 参数设置为 SPI_SETDESKWALLPAPER)和 lpvParam 参数(指定位图文件名)来更改桌面壁纸。 然后,SystemParametersInfo 从指定文件加载位图,使用位图绘制屏幕背景,并在注册表中输入新文件名。
应用程序窗口
每个基于 Windows 的图形应用程序至少创建一个窗口(称为main窗口),用作用户和应用程序之间的主接口。 大多数应用程序还会直接或间接创建其他窗口,以执行与main窗口相关的任务。 每个窗口在显示输出和接收来自用户的输入方面都起着一个作用。
启动应用程序时,系统还会将任务栏按钮与应用程序相关联。 任务栏按钮包含程序图标和标题。 当应用程序处于活动状态时,其任务栏按钮以推送状态显示。
应用程序窗口包括标题栏、菜单栏、窗口菜单 (以前称为系统菜单) 、最小化按钮、最大化按钮、还原按钮、关闭按钮、调整大小边框、工作区、水平滚动条和垂直滚动条等元素。 应用程序的main窗口通常包括所有这些组件。 下图显示了典型main窗口中的这些组件。
工作区
工作区是窗口的一部分,应用程序在其中显示输出,例如文本或图形。 例如,桌面发布应用程序在工作区中显示文档的当前页。 应用程序必须提供一个函数(称为窗口过程)来处理窗口的输入并在工作区中显示输出。 有关详细信息,请参阅 窗口过程。
非工作区
标题栏、菜单栏、窗口菜单、最小化和最大化按钮、调整边框大小和滚动条统称为窗口 的非工作区。 系统管理非工作区的大部分方面:应用程序管理其工作区的外观和行为。
标题栏显示应用程序定义的图标和文本行;通常,文本指定应用程序的名称或指示窗口的用途。 应用程序在创建窗口时指定图标和文本。 标题栏还使用户能够使用鼠标或其他指向设备移动窗口。
大多数应用程序都包含一个 菜单栏 ,其中列出了应用程序支持的命令。 菜单栏中的项表示命令main类别。 单击菜单栏上的项通常会打开一个弹出菜单,该菜单的项目对应于给定类别中的任务。 通过单击命令,用户指示应用程序执行任务。
窗口菜单由系统创建和管理。 它包含一组标准菜单项,当用户选择这些菜单项时,可设置窗口的大小或位置、关闭应用程序或执行任务。 有关详细信息,请参阅 菜单。
右上角的按钮会影响窗口的大小和位置。 单击“ 最大化”按钮时,系统会将窗口放大到屏幕大小并定位窗口,使其覆盖整个桌面,减去任务栏。 同时,系统将最大化按钮替换为还原按钮。 单击 还原按钮时,系统会将窗口还原到以前的大小和位置。 单击 最小化按钮时,系统会将窗口缩小到其任务栏按钮的大小,将窗口置于任务栏按钮上方,并将任务栏按钮显示为正常状态。 若要将应用程序还原到以前的大小和位置,请单击其任务栏按钮。 单击 关闭按钮时,应用程序将退出。
调整大小边框是窗口周边的一个区域,使用户能够使用鼠标或其他指向设备调整窗口大小。
水平滚动条和垂直滚动条将鼠标或键盘输入转换为应用程序用于水平或垂直移动工作区内容的值。 例如,显示冗长文档的字处理应用程序通常提供垂直滚动条,使用户能够上下翻页浏览文档。
控件和对话框
除了main窗口外,应用程序还可以创建多种类型的窗口,包括控件和对话框。
控件是应用程序用来从用户处获取特定信息的窗口,例如要打开的文件的名称或文本选择的所需点大小。 应用程序还使用控件获取控制应用程序的特定功能所需的信息。 例如,字处理应用程序通常提供一个控件,允许用户打开和关闭自动换行。 有关详细信息,请参阅 Windows 控件。
控件始终与其他窗口(通常是对话框)结合使用。 对话框是包含一个或多个控件的窗口。 应用程序使用对话框提示用户输入完成命令所需的输入。 例如,包含用于打开文件的命令的应用程序将显示一个对话框,其中包含用户在其中指定路径和文件名的控件。 对话框通常使用与main窗口相同的窗口组件集。 大多数都有标题栏、窗口菜单、边框 (非大小调整) 和工作区,但它们通常没有菜单栏、最小化和最大化按钮或滚动条。 有关详细信息,请参阅 对话框。
消息框是向用户显示备注、警告或警告的特殊对话框。 例如,消息框可以通知用户应用程序在执行任务时遇到的问题。 有关详细信息,请参阅 消息框。
窗口属性
创建窗口时,应用程序必须提供以下信息。 (除了 窗口句柄,创建函数将返回该句柄以唯一标识新窗口。)
以下部分介绍了这些窗口属性。
类名
每个窗口都属于一个窗口类。 应用程序必须先注册窗口类,然后才能创建该类的任何窗口。 window 类定义窗口外观和行为的大多数方面。 window 类的主要组件是 窗口过程,它是一个函数,用于接收和处理发送到窗口的所有输入和请求。 系统以 消息的形式提供输入和请求。 有关详细信息,请参阅 窗口类、 窗口过程和 消息和消息队列。
窗口名称
窗口名称是标识用户窗口的文本字符串。 main窗口、对话框或消息框通常在其标题栏中显示其窗口名称(如果存在)。 控件可能会显示其窗口名称,具体取决于控件的类。 例如,按钮、编辑控件和静态控件在控件占用的矩形中显示其窗口名称。 但是,列表框和组合框等控件不显示其窗口名称。
若要在创建窗口后更改窗口名称,请使用 SetWindowText 函数 。 此函数使用 GetWindowTextLength 和 GetWindowText 函数从窗口中检索当前窗口名称字符串。
窗口样式
每个窗口都有一个或多个窗口样式。 窗口样式是一个命名常量,用于定义窗口的外观和行为方面,而窗口的类未指定。 应用程序通常在创建窗口时设置窗口样式。 它还可以在使用 SetWindowLong 函数创建窗口后设置样式。
系统以及类的窗口过程在一定程度上解释窗口样式。
某些窗口样式适用于所有窗口,但大多数样式适用于特定窗口类的窗口。 常规窗口样式由以 WS_ 前缀开头的常量表示;它们可以与 OR 运算符结合使用,形成不同类型的窗口,包括main窗口、对话框和子窗口。 特定于类的窗口样式定义属于预定义控件类的窗口的外观和行为。 例如, SCROLLBAR 类指定滚动条控件,但 SBS_HORZ 和 SBS_VERT 样式确定是创建水平滚动条控件还是垂直滚动条控件。
有关窗口可以使用的样式列表,请参阅以下主题:
扩展窗口样式
每个窗口可以选择具有一个或多个扩展窗口样式。 扩展窗口样式是一个命名常量,用于定义窗口的外观和行为方面,而窗口类或其他窗口样式未指定。 应用程序通常在创建窗口时设置扩展窗口样式。 它还可以在使用 SetWindowLong 函数创建窗口后设置样式。
有关详细信息,请参阅 CreateWindowEx。
位置
窗口的位置定义为其左上角的坐标。 这些坐标(有时称为窗口坐标)始终相对于屏幕的左上角,或者对于子窗口,则相对于父窗口工作区的左上角。 例如,将坐标 (为 10,10) 的顶级窗口放置在屏幕左上角右侧 10 像素,距离屏幕向下 10 个像素。 将坐标 (为 10,10) 的子窗口放置在其父窗口工作区左上角右侧 10 像素处,从其向下放置 10 个像素。
WindowFromPoint 函数检索占据屏幕上特定点的窗口的句柄。 同样, ChildWindowFromPoint 和 ChildWindowFromPointEx 函数检索子窗口的句柄,该子窗口占据父窗口工作区中的特定点。 尽管 ChildWindowFromPointEx 可以忽略不可见、禁用和透明的子窗口, 但 ChildWindowFromPoint 不能。
大小
窗口的大小 (宽度和高度) 以像素为单位。 窗口的宽度或高度可以为零。 如果应用程序将窗口的宽度和高度设置为零,则系统会将窗口大小设置为默认的最小窗口大小。 为了发现默认的最小窗口大小,应用程序使用具有 SM_CXMIN 和 SM_CYMIN 标志的 GetSystemMetrics 函数。
应用程序可能需要创建具有特定大小的工作区的窗口。 AdjustWindowRect 和 AdjustWindowRectEx 函数根据所需工作区的大小计算窗口的所需大小。 应用程序可以将生成的大小值传递给 CreateWindowEx 函数。
应用程序可以调整窗口的大小,使其非常大;但是,它不应调整窗口的大小,使其大于屏幕。 在设置窗口大小之前,应用程序应通过使用具有SM_CXSCREEN和SM_CYSCREEN标志的 GetSystemMetrics来检查屏幕的宽度和高度。
父窗口或所有者窗口句柄
一个窗口可以有一个父窗口。 具有父窗口的窗口称为 子窗口。 父窗口提供用于定位子窗口的坐标系。 具有父窗口会影响窗口外观的各个方面;例如,对子窗口进行剪裁,使子窗口的任何部分都不能出现在其父窗口的边框之外。
没有父窗口或其父窗口为桌面窗口的窗口称为 顶级窗口。 应用程序可以使用 EnumWindows 函数获取屏幕上每个顶级窗口的句柄。 EnumWindows 将句柄传递到每个顶级窗口,然后传递到应用程序定义的回调函数 EnumWindowsProc。
顶级窗口可以拥有另一个窗口,也可以由另一个窗口拥有。 拥有的窗口始终出现在其所有者窗口的前面,当其所有者窗口最小化时隐藏,当其所有者窗口被销毁时会销毁。 有关详细信息,请参阅 拥有的 Windows。
菜单句柄或Child-Window标识符
子窗口可以具有 子窗口 标识符,即与子窗口关联的应用程序定义的唯一值。 子窗口标识符在创建多个子窗口的应用程序中特别有用。 创建子窗口时,应用程序指定子窗口的标识符。 创建窗口后,应用程序可以使用 SetWindowLong 函数更改窗口的标识符,也可以使用 GetWindowLong 函数检索标识符。
每个窗口(子窗口除外)都可以有一个菜单。 应用程序可以通过在注册窗口的类或创建窗口时提供菜单句柄来包含菜单。
应用程序实例句柄
每个应用程序都有一个与之关联的实例句柄。 应用程序启动时,系统会向应用程序提供实例句柄。 由于它可以运行同一应用程序的多个副本,因此系统在内部使用实例句柄来区分应用程序的一个实例与另一个实例。 应用程序必须在许多不同的窗口中指定实例句柄,包括创建窗口的窗口。
创建数据
每个窗口都可以有关联的应用程序定义的创建数据。 首次创建窗口时,系统会将指向上数据的指针传递到正在创建的窗口的窗口过程。 窗口过程使用数据来初始化应用程序定义的变量。
窗口句柄
创建窗口后,创建函数返回唯一标识窗口的窗口 句柄 。 窗口句柄具有 HWND 数据类型;应用程序在声明包含窗口句柄的变量时必须使用此类型。 应用程序在其他函数中使用此句柄将其操作定向到窗口。
应用程序可以使用 FindWindow 函数来发现系统中是否存在具有指定类名或窗口名称的窗口。 如果存在此类窗口, FindWindow 将返回该窗口的句柄。 若要将搜索限制为特定应用程序的子窗口,请使用 FindWindowEx 函数。
IsWindow 函数确定窗口句柄是否标识有效的现有窗口。 有一些特殊的常量可以替换某些函数中的窗口句柄。 例如,应用程序可以在 SendMessage 和 SendMessageTimeout 函数中使用 HWND_BROADCAST,或在 MapWindowPoints 函数中使用HWND_DESKTOP。
窗口创建
若要创建应用程序窗口,请使用 CreateWindow 或 CreateWindowEx 函数。 必须提供定义窗口属性所需的信息。 CreateWindowEx 具有参数 dwExStyle, 而 CreateWindow 没有此参数;否则,函数是相同的。 事实上,CreateWindow 只需调用将 dwExStyle 参数设置为零的 CreateWindowEx。 因此,本概述的其余部分仅引用 CreateWindowEx。
本节包含下列主题:
注意
还有其他用于创建特殊用途窗口的函数,如对话框和消息框。 有关详细信息,请参阅 DialogBox、 CreateDialog 和 MessageBox。
主窗口创建
每个基于 Windows 的应用程序都必须具有 WinMain 作为其入口点函数。 WinMain 执行许多任务,包括注册main窗口的窗口类和创建main窗口。 WinMain 通过调用 RegisterClass 函数注册main窗口类,并通过调用 CreateWindowEx 函数创建main窗口。
WinMain 函数还可以将应用程序限制为单个实例。 使用 CreateMutex 函数创建命名互斥体。 如果 GetLastError 返回 ERROR_ALREADY_EXISTS,则应用程序的另一个实例在创建互斥) (存在,应退出 WinMain。
创建main窗口后,系统不会自动显示它;相反,应用程序必须使用 ShowWindow 函数来显示main窗口。 创建main窗口后,应用程序的 WinMain 函数调用 ShowWindow,并向其传递两个参数:一个main窗口的句柄,以及一个用于指定main窗口在首次显示时应最小化还是最大化的标志。 通常,可以将 标志设置为以SW_前缀开头的任何常量。 但是,当调用 ShowWindow 以显示应用程序的main窗口时,必须将 标志设置为 SW_SHOWDEFAULT。 此标志指示系统按照启动应用程序的程序的指示显示窗口。
如果向 Unicode 版本的 RegisterClass 注册了窗口类,则窗口仅接收 Unicode 消息。 若要确定窗口是否使用 Unicode 字符集,请调用 IsWindowUnicode。
Window-Creation消息
创建任何窗口时,系统会将消息发送到窗口的窗口过程。 系统在创建窗口的非工作区后发送 WM_NCCREATE 消息,并在创建工作区后发送 WM_CREATE 消息。 窗口过程在系统显示窗口之前接收这两条消息。 这两条消息都包含指向 CREATESTRUCT 结构的指针,该结构包含 CreateWindowEx 函数中指定的所有信息。 通常,窗口过程在收到这些消息时执行初始化任务。
创建子窗口时,系统会在发送WM_NCCREATE并WM_CREATE消息后,将WM_PARENTNOTIFY消息发送到父窗口。 它还会在创建窗口时发送其他消息。 这些消息的数量和顺序取决于窗口类和样式以及用于创建窗口的函数。 此帮助文件中的其他主题中介绍了这些消息。
多线程应用程序
基于 Windows 的应用程序可以有多个执行线程,每个线程可以创建窗口。 创建窗口的线程必须包含其窗口过程的代码。
应用程序可以使用 EnumThreadWindows 函数枚举由特定线程创建的窗口。 此函数将句柄传递到每个线程窗口,进而传递给应用程序定义的回调函数 EnumThreadWndProc。
GetWindowThreadProcessId 函数返回创建特定窗口的线程的标识符。
若要设置由另一个线程创建的窗口的显示状态,请使用 ShowWindowAsync 函数。