|
1、[url=]窗口的类型(Window Types)[/url]这部分包含下列描述窗口类型的主题
l 重叠窗口
l 弹出窗口
l 子窗口
l 分层窗口
l 消息窗口
1.1 重叠窗口
重叠窗口是一个顶层窗口,并且有一个标题栏、边框和客户区;其可以被当做主窗口来使用。它也有窗口菜单、最大化和最小化按钮、滚动条。含有这些组件的重叠窗口可以当做典型的主窗口。
一个应用程序创建重叠窗口可以通过在CreateWindowEx函数中指定WS_OVERLAPPED或者WS_OVERLAPPED-
WINDOW样式来实现。如果你使用WS_OVERLAPPED样式,窗口有标题栏和边框。如果你使用WS_OVERLAPPED-
WINDOW样式,窗口有一个标题栏、可调整边框、窗口菜单、最小化和最大化按钮。
1.2 弹出窗口
弹出窗口是个特殊类型的重叠窗口用于对话框、消息框和出现在应用程序的主窗口之外的临时窗口。弹出窗口的标题栏是可选的(可有可无);其他方面弹出窗口和WS_OVERLAPPED样式的重叠窗口一样。
你可以通过在CreateWindowEx函数中指定WS_POPUP样式来创建一个弹出窗口。指定WS_CAPTION样式可以使窗口包含标题栏。使用WS_POPUPWINDOW样式创建的弹出窗口具有边框和窗口菜单。WS_POPUPWINDOW样式和WS_CAPTION样式必须结合使用才能是窗口菜单可见。
1.3 子窗口
子窗口具有WS_CHILD样式和它父窗口限制的工作区。应用程序使用子窗口的典型就是父窗口在功能区里边划分客户区。你可以通过在CreateWindowEx函数中指定WS_CHILD样式来创建子窗口。
一个子窗口必须有一个父窗口。父窗口可以使重叠窗口、弹出窗口或者甚至可以是另一个子窗口。当你在调用CreateWindowEx函数时指定父窗口。如果你在CreateWindowEx中指定了WS_CHILD样式但是没有指定父窗口,系统不会创建一个窗口。
子窗口有一个客户区但是没有其他特征,除非我们去指定需求。应用程序可以请求一个标题栏,一个窗口菜单,最小化、最大化按钮,边框,滚动条给子窗口,但是子窗口不能有菜单。如果应用程序指定菜单句柄,当菜单句柄注册子窗口类或者创建子窗口,菜单句柄可以忽略。如果边框样式没有指定,系统创建一个无边框的窗口。应用程序可以使用无边框的子窗口来划分父窗口的工作区,分出的部分对用户不可见。
这部分讨论下列
定位
裁剪
关联父窗口
消息
定位(Positioning)
系统常常通过父窗口的客户区左上角来定位一个子窗口,没有子窗口的那一部分是处于父窗口的边框之外的。如果应用程序创建了比父窗口大的子窗口或者是定位一个子窗口一些部分或者子窗口的全部延伸到了父窗口的边框之外时,系统将会裁剪子窗口处于父窗口之外的部分;所以超出系统边框之外的部分在父窗口客户区不显示。影响父窗口也影响子窗口的情景(Actions)
父窗口 子窗口
被销毁
| 在父窗口之前被销毁
| 被隐藏
| 在父窗口之前被隐藏(注释1)
| 被移动
| 在父窗口的客户区被移动,子窗口负责移动之后它客户区的绘制
| 被显示
| 在父窗口显示之后显示
| 注释1:子窗口只能在父窗口可见的情况下可见
裁剪(Clipping)
系统不会自动的从父窗口的客户区裁剪子窗口,这意味着父窗口在子窗口的位置进行绘图会将本应该绘制在父窗口上的图形绘制在子窗口上。如果父窗口使用
WS_CLIPCHILDREN样式,父窗口裁剪处于它客户区的子窗口。如果子窗口已经被裁剪则父窗口的绘图不会绘到子窗口上去。
在相同的客户区一个子窗口可以和另外的子窗口重叠。一个子窗口可以和一个或多个子窗口共有一个父窗口,此类子窗口成为“兄弟姐妹窗口”。“兄弟姐妹窗口“可以相互的在它们的客户区上进行绘图,除非“兄弟姐妹窗口”中的某一个窗口具有WS_CLIPSIBLINGS样式。如果一个子窗口有此样式,则它所有兄弟姐妹窗口中与它重叠的都将被裁剪(相当于此子窗口为其他兄弟姐妹窗口的“父窗口”)。
如果一个窗口拥有WS_CLIPCHILDREN和WS_CLIPSIBLINGS中的一个样式,将会发生一点小的损失。每个窗口都占据系统资源,所以一个应用程序不应该任意的使用子窗口。一个应用程序为了更好的性能,应该在逻辑上划分主窗口的窗口过程函数,这样比任意的使用子窗口更好。
关联父窗口(Relationship to parent window)
应用程序可以通过调用SetParent函数改变目前已经存在的子窗口的父窗口。在这种情况下,系统从旧的父窗口的客户区将子窗口移动到新的父窗口的客户区,如果指定SetParent函数的句柄为NULL则桌面窗口为新的父窗口。这样可以得到子窗口的父窗口的窗口句柄。
父窗口将它客户区的一部分工作空间让渡给子窗口,在让渡给子窗口的那部分工作空间上的所有输入全部由子窗口接收。具有相同父窗口的所有子窗口的窗口类不一定非得全部相同。这意味着一个应用程序可以用许多个子窗口来填充父窗口使得父窗口既可以有超炫的界面又可以有强大的功能。例如,一个对话框可以包含许多类型控件(子窗口),每个子窗口接收来自用户的不同类型的数据。
一个子窗口只能有一个父窗口,但是一个父窗口可以有很多个子窗口。结果每个子窗口又可以有子窗口,这种子窗口称为原始父窗口的子代窗口。应用程序可以使用IsChild函数来判断一个窗口是子窗口还是子代窗口。
函数EnumChildWindows枚举一个父窗口的所有子窗口。通过向应用程序中已经定义的回调函数传递窗口的句柄,并通过此函数的返回值来判断窗口的所有子窗口是否已经被枚举完。传递窗口句柄窗口的子代窗口在被枚举字窗口时也被枚举。
EnumChildWindows函数:
函数功能:枚举一个父窗口的所有子窗口
函数原型:BOOL EnumChildWindows(HWNDhWndParent,WNDENUMPROC lpEnumFunc, LPARAM lParam);
参数说明:
HWND hWndParent 父窗口句柄
WNDENUMPROC lpEnumFunc 回调函数的地址
LPARAM lParam 自定义的参数
注意:回调函数的返回值将会影响到这个API函数的行为。如果回调函数返回true,则枚举继续直到枚举完成;如果返回false,则将会中止枚举。
消息(Messages)
子窗口一有消息输入系统就将此消息传递给子窗口;这些消息的传递是不经过父窗口的。但是也有一种例外如果一个子窗口已经被系统通过调用EnableWindow函数置为无效,在这种情况下系统向子窗口的所有消息传递都是先经过父窗口。如果有必要父窗口可以通过这个规则检验子窗口的输入消息并决定是否给子窗口传递此消息。
EnableWindow函数说明:
函数作用:可以将有效窗口置为无效反之亦然
函数原型:
BOOL EnableWindow( HWND hWnd, // handle to window
BOOL bEnable // enable or disable input
);
参数说明:
hWnd 窗口句柄
bEnable 如果值为TRUE则将窗口置为有效,如果是FALSE则置为无效
一个子窗口可以有一个独特的整数标识符,当和控件窗口在一起工作时子窗口的标识符是很重要的。应用程序通过标识符来发送消息来控制控件的活动。应用程序通过控件的子窗口标识符向每个控件发送控制消息。另外,控件向它的父窗口发送通知消息。通知消息内容包括,控件的子窗口标识符用来确认父窗口向那个控件发送的消息。应用程序中子窗口标识符是通过CreateWindowEx函数中的HMenu参数来确定的而不是菜单句柄。
1.4 层叠窗口(LayeredWindows)
使用层叠窗口可以大大的提高一个复杂形状窗口的性能和观赏性,动画形状或者混入透明特效。系统自动的混合和重绘应用程序下边的层叠窗口。这使得层叠窗口被绘制的很平滑,所以分层窗口上没有窗口闪烁较严重的区域。另外,分层窗口还可以通过设置透明度来使得窗口半透明。
可以通过CreateWindowEx函数中指定WS_EX_LAYERED这个窗口扩展样式来创建一个分层窗口,也可以通过调用SetWindowLong函数来设置窗口的WS_EX_LAYERED样式使得已经创建成功的非分层窗口变为分层窗口。在调用CreateWindowEx函数之后,分层窗口将会变为不可见直到调用SetLayeredWindowAttbutes 或者UpdateLayeredWindow函数之后此窗口才会变为可见的。
SetWindowLong函数说明:
函数作用:改变指定窗口的属性。
函数原型:
LONG SetWindowLong( HWND hWnd, // handle to window
int nIndex, // offset of value to set
LONG dwNewLong // new value
);
参数说明:
hWnd 需要改变窗口的窗口句柄
nIndex 想要取消的窗口属性
dwNewLong 重置的窗口属性
注释:从Windows8 操作系统开始,顶层窗口和子窗口可以和WS_EX_LAYERED样式一起被使用。以前的Windows版本只有顶层窗口支持WS_EX_LAYERED样式。
通过调用SetLayeredWindowAttributes函数来规定分层窗口的不透明度或者透明度的色键。调用此函数之后,当窗口被显示或者被调整大小时系统仍然会向窗口请求绘制。但是由于系统已经存储了分层窗口的图像,所以在一个分层窗口相对于另一个窗口移动时,不会向系统请求重绘来绘制(简单来说就是移动不会使移动窗口发生重绘)。如果需要一个窗口增加色键值或者色键特效,应用程序不需要调整重绘代码,这是由于系统调用SetLayeredWindowAttributes函数从离屏存储中获取窗口相关的信息使得窗口重绘以达到我们想要的特效。
SetLayeredWindowAttributes函数说明:
用法:在Windows 2000/XP中,User32.dll增加了一个新函数SetLayeredWindowAttributes。要使用该函数,我们必须在生成窗口或使用SetWindowLong函数中设置窗口风格WS_EX_LAYERED (0x00080000)。该风格一旦被设置,我们就可以调用该函数来透明化窗口。
函数原型:
BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
);
参数说明:
hWnd 窗口句柄
crKey 色键值
bAlpha 透明度
dwFlags 指定功能
如果窗口需要透明更高效更快,可以调用UpdateLayeredWindow函数进行逐像素透明。对此分层窗口使用UpdateLayeredWindow函数,窗口的形状和内容必须要应用程序直接提供,而不是系统通过UpdateLayeredWindow函数重定向。另外UpdateLayeredWindow函数直接使用内存可以更高效,因为系统不需要额外的内存来存储重定向窗口的图像。为了最大效率的使窗口生动起来,可以调用UpdateLayeredWindow函数来改变分层窗口的位置和大小。请注意,在调用SetLayeredWindowAttribues(设置分层窗口属性)函数之后调用UpdateLayeredWindow函数会失败直到再次设置的图层样式被清除。
UpdateLayeredWindow函数说明:
函数作用:刷新分层窗口
函数原型:
BOOL UpdateLayeredWindow( HWND hwnd, // handle to layered window
HDC hdcDst, // handle to screen
DC POINT *pptDst, // new screen position
SIZE *psize, // new size of the layered window
HDC hdcSrc, // handle to surface
DC POINT *pptSrc, // layer position
COLORREF crKey, // color key
BLENDFUNCTION *pblend, // blend function
DWORD dwFlags // options
);
参数说明:自己去查MSDN
分层窗口的测试是基于窗口的形状和透明度来测试的。这意味着在窗口的形状扭曲区域和透明度为零的区域鼠标会消失。然而,如果分层窗口具有WS_EX_TRANSPARENT这个Windows扩展窗口样式分层窗口的形状将会被忽略,鼠标事件会被转到分层窗口之下的其他窗口。
1.5消息窗口(Message-Only Window)
一个消息窗口只能让你发送或者接受消息。窗口是可见的,没有Z序,不能被枚举,不能接收广播消息。消息窗口仅仅分派消息。
在调用CreateWindowEx函数指定此函数的hWndParent 参数为HWND_MESSAGE常量或者为一个现存消息窗口的窗口句柄可以创建一个消息窗口。你也可以将一个现存窗口转换成消息窗口,通过调用SetParent函数将此函数的hWndNewParent 参数指定为HWND_MESSAGE。
SetParent函数说明:
函数功能:改变某个子窗口的父窗口。
函数原型:
HWND SetParent( HWND hWndChild, // handle to window
HWND hWndNewParent // new parent window
);
参数说明:
hWndChild 子窗口句柄
hWndParent 新的父窗口句柄
可以通过调用FindWindowEx函数并指定其hwndParent参数为HWND_MESSAGE来寻找消息窗口。另外如果FindWindowEx函数的hwndParent参数和hwnChildAfter参数为NULL,则通过此函数检索到的消息函数为最顶层窗口。
FindWindowEx函数:
函数功能:在窗口列表中寻找与指定条件相符的第一个子窗口 。
函数原型:
HWND FindWindowEx( HWND hwndParent, // handle to parent window
HWND hwndChildAfter, // handle to child window
LPCTSTR lpszClass, // class name
LPCTSTR lpszWindow // window name
);
参数说明:
hwndParent 要查找的子窗口所在的父窗口的句柄
hwndChildAfter 子窗口句柄
lpszClass 指向一个指定了类名的空结束字符串或一个标识类名字符串的指针
lpszWindow 指向一个指定了窗口名(窗口标题)的空结束字符串
2、[url=]窗口[/url]关系(WindowRelationships)
一个窗口会通过很多方式与用户或者其他窗口有联系。一个窗口有可能是奴隶窗口(owned window)或者前景窗口或者背景窗口。窗口也有可能通过Z序与其他窗口有联系。至于更多的关于这方面的信息,我们来看下面专题:
l 前景窗口和背景窗口
l 奴隶窗口(Owned Window)
l Z序
前景窗口和背景窗口
每一个进程都可以有大量的线程,每个线程都可以创建窗口。用户当前操作的线程叫做前景线程,前景线程创建的窗口叫做前景窗口。其他的(非用户当前操作)线程称为背景线程,背景线程创建的窗口叫做背景窗口。
每个线程都有一个优先级,优先级决定线程得到CPU时间的多少。通过应用程序可以设置他的线程的优先级,通常前景线程的优先级比背景线程的优先级稍微高点。由于前景线程的优先级较高所以所分配到的CPU时间会比背景线程多。前景线程的正常基底优先级为9,背景线程的正常基底优先级为7。
用户通过点击一下窗口或者通过使用ALT+TAB或者ALT+ESC快捷键来设置前景窗口可以通过GetForegroundWindow函数来检索一个窗口是否为前景窗口。如果GetForegroundWindow函数返回的句柄和应用程序窗口的句柄相同,则当前应用程序的窗口为前景窗口,反之则为背景窗口。
GetForegroundWindow函数说明:
函数功能:判断当前窗口是否为前景窗口
函数原型:HWND GetForegroundWindow(VOID);
应用程序可以通过调用SetForegroundwindow函数将一个窗口设置为前景窗口。
SetForegroundwindow函数说明:
函数功能:将一个非前景窗口的窗口变为前景窗口
函数原型:
BOOL SetForegroundWindow(HWND hWnd);
参数说明:hWnd 需要变为前景窗口的窗口句柄
返回值:如果返回值为非零则成功反之则失败
系统会约束进程设置前景窗口。一个进程可以设置前景窗口只要下边列举的条件中有一个为TRUE:
l 进程为前台进程
l 进程通过前台进程被启动
l 进程接收到了最后的输入事件
l 没有前台进程
l 前台进程正在调试
l 前台未被锁定(可以去看LockSetForegroundWindow)
l 前台锁过期或者失效(请看SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo)
l 当前没有活动菜单
进程可以设置窗口为前台窗口可以通过调用AllowSetForegroungWindow函数或者调用BroadcastSystemMessage 函数设置其dwFlags参数为BSF_ALLOWSFW让另一进程去设置前台窗口。被LockSetForegroundWindow函数调用的前台进程被禁止调用SetForegroundWindow函数。
AllowSetForegroundWindow函数:
函数功能:规定进程可以调用SetForegroundWindow函数将其设为前台进程
函数原型:BOOL AllowSetForegroundWindow( DWORD dwProcessId );
参数说明:
dwProcessID 进程ID
BroadcastSystemMessage函数:
函数功能:向规定的收件人发送一条消息
函数原型:long BroadcastSystemMessage( DWORD dwFlags, // broadcast option LPDWORD lpdwRecipients, // recipients UINT uiMessage, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter );
参数说明:(由于内容过多此处不做过多解释详细去查看MSDN)
dwFlags 规定消息类型的选项(有多种类型供选择)
lpdwRecipients 收件人(发送消息的目的地)
uiMessage 被发送的消息
wParam 其他的关于此消息的附加信息
lParam 其他的关于此消息的附加信息
LockSetForegroundWindow函数:
函数功能:锁定进程并决定进程是否能调用SetForegroundWindow函数
函数原型:BOOL LockSetForegroundWindow( UINT uLockCode );
参数说明:
uLockCode 能否调用SetForegroundWindow函数的标志,如果为LSFW_LOCK则不能调用,如果为LSFW_UNLOCK则能调用
2.2 奴隶窗口(Owned Window)
一个重叠窗口或者弹出窗口可能被其他重叠窗口或者弹出窗口所拥有。奴隶窗口有以下几个约束:
l 奴隶窗口的Z序通常会比拥有它的窗口的Z序大
l 如果一个奴隶窗口的拥有者被摧毁则系统会自动将奴隶窗口摧毁
l 当奴隶窗口的拥有者在最小化的时间奴隶窗口是隐藏的
只有重叠窗口或者弹出窗口才能成为奴隶窗口,子窗口不能成为奴隶窗口。应用程序调用CreateWindowEx函数创建一个重叠或者弹出窗口时指定其hwndParent参数为拥有者窗口的窗口句柄则可以为此窗口创建一个奴隶窗口。hwndParent参数必须为一个重叠窗口或者弹窗口的句柄。如果父窗口的句柄被指定为一个子窗口的句柄则系统将会将此奴隶窗口的所有权转给子窗口的最顶层父窗口。已经创建的奴隶窗口的拥有不能被转让给其他窗口。
对话框和消息框被默认为奴隶窗口。应用程序在调用函数创建对话框或者消息框的时间指定其的拥有者。
应用程序可以通过调用GetWindow函数并指定其的dwFlags参数为GW_OWNER来检索一个奴隶窗口的拥有者。
GetWindow函数:
函数功能:返回与指定窗口有特定关系(如Z序或所有者)的窗口句柄
函数原型:HWND GetWindow(HWND hWnd,UINT nCmd);
参数说明:
hWnd 窗口句柄,要获得的窗口句柄是依据nCmd参数值相对于这个窗口的句柄
nCmd 说明指定窗口与要获得句柄的窗口之间关系
2.3 Z序(Z-Order)
Z序是一个窗口在一叠重叠窗口中所处位置的标识符。窗口的堆叠是以Z轴为方向堆叠的,Z轴就是以桌面为0向屏幕外延伸的一条虚轴。Z序最顶端的窗口遮住了其他窗口,Z序底部的窗口被其他窗口所遮住。
系统通过一张表维持Z序。将窗口Z序向Z序表添加的根据是窗口是否为最顶端窗口,顶层窗口或者子窗口。最顶端窗口遮住所有的非最顶端窗口,不管它是活动窗口或是前景窗口。最顶端窗口具有WS_EX_TOPMOST样式。所有的最顶层窗口的Z序处于所有非顶层窗口之前。子窗口Z序和他的父窗口Z序是分类的。
当应用程序创建窗口,系统会将此窗口的Z序放在与它同类型窗口的顶端。可以通过调用BringWindowToTop函数将窗口的Z序提到与它同类型的窗口的顶端。你可以通过调用SetWindowPos函数和DeferWindowPos函数将Z序重新排列。
BringWindowToTop函数:
函数功能:将一个窗口提到当前一叠重叠窗口的顶端
函数原型:void BringWindowToTop(void);
参数说明:参数为空
SetWindowPos函数:
函数功能:改变子窗口、弹出窗口或者顶层窗口的位置、大小和Z序
函数原型:BOOL SetWindowPos(HWND hWnd,HWND hWndInsertAfter,int X,int Y,int cx,int cy,UINT uFlags);
参数说明:
hWnd 窗口句柄
hWndInsertAfter 在Z序中处于被置位前的窗口句柄。(可以是一些系统默认的值。比如HWND_BOTTOM)
X 以客户坐标指定窗口新位置的左边界
Y 以客户坐标指定窗口新位置的顶边界
Cx 以像素指定窗口的新的宽度
Cy 以像素指定窗口的新的高度
uFlags 窗口的尺寸和定位的标识符。(详见MSDN中SetWindowPos函数参数说明)
DeferWindowPos函数:
函数功能:指定的窗口更新指定的多窗口位置结构
函数原型:HWND DeferWindowPos(HDWP hWinPoslnfo,HWND hWnd,HWND hWndlnsertAffer, int x,int y, int cx, int Cy,UINT uFags);
参数说明:参数过多此处不做介绍。(详见MSDN中DeferWindowPos函数)
用户通过激活不同的窗口来改变Z序。系统规定,相同类型的窗口处于Z序顶层的为此类型的激活的窗口。当窗口出现在Z序的最顶端,那么它的子窗口同样处在Z序的最顶端。你可以通过调用GetTopWindow函数来检索所有子窗口并通过此函数返回的窗口句柄来判断哪个子窗口处于子窗口Z序的最顶端。GetNextWindow函数可以在Z序中获取到当前窗口的前一个或者后一个窗口。
GetNextWindow函数:
函数功能:该函数返回Z序中的前一个或者后一个窗口的句柄
函数原型:HWND GetNextWindow(HWND hWnd,UINTwCmd);
参数说明:
hWnd 窗口句柄
wCmd 指定返回的是前一个窗口还是后一个窗口(具体说明详见MSDN解释)
3、窗口显示状态(Window Show State)
在任意给定的时间,一个窗口有可能是活动窗口也有可能是非活动窗口,可见或者隐藏、也许是最大化、最小化、或者原始状态。和这些状态有关的所有特征被称为窗口的显示状态。我们用一下专题讨论窗口显示状态:
l 活动窗口
l 非活动窗口
l 窗口可见性
l 最大化、最小化和原始窗口
3.1 活动窗口(Active Window)
应用程序中用户当前操作的活动窗口是一个最顶层窗口。为了让用户更容易的识别活动窗口,系统将它放在Z序的最顶端,并且将它标题栏和边框的颜色转换为系统规定的活动窗口颜色。只有最高阶层的窗口才能成为活动窗口。当用户对子窗口进行操作时,系统激活与此子窗口有关系的最高阶层层窗口。
在某一个时间只能有一个最顶层窗口是活动窗口。用户可以通过点击最高阶层窗口(或者它的子窗口)激活一个最高阶层窗口,或者使用ALT+ESC或者ALT+TAB组合键。应用程序可以通过调用SetActiveWindow函数来激活最高阶层窗口。其他函数可以让系统激活非最高阶层窗口,这些函数包括SetWindowPos、DeferWindowPos、SetWindowPlacement和DestroyWindow。由于应用程序可以在任意时间激活一个非最高阶层窗口,为了避免用户混淆,应用程序应该唯一的响应用户操作。应用程序使用GetActiveWindow函数来得到活动窗口的句柄。
SetActiveWindow函数:
函数功能:激活一个窗口
函数原型:HWND SetActiveWindow(HWND hWnd);
参数说明:hWnd 将要被激活的最高阶层窗口的窗口句柄
SetWindowPlacement函数:(详细解释请查看MSDN)
函数功能:设置指定窗口的显示状态和恢复,最小化,最大化位置
函数原型:BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl)
参数说明:
hWnd 窗口句柄
*lpwndpl 指向一个WINDOWPLACEMENT结构的指针,该结构包含了新的显示状态和窗口的位置
在调用函数SetWindowPlacement之前,将WINDOWPLACEMENT结构的长度单元置为sizeof(WINDOWPLACEMENT)。如果lpwndpl->length设置不正确,函数SetWindowPlacement将失败。
GetActiveWindow函数:
函数功能:该函数可以获得与调用线程的消息队列相关的活动窗口的窗口句柄
函数原型:Cwnd* GetActiveWindow(void);
参数说明:参数为空
当两个不同应用程序的最高阶层窗口的激活状态被相互转换时,系统会向两个应用程序发送一条WM_ACTIVATEAPP消息,当同一个应用程序的不同最高阶层窗口的激活状态被相互转换时系统会向这两个窗口发送WM_ACTIVATE消息。
3.2 失效窗口(Disable Windows)
窗口可以使失效的。失效窗口不接收用户的键盘和鼠标输入。但是可以接收来自其他窗口、其他应用程序和其他系统的消息。比如,应用程序为了避免用户选择一个对话框中的按钮,可以将此按钮置为失效状态。应用程序可以再任意时间启用一个失效窗口;让一个窗口恢复正常的输入。
默认情况下,当一个窗口被创建此窗口处于激活状态。然而应用程序可以通过指定WS_DISABLE样式使一个新建窗口处于失效状态。应用程序可以通过调用EnableWindow函数将一个现存的窗口设置为启用或者失效状态。当窗口的允许状态即将转变时,系统会向它发送一条WM_ENABLE消息。应用程序可以决定窗口是否可以通过调用IsWindowEnabled函数被启用。
EnableWindow 函数:
函数功能:该函数允许/禁止指定的窗口或控件接收鼠标和键盘的输入,当输入被禁止时,窗口不响应鼠标和按键的输入。输入允许时,窗口接收所有输入。
函数原型:BOOL EnableWindow(HWND hWnd,BOOL bEnable);
参数说明:
hWnd 被允许/禁止的窗口的句柄
bEnable 定义窗口是被允许输入还是禁止输入
IsWindowEnabled函数:
函数功能:该函数用于判断指定的窗口是否允许接收键盘或鼠标的输入
函数原型:BOOL IsWindowEnabled(HWND hWnd);
参数说明:
hWnd 窗口句柄(详细信息请自行查看MSDN)
若函数返回值为0则允许输入,否则禁止输入。
当一个失效的子窗口接收鼠标输入消息时,系统会将此鼠标输入消息传递给此子窗口的父窗口。父窗口使用此消息来决定是否启用子窗口。需要更多资讯请看鼠标输入。
每次只有一个窗口能接受到键盘输入;此窗口具有键盘焦点。如果应用程序调用EnableWindow函数让一个窗口的键盘焦点失效,此窗口将会失去键盘焦点此外此窗口变为失效窗口。如果EnableWindow函数将键盘焦点置为NULL,则意味着没有窗口有焦点。如果一个子窗口或者子代窗口具有键盘焦点,当父窗口失效时子代窗口失去焦点。如果需要更多信息,请看键盘输入。
3.3 窗口可见性(Window Visibility)
窗口要么是隐藏的,要么是可见的。系统在屏幕上显示一个可见的窗口。系统通过不绘制隐藏窗口来让隐藏窗口达到隐藏的效果。如果窗口是可见的则用户可以对窗口进行输入和查看窗口的输出。隐藏窗口实际上也就是失效窗口。 隐藏窗口可以处理来自系统的消息或者来自其他窗口的消息,但是他不能处理来自用户或者输出显示的消息。应用程序在创建窗口的时间设置可见性状态。之后,应用程序可以改变可见性状态。
当一个窗口具有WS_VISIBLE样式时此窗口为可见窗口。默认情况下CreateWindowEx函数创建的窗口为隐藏窗口,除非应用程序指定WS_VISIBLE样式。典型的应用程序设置WS_VISIBLE样式之后,应用程序将会创建一个窗口来保存用户创建隐藏窗口的详细过程。比如应用程序可以让一个窗口隐藏一会儿然后他自定义窗口的外观。如果函数CreateWindowEx指定了WS_VISIBLE样式系统将会在窗口创建之后且显示之前向窗口发送WM_SHOWWINDOW消息。
应用程序可以通过IsWindowVisible函数决定一个窗口是否为可见窗口。应用程序可以通过调用ShowWindow函数、SetWindowPos函数、DeferWindowPos函数、SetWindowPlacement函数或者SetWindowLong函数来隐藏/显示窗口。这些函数通过对窗口设置WS_VISIBLE样式或者移除WS_VISIBLE样式来达到窗口的隐藏/显示效果。他们也在窗口隐藏/显示之前向窗口发送WM_SHOWWINDOW消息。
IsWindowVisible函数:
函数功能:该函数获得给定窗口的可视状态
函数原型:BOOL IsWindowVisible(HWND hWnd);
参数说明:hWnd 被测试窗口句柄
ShowWindow函数:
函数功能:设置指定窗口的显示状态
函数原型:BOOL ShowWindow(HWND hWnd,int nCmdShow);
参数说明:
hWnd 窗口句柄
nCmdShow 指定窗口如何显示(详细请自行查看MSDN)
SetWindowLong函数:
函数功能:改变指定窗口的窗口属性
函数原型:LONG SetWindowLong(HWND hWnd,int nIndex,LONG dwNewLong);
参数说明:
hWnd 窗口句柄
nIndex 指定的偏移值
dwNewLong 指定的替换值 (参数详解请自行查看MSDN)
当拥有者(相对于奴隶窗口而言)窗口最小化时,系统会自动隐藏和它有关的奴隶窗口。类似的,当一个拥有者窗口是还原状态时系统会自动的将和它有关的奴隶窗口显示。上面两种情况,在奴隶窗口隐藏或者显示前系统回向他们发送一条WM_SHOWWINDOW消息。有时应用程序需要除最小化和隐藏拥有者窗口之外的方式来隐藏奴隶窗口。在这种情况下,应用程序就会调用ShowOwnedPopups函数。这个函数设置或移除所有奴隶窗口的WS_VISIBLE样式,并且在奴隶窗口显示或者隐藏前向奴隶窗口发送WM_SHOWWINDOW消息。隐藏一个拥有者窗口不影响奴隶窗口的显示状态。
ShowOwnedPopups函数:
函数功能:显示或隐藏属于指定窗口的所有弹出式窗口
函数原型:BOOL ShowOwnedPopups(HWND hWnd,BOOL fshow);
参数说明:
hWnd 拥有弹出式窗口的窗口句柄
fshow 指明弹出式窗口是被显示还是被隐藏
当一个父窗口是可见的时间与它相关联的子窗口也是可见的。类似的如果一个父窗口是不可见的那么它的子窗口也是不可见的。父窗口的最小化不会影响到子窗口的可见性状态,换句话说就是子窗口随着父窗口一起被最小化,但是WS_VISIBLE样式没有改变。
即使一个窗口具有WS_VISIBLE样式,用户也不一定能在屏幕上看见它;也许是其他的窗口完全遮住了它或者它移动出了屏幕的边缘。并且,一个可见的子窗口会被通过与它具有父子关系窗口规定的裁剪规则而被裁剪。如果窗口的父窗口是不可见的,那么它也是不可见的。如果父窗口移出了屏幕的边缘,那么他的子窗口也会移出屏幕的边缘这是因为子窗口是以父窗口的客户区的左上顶点为原点绘制的。例如,用户可以将父窗口包含其子窗口移动到远离屏幕边缘,即使子窗口和它的父窗口都具有WS_VISIBLE样式,用户看不到子窗口。
3.4 最小化、最大化和还原窗口(Minimized ,Maximized and Restored Windows)
最大化窗口具有WS_MAXIMIZE样式。默认情况下,系统会增大最大化窗口以便于它能填充屏幕,如果是一个子窗口在这种情况下,则它填充它所在父窗口的客户区。尽管一个窗口的大小可以设置成与最大化窗口一样的尺寸,但是最大化窗口与原始窗口还是稍微有点不同。系统自动的将窗口的标题栏移动到屏幕的顶部或者是父窗口客户区的顶端(对子窗口而言),同时系统会让窗口的弹性边框和通过拖拽标题栏来移动窗口的功能失效。
最小化窗口具有WS_MINIMIZE样式。通常情况下,系统缩小最小化窗口和它的任务栏按钮一样大小并将最小化窗口移动到任务栏下。还原窗口就是将最小化或者最大化的窗口恢复到最小化或最大化之前的大小和位置。
应用程序在调用CreateWindowEx来创建窗口时如果指定样式为WS_MAXIMIZE或者WS_MINIMIZE则创建的窗口刚开始就为最小化或者最大化。在创建窗口之后,应用程序可以通过调用CloseWindow函数来将一个窗口最小化。ArrangeIconicWindows函数排列桌面图标,或者在父窗口上排列父窗口的最小化的子窗口。OpenIcon函数将一个最小化的窗户口恢复到它最小化以前的位置和大小。
[url=]CloseWindow[/url]函数:
函数功能:最小化指定的窗口但是不销毁窗口
函数原型:BOOL CloseWindow(HWND hWnd);
参数说明:hWnd 需要最小化的窗口句柄
ArrangeIconicWindows函数:
函数功能:排列一个父窗口的最小化子窗口
函数原型:UINT ArrangleIconicWindows(HWND hWnd);
参数说明:hWnd 父窗口的句柄 (注:当参数为空时表示排列的不是子窗口)
OpenIcon函数:
函数功能:恢复一个最小化的窗口并将其激活
函数原型:LONG OpenIcon(HWND hWnd);
参数说明:hWnd 窗口句柄
ShowWindow函数可以将一个窗口最小化、最大化或者恢复。同时他也能设置窗口的可见性和活动状态。SetWindowPlacement函数与ShowWindow函数的功能相似,但是SetWindowPlacement函数可以覆盖默认的最小化、最大化和还原状态窗口的位置。
IsZoomed函数和IsIconic函数分别决定是否让一个窗口最大化和最小化。
GetWindowPlacement函数获取最小化、最大化或者还原窗口的位置,同时也决定窗口的显示状态。
IsZoomed函数:
函数功能:确定窗口是否是最大化窗口
函数原型:BOOL IsZoomed(HWND hWnd);
参数说明:hWnd 被测试窗口的窗口句柄
返回值:如果返回值为非0则窗口已经最大化,如果返回值为0则窗口未最大化
IsIconic函数:
函数功能:确定窗口是否是最小化窗口
函数原型:BOOL IsIconic(HWND hWnd);
参数说明:hWnd 被测试窗口的窗口句柄 (返回值与检测最大化窗口一样)
GetWindowPlacement函数:
函数功能:返回指定窗口的显示状态以及被恢复的最小化、最大化的窗口位置
函数原型:BOOL GetWindowPlacement(HWND hWnd,WINDOWPLACEMENT *lpwndpl);
参数说明:
hWnd 窗口句柄
*lpwndpl 指向WINDOWPLACEMENT结构的指针,此结构存储窗口信息
当系统接收到将最小化窗口最大化或者还原的命令时,系统给窗口发送一条WM_QUERYOPEN消息。如果窗口过程函数返回值为FALSE则系统忽略这条消息。
系统自动设置一个最大化窗口的大小和位置通过系统默认的规定的最大窗口。为了改变这个默认值,应用程序可以在当系统正要最大化窗口时调用SetWindowPlacement函数处理窗口或者向窗口发送WM_GETMINMAXINFO消息。WM_GETMINMAXINFO消息包含一个MINMAXINFO结构体指针,此结构含有系统用来设置最大化窗口的位置和大小的值。替换这些值就可以改变默认状态了。
4、窗口的大小和位置(Window Size and Position)
窗口的大小和位置是以一个矩形边框来表示的,给出相对于屏幕或者父窗口的坐标。最高阶层的窗口的坐标是相对于屏幕左上角的;子窗口的位置坐标是相对于父窗口客户区左上角的。应用程序在创建窗口时指定窗口的初始大小和位置,应用程序在任意时间都可以改变窗口的大小和位置。如果需要更多消息,请自行查看填充图形:
这部分包含了一下的一些专题:
l 默认大小和位置
l 追踪大小
l 系统命令
l 与大小和位置有关的函数
l 与大小和位置有关的消息
4.1 默认大小和位置(Default Size and Position)
应用程序允许系统通过在CreateWindowEx中指定CW_USERDEFAULT参数来打算最高阶层窗口的初始大小和位置。如果应用程序将窗口的坐标设置为
CW_USERDEFAULT并且系统在没有创建其他的最高阶层的窗口;系统设置新窗口的位置是相对于屏幕坐标系的左上角,另外系统设置新窗口的位置还与应用程序最近创建的最高阶层窗口有关。如果宽度和高度参数设置为CW_USERDEFAULT则新窗口的大小由系统计算。如果应用程序已经创建了其他的顶层窗口,系统在创建新的窗口时,新窗口的大小是基于最近创建的顶层窗口的大小来创建的。当系统在创建子窗口或者弹出窗口时指定CW_USERDEFAULT,则系统将会将窗口的大小设置为默认的最小化窗口大小。
4.2 追踪大小 (Tracking Size)
具有WS_THICKFRAME样式的窗口系统会给它提供一个追踪大小的最大值和最小值;有这种样式的窗口具有弹性边框。追踪大小的最小值为你自己拖拽弹性边框起作用的最小值。同理,追踪大小的最大值为你自己拖拽弹性边框起作用的最大值。
系统在创建窗口时将窗口的追踪大小的最大值和最小值设置为系统规定的默认值。应用程序可以通过处理WM_GETMINMAXINFO消息获得这个默认值并且可以修改这个值。如果需要更多的消息,请查看大小和位置消息:
4.3 系统控制 (System Commands)
应用程序可以通过发送系统控制来改变菜单窗口的大小和位置。当用户在菜单窗口选择时产生系统指令。应用程序可以通过向窗口发送WM_SYSCOMMAND消息来模仿用户操作。下面的系统指令影响窗口的大小和位置:
指令
| 描述
| SC_CLOSE
| 关闭窗口 这条指令向窗口发送WM_CLOSE消息 ,窗口开展的所有工作都要清除并要摧毁自己
| SC_MAXIMIZE
| 窗口的最大化
| SC_MINIMIZE
| 窗口最小化
| SC_MOVE
| 窗口移动
| SC_RESTORE
| 使得最小化或者最大化的窗口恢复到他们未最大化和最小化之前的大小和位置
| SC_SIZE
| 启动大小指令,可以通过使用鼠标和键盘来改变窗口的大小
|
4.4 大小、位置相关的函数(Size and Position Functions)
创建窗口之后,应用程序可以调用下面的函数来设置窗口的大小或者位置,这些函数是:SetWindowPlacement、MoveWindow、SetWindowPos和DeferWindowPos。SetWindowPlacement函数设置窗口最小化的位置、最大化的位置、恢复状态的大小和位置和显示状态。MoveWindow和SetWindowPos函数基本相似,两者都是设置单一的应用程序窗口。SetWindowPos函数具有一个影响窗口显示状态额标识,而MoveWindow函数没有此标志。使用BeginDeferWindowPos,DeferWindowPos和EndDeferWindowPos可以同时设置多个窗口的位置,包括窗口大小,窗口位置,窗口Z序和窗口显示状态。
关于BeginDeferWindowPos、DeferWindowPos和EndDeferWindowPos三个函数用法的说明:(函数功能、原型以及参数说明等详细信息请自己查阅MSDN)
首先BeginDeferWindowPos函数生成一个HDWP结构
DeferWindowPos 对窗口进行移动,此函数和SetWindowPos相比只多了一个HDWP参数
最后EndDeferWindowPos函数对之前DeferWindowPos的操作来个了结。
个人猜测:针对多个窗口移动而又相互影响或者是都影响到另外一个窗口的情形,相比调用SetWindowPos,这三个函数应该可以提高窗口重绘的效率,个人猜测,并未做出验证。
应用程序可以通过调用GetWindowRect函数来获得窗口的矩形边框的坐标。GetWindowRect填充区域为一个矩形窗口的左上角到右下角。坐标是相对于屏幕左上角为原点的坐标系的坐标,即使是对于子窗口。ScreenToClient或MapWindowPoints函数映射子窗口的屏幕坐标的矩形边界相对于父窗口客户区的坐标。
ScreenToClient函数:
函数功能:将屏幕上指定点的屏幕坐标转换成用户坐标
函数原型:BHWNDOOL ScreenToClient(HWND hWnd,LPPOINT lpPoint);
参数说明:
hWnd 指向窗口的句柄,此窗口的用户空间将被用来转换
lpPoint 指向Point结构的指针,该指针含有要转换的屏幕坐标
MapWindowPoints函数:
函数功能:该函数把相对于一个窗口的坐标空间的一组点映射成相对于另一窗口的坐标空间的一组点
函数原型:int MapWindowPoints(HWND hWndFrom, HWND hWndTo,LPPOINT lpPoints, UINT cPoints);
参数说明:
hWndFrom 转换点所在的窗口的句柄,如果此参数为NULL则假定此点在屏幕上
hWndTo 转换到的窗口句柄,如果此参数为NULL则将此点转换到屏幕上
lpPoints 指向POINT结构数组的指针,此结构数组包含要转换的点,此参数也可指向RECT结构体,在此情况下cPoints的参数应设置为2
cPoints 指定lpPoints参数指向的数组中POINT结构的数目
函数GetClientRect函数获取窗口客户区的坐标。窗口客户区坐标自客户区的左上角到右下角将整个客户区填充,但是这坐标是相对于它自己的客户区的。这个意思就是客户区左上顶点的坐标一直为(0,0),并且右下角坐标为客户区的宽和高。
GetClientRect函数:
函数功能:该函数获取窗口客户区的坐标。
函数原型:BOOL GetClientRect(HWND hWnd,LPRECT lpRect);
参数说明:
hWnd 窗口的句柄
lpRect 指向一个RECT类型的Rectangle结构,该结构具有四个LONG字段,分别为left 。right 。top 和bottom
CascadeWindows函数将窗口级联在桌面上或者级联指定父窗口的子窗口。TileWindows函数就是将窗口拼接到桌面上或者拼接指定父窗口的子窗口。(具体意思我也不是太明白)
CascadeWindows函数:
函数功能:级联指定父窗口的指定子窗口
函数原型:BOOL CascadeWindows (HWND hWndParent,UINT wHow,CONST RECT *lpRect,UINT cKids,const HWND *lpKids);
参数说明:
hWndParent 父窗口句柄
wHow 指定级联方式(详细请查看MSDN)
lpRect 指向矩形区域的RECT结构体指针
cKids 指定lpKids参数数组 中元素的个数
lpKids 需要参与排列子窗口数组的指针
TileWindows函数:
函数功能:拼接指定父窗口的指定子窗口
函数原型:WORD TileWindows(HWND hWndParent,UINT wHow,CONST RECT *lpRect,UINT cKids,const HWND *lpKids);
参数说明:
hWndParent 指定的父窗口的句柄
wHow 拼接方式
lpRect 指向矩形区域的RECT结构体指针
cKids 指定lpKids参数数组中元素的个数
lpKids 需要参与排列的子窗口的数组的指针
4.5 大小和位置消息(Size and Position Messages)
在窗口的大小或者位置信息即将改变时,系统会向窗口发送一条WM_GETMINMAXINFO消息。例如,当用户通过菜单栏、弹性边框或者标题栏来点击MOVE或者SIZE时,WM_GETMINMAXINFO信息也被发送;当用户调用SetWindowPos函数来改变窗口的大小或者位置时,此消息也被发送。WM_GETMINMAXINFO消息包括一个指向MINMAXINFO结构体的指针,此结构体的内容为:窗口的默认最大化的大小和位置,还有默认追踪大小的最小值和最大值。应用程序可以通过WM_GETMINMAXINFO来重写默认值,并且还可以设置MINMAXINFO结构体的成员。窗口要想接收WM_GETMINMAXINFO消息必须有WS_THICKFRAME样式或者WS_CAPTION样式。具有WS_THICKFRAME样式的窗口在创建窗口过程期间接收WM_GETMINMAXINFO消息,也在移动或者改变大小时接收此消息。
当窗口的大小、位置、Z序位置或者显示状态即将改变时,系统会向窗口发送WM_WINDOWPOSCHANGE消息。此消息包括一个指向WINDOWPOS结构体的指针,此结构体指定窗口新的大小、位置、Z序位置以及显示状态。通过此消息来设置WINDOWPOS结构体成员对窗口的大小、位置和外观没有影响。
在改变窗口的大小、位置、Z序、显示状态之后,系统给窗口发送WM_WINDOWPOSCHANGE消息。此消息包含了一个指向[url=]WINDOWPOS[/url]结构体的指针,此结构体信息为窗口新的大小、位置、Z序以及显示状态。通过WM_WINDOWPOSCHANGE消息设置WINDOWPOS结构体的内容对窗口无影响。系统必须向DefWindowProc函数发送WM_WINDOWPOSCHANGE消息窗口才可以处理WM_SIZE和WM_MOVE消息;否则系统不会向窗口发送WM_SIZE和WM_MOVE消息。
DefWindowProc函数:
函数功能:调用缺省的窗口过程来为应用程序没有处理的窗口消息进行缺省处理。
函数原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
参数说明:
hWnd 接收消息的窗口过程的句柄
Msg 指定消息类型
wParam 指定消息的其他附加信息,参数内容与Msg有关
lParam 指定消息的其他附加信息,参数内容与Msg有关
当窗口被创建或者被改变大小时,系统向窗口发送WM_NCCALCSIZE消息。系统通过此消息来计算窗口的客户区的大小、相对于窗口左上角窗口客户区的位置。窗口通常将这个消息传递给默认的窗口过程;,然而此消息有可能对应用程序有用,应用程序会用此消息来自定义窗口的非客户区或者在窗口改变大小的过程中保护客户区的大小。如需更多的关于此方面的消息,请看绘图和重绘…
5、 窗口动画(Window Animation)
在显示或者隐藏窗口时你可以通过使用AnimateWindow函数来产生一些特殊的效果。当窗口在进行滚动、滑动或者淡出淡入这种方式的动画,这全是因为你在调用AnimateWindow函数指定了此函数的 dwFlags参数。
[url=]Animat[/url]eWindow函数:
函数功能:使得窗口在隐藏或者显示时产生特殊的效果
函数原型:BOOL AnimateWindow(HWND hWnd,DWORD dwTime,DWORD dwFlags);
参数说明:
hWnd 指定产生动画的窗口的句柄
dwTime 指定动画持续的时间
dwFlags 指定动画类型(具体类型此处不做列举,感兴趣的同学可以自行查看)
默认情况下系统使用滚动特效。此效果窗口滚动的打开(显示窗口)或者关闭(隐藏窗口)。你可以使用dwFlags参数来指定窗口是水平滚动、垂直滚动或者是斜对角的滚动。
当你指定dwFlags为AW_SLIDE时,系统会使用滑动特效。这种效果可以使窗口看上去就像是滑入视野(窗口显示)或者是滑出视野(窗口隐藏)。你可以通过指定dwFlags参数来指定窗口时水平的滑动还是垂直的滑动或者是对角线的滑动。
当你使用AW_BLEND时,系统使用阿尔法混合褪色。(注释:此标志只能被用于顶层窗口)
你也可以使用AW_CENTER,使得窗口看起来就像是向内瓦解(隐藏窗口)或者向外膨胀(显示窗口)。
6、窗口的布局和镜像(Window Layout and Mirroring)
窗口布局定义了文本和图形设备接口对象在窗口或者设备环境中的布局。一些语言,比如英语、法语德语需要你从左向右布局。其他语言比如阿拉伯语、希伯来语需要你从右向左布局。窗口对文本的布局会影响到窗口的其他GDI元素,包括位图、图标、原点的位置、按钮、级联树控件以及水平坐标是向左增大还是向右增大。例如,当一个应用程序设置从右向左布局,原点位置在窗口或者设备的右端边缘,这代表水平坐标随你向左移动了。然而,并不是所有的对象都被一个窗口布局。例如,对话框、消息框和设备环境的布局与窗口没关系,例如,图元文件、打印机设备必须单独的处理。随后的这些专题是这个问题的详细细节:
窗口函数允许你指定或者改变窗口的布局在阿拉伯语或者希伯来语版本的Windows下。注意改变RTL(right to left)布局操作不被具有CS_OWNDC样式的窗口或者具有GM_ADVANCED图形模式的设备环境所支持。
默认情况下窗口时从左向右布局的。调用CreateWindowEx函数指定其样式参数为WS_EX_LAYOUTRTL可以将窗口的布局设置为RTL。在默认情况下子窗口(在父窗口有效的情况下调用CreateWindowEx或者CreateWindow函数创建的子窗口)的布局和父窗口的布局一致。在调用CreateWindowEx函数时指定WS_EX_NOINHERITLAYOUT样式可以禁止所有的子窗口继承镜像。注意,镜像不能被奴隶窗口或者在调用CreateWindowEx函数创建窗口时将父窗口句柄设置为NULL的窗口所继承。禁止个体窗口继承镜像,通过向GetWindowLong函数或者SetWindowLong函数处理WM_NCCREATE消息可以关闭WS_EX_LAYOUTRTL样式。这个处理是除了其他处理之外必须进行的,下面的代码片段显示了此过程是如何实现的。
SetWindowLong(hWnd,
GWL_EXSTYLE,
GetWindowLong(hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL)
你可以通过调用SetProcessDefaultLayout函数来将默认布局方式设置为从右往左。在这之后创建的所有窗口在被调用时将会调用它们的镜像,但是现存的窗口不受影响,可以通过调用SetProcessDefaultLayout(0)来取消默认镜像。
SetProcessDefaultLayout函数:
函数功能:[url=]在非父窗口[/url]或拥有者窗口下创建窗口时改变窗口的默认布局方式
函数原型:BOOL SetProcessDefaultLayout(DWORD dwDefaultLayout);
参数说明:
dwDefaultLayout 默认布局
注意,SetProcessDefaultLayout函数只能映射镜像窗口的设备环境。调用SetLayout函数可以映射任意设备环境,有关更多信息,请参见讨论镜像设备上下文与窗户这个话题
在默认情况下,位图和图标在一个镜像窗口也会被反射,然而也不是所有的都会被反射。例如,文本、商业标志或者模拟时钟不应该被反射。调用SetLayout函数并将其dwLayout参数设置为LAYOUT_BITMAPORIENTATIONPRESERVED位来禁止位图镜像。调用SetLayout(hdc,0)可以将设备环境镜像关闭。
SetLayout函数:
函数功能:设置设备的布局
函数原型:DWORD SetLayout(HDC hdc,DWORD dwLayout);
参数说明:
hdc 设备环境句柄
dwLayout 指定设备环境的布局方式
调用GetProcessDefaultLayout函数可以查看当前默认布局方式。如果成功返回pdwDefaultLayout会含有,LAYOUT_RTL或者0.调用GetLayout可以查看设备环境的布局设置,如果成功返回,GetLayout返回一个DWORD,则表明布局方式是通过LAYOUT_RTL和LAYOUT_BITMAPORIENTATIONPRESERVED设置的。
GetProcessDefaultLayout函数:
函数功能:在非父窗口或拥有者窗口下创建窗口时获得当前窗口的默认布局方式
函数原型:DWORD GetProcessDefaultLayout(DWORD *pdwDefaultLayout);
参数说明:pdwDefaultLayout 指向用来接收一个存储布局方式的存储单元的指针
GetLayout函数:
函数功能:返回设备环境的布局方式
函数原型:DWORD GetLayout(HDC hdc);
参数说明:hdc 设备环境句柄
当一个窗口创建之后,你可以通过调用SetWindowLong函数来改变窗口的布局方式。例如,当用户将当前窗口的用户界面语言从阿拉伯语或希伯来语改为德语这是很必要的,。然而,当你改变当前窗口的布局方式时,你必须先让窗口变得无效然后再刷新窗口以确保窗口的所有内容都已相同的布局方式绘制。下面的代码实例,为 需要改变窗口布局的简单代码:
//Using ANSI version of GetWindowLong and SetWindowLong because Unicode
//is not needed for these calls
lExStyles=GetWindowLong(hWnd,GWL_EX_STYLE);
//Check whether new layout is oppsite the current layout
If(!!(plState->IsRTLLAyout) !=!!(lExStyles & WS_EX_LAYOUTRTL))
{
//the following lines will update the window laout
lExStyles ^=WS_EX_LAYOUT; //toggle layout
SetWindowLongA(hWnd, GWL_EXSTYLE,lExStyles);
InvalIDAteRect(hWnd,NULL,TRUE); //to update layout in the client area
}
在镜像中,你应该想到‘近’、‘远’这些术语而不是左、右。如果不这样做就会出现一些问题。当一个镜像窗口在客户区坐标和屏幕坐标之间发生绘图时将会产生错误,这是一个常见的编码实践问题。例如,应用程序使用类似于下边的代码控制窗口位置:
// DO NOT USE THIS IF APPLICATION MIRRORS THE WINDOWS
//get coordinates of the window in screen coordinates
GetWindowRect(hControl,(LPRECT)&rControlRect);
//map screen coordinates to client coordinates in dialog
ScreenToClient(hDialog,(LPPOINT)&rControlRect.left);
ScreenToClient(hDialog,(LPPOINT)&ControlRect.right);
这个导致镜像问题的原因是矩形的左边缘变为了镜像窗口的右边缘,反之亦然。为了避免这个问题用下面的方式将ScreenToClient替换为MapWindowPoints:
//USE THIS FOR MIRRORING
GetWindowRect(hControl,(LPRECT)&rControlRect);
MapWindowPoints(NULL,hDialog,(LPPOINT)&rControlRect,2);
这段代码正常是因为平台支持镜像。当客户窗口是镜像窗口时,MapWindowPoints函数会将左右两点之间的坐标进行互换。想要获得更多信息,请看MapWindowPoints函数的附录信息:
另一个常见的做法是将导致镜像窗口问题的对象定位客户窗口在屏幕的坐标而不是使用客户窗口的坐标。例如,下面的代码使用屏幕坐标的差异作为x位置在客户端坐标,在此位置控制一个对话框。
//OK If LTR layout and mapping mode of client is MM_TEXT
//but WRONG for a mirrored dialog
RECT rdDialog;
RECT rcClient;
HWND hControl = GetDlgItem(hDlg, IDD_CONTROL);
GetWindowRect(hDlg, &rcDialog); // gets rect in screen coordinates
GetWindowRect(hControl, &rcControl);
MoveWindow(hControl,
rcControl.left - rcDialog.left, // uses x position in client coords
rcControl.top - rcDialog.top,
nWidth,
nHeight,
FALSE);
这段代码是相当不错的,当对话框窗口是从左向右布局的,并客户端的映射模式是MMTEXT,因为客户区坐标系中x的新位置与在屏幕坐标系中被控制的对话框的左边缘不同。然而,在一个镜像对话框中,左右是颠倒的,所以你应该使用MapWindowPoints函数来替换他们坐标,使用下边的方式:
RECT rcDialog;
RECT rcControl;
HWND hControl – GetDlgItem(hDlg,IDD_CONTROL);
GetWindowRect(hControl,&rcControl);
//MapWindowPoints work correctly in both mirrored and non-mirrored windows
MapWindowPoints(NULL,hDlg,(LPPOINT)&rcControl,2);
//Now rcControl is in client coordinates
MoveWindow(hControl,rcControl.left,rcControl.top,nWidth,nHeight,FALSE);
6.1 镜像对话框和镜像消息框(Morroring Dialog Box and Message Box)
对话框和消息框不能够继承布局,所以你必须明确的设置他们的布局,对一个镜像消息框来说在调用MessageBox或者MessageBoxEx是选择MB_RTLREADING
如果想将对话框的布局设置为从右向左,可以在对话框模板结构DLGTEMPLATEEX中使用扩展样式WS_EX_LAYOUTRTL。属性表是对话框的一个特性。每个表都被当做是一个独立的对话框,所以如果你需要WS_EX_LAYOUTRTL样式,就必须对每个表都使用此样式。
6.2 镜像设备环境不能和一个窗口关联(Mirroring Device Contexts Not Associated with a Window)
设备环境不能和一个窗口关联,比如,图元文件、打印机DC,不能继承布局,所以你必须明确地的指定布局。可以通过调用SetLayout函数来改变设备环境的布局。
SetLayout函数很少和窗口使用,代表性的窗口仅仅通过WM_PAINT消息来获得关联DC。偶尔的程序通过调用GetDC来为窗口创建一个DC。无论哪种情况最初的布局DC都是按照WS_EX_LAYOUTRTL标志来通过BeginPaint或者GetDC来设置的。
(小提示:DC获取之后一定要记得释放,使用BeginPaint获得DC使用EndPaint释放。使用GetDC获取的DC使用ReleaseDC来释放。另外在使用GetDC获取DC和ReleaseDC函数释放DC时会稍微的造成一点内存泄露,至于内存泄露原因当前仍然未知)-------杨金鹏注释。
通过调用GetWindowOrgEx、GetWiondowExtEx、GetViewportOrgEx、和GetViewportExtEx函数所得的返回值不会影响SetLayout的调用。
当布局方式是RTL时,GetMapMode将会返回MM_ANISOTROPIC来代替MM_TEXT。通过MM_TEXT方式调用SetMapMode函数时正常的,只有GetMapMode函数的返回值是受影响的。同理当镜像模式为MM_TEXT时调用SetLayout函数时可以将镜像模式改变为MM_ANISOTROPIC。
7、 窗口销毁(Window Destroy)
一般来说,应用程序必须销毁它所创建的所有窗口,通过使用DestroyWindow函数。当一个窗口被销毁,系统隐藏这个窗口,如果它是可见的,在销毁时移除所有与它关联的内部数据。这个窗口句柄作废,并不再在此应用中使用。
应用程序销毁窗口的同时也销毁了此窗口所创建的窗口。例如,如果用户在客户区输入足够多的数据,为了保证他的任务继续,它会将一些对话框窗口关闭。应用程序在最后销毁它的主窗口(在应用程序被终结前)。
在销毁窗口之前,应用程序应该保存或者移除与此窗口相关的数据,并且释放窗口所分配的系统资源。如果应用程序不释放资源,操作系统将会释放所有的资源,并不是被应用程序释放。
销毁一个窗口不会影响到创建它的窗口类,新的窗口可以继续使用此窗口类来创建,现存的由此类创建的窗口可以继续运转。销毁一个窗口的同时会销毁掉它的子窗口。DestroyWindow函数先向父窗口发送WM_DESTROY消息,然后再向子窗口和子代窗口发送WM_DESTROY。用这样的方法所有子代窗口都将被销毁并且确保被销毁。
当用户点击关闭时窗口和窗口菜单会发送一条WM_CLOSE消息。此消息的处理机制为,在窗口销毁之前,应用程序会向用户发送确认提示,如果用户确认,应用程序会调用DestroyWindow函数来销毁窗口。
如果将要被销毁的窗口是一个活动窗口,活动窗口的活动状态和焦点将会被转移到另一个窗口,此窗口将会变成活动窗口,下一个活动窗口取决于ALT+ESC组合键。新的活动窗口决定哪个窗口接收键盘焦点。
|
免费评分
-
查看全部评分
|