SetWindowPos函数的定义和参数窗 体
函数功能描述:SetWindowPos函数能够改变窗口的大小,位置和Z轴方向上的窗口顺序。
SetWindowPos函数能够改变Child、Popup或Top-level型窗口的大小,位置和Z轴方向上的窗口顺序,这些窗口根据它们在屏幕上的外表有序排列。(Topmost窗口排在Z轴方向上第一位).
函数原型:
BOOL SetWindowPos(
HWND hWnd, // 窗口句柄
HWND hWndInsertAfter, // 窗口位置句柄
int X, // 水平位置
int Y, // 垂直位置
int cx, // 宽度
int cy, // 高度
UINT uFlags // 窗口位置标志
);
参数:
hWnd:标识相应的窗口。
hWndInsertAfter:指定在Z轴方向上前面的窗口句柄.这个参数必须是一个窗口句柄或者是下面的值之一:
值 含义
HWND_BOTTOM 把窗口放在Z轴方向上最下面.如果hWnd参数标识一个Topmost窗口,则窗口丢失它的Topmost状态并且被放在所有其它窗口的最下面.
HWND_NOTOPMOST 把窗口放在所有非Topmost窗口上面(在所有Topmost窗口后面).假如窗口已经是非Topmost窗口,则没有影响.
HWND_TOP 把窗口放在Z轴方向上最上面。
HWND_TOPMOST 把窗口放在所有非Topmost窗口上面。甚至当它是非活动窗口时,窗口仍保持topmost位置。
关于这个参数用法的更多信息,可以参照下面的注释部分。
X:指定窗口左边的新位置.
Y:指定窗口上边的新位置.
cx:指定窗口新宽度.(象素为单位)
cy:指定窗口新高度.(象素为单位)
uFlags:标识相应的窗口大小和位置标志.
可以是下面的值组合:
值 含义
SWP_DRAWFRAME 沿着窗口画出框架
SWP_FRAMECHANGED 向窗口发WM_NCCALCSIZE消息,甚至大小没有改变.假如没有设置这个标志,那么只有当窗口大小被改变时WM_NCCALCSIZE消息才被发送.
SWP_HIDEWINDOW 隐藏窗口.
SWP_NOACTIVATE 不激活窗口.假如没有指定这个标志,窗口被激活并且被移动到topmost或者是非topmost组(依赖于hWndInsertAfter参数设置)上面.
SWP_NOCOPYBITS 放弃整个客户区的内容.假如没有指定这个标志,当窗口大小或位置改变后,客户区的有效内容将被保存并且拷贝回客户区。
SWP_NOMOVE 保持当前位置(忽略X和Y参数).
SWP_NOOWNERZORDER 不改变其拥有者窗口在Z轴方向的位置.
SWP_NOREDRAW 不重画窗口变化.如果此标志被指定,任何重画都不会发生。当窗口移动时,可以应用到客户区,非客户区(包括标题栏和滚动条),以及父窗口的未被覆盖部分.当此标志被指定时,应用程序必须明确地使无效或重画窗口的任何部分和父窗口需要重画的部分.
SWP_NOREPOSITION 同SWP_NOOWNERZORDER
SWP_NOSENDCHANGING 阻止窗口接收WM_WINDOWPOSCHANGING消息.
SWP_NOSIZE 保持当前大小(忽略cx和cy参数).
SWP_NOZORDER 保持当前Z轴方向前后顺序(忽略hWndInsertAfter参数).
SWP_SHOWWINDOW 显示窗口.
返回值:
如果函数调用成功,返回值为非0值.
如果函数调用失败,返回值为0.如果要得到扩展的错误信息,可以调用GetLastError。
注释:
假如指定了SWP_SHOWWINDOW或SWP_HIDEWINDOW,窗口不能被移动或改变大小。
子窗口的所有坐标都是客户区坐标(相对于父窗口的客户区左上角).
一个窗口能够成为一个Topmost窗口,可以通过设置hWndInsertAfter参数为HWND_TOPMOST并且保证SWP_NOZORDER标志没有设置,或者通过设置它的窗口在Z轴方向上的位置,以便使它在现存的任何Topmost窗口之上.当一个非Topmost窗口被设置成topmost,那么它拥有的窗口也将成为,然而它的拥有者们没有变。
假如SWP_NOACTIVATE和SWP_NOZORDER标志都没有指定(指当应用程序要求窗口被激活同时改变它在Z轴方向上的位置时),则hWndInsertAfter仅用在以下几种情况:
1.HWND_TOPMOST和HWND_NOTOPMOST标志在hWndInsertAfter中都没有指定.
2.hWnd句柄指定的窗口不是活动窗口.
如果一个应用程序不把一个非活动窗口调整到Z轴方向顶部,则不能激活非活动窗口。应用程序能够没有限制地改变一个活动窗口在Z轴方向上的位置,它能够激活一个窗口并且把它移动到topmost或者非topmost窗口的顶部。
假如一个topmost窗口被重定位到Z轴方向上最下面(HWND_BOTTOM),或者在任何非topmost窗口后面,那么它不在是topmost窗口.当一个Topmost窗口变成非topmost窗口时,它的拥有者和它拥有的窗口也都将成为非topmost窗口.
一个非Topmost窗口能够拥有一个Topmost窗口,但是反过来不行.任何窗口(例如:一个对话框)被一个Topmost窗口拥有,同时它使也自己成为一个Topmost窗口,要保证所有被拥有的窗口处在它们的拥有者的上面。
假如一个应用程序没有在前台,但是要成为前台程序,它应该调用SetForegroundWindow函数.
参看:
MoveWindow, SetActiveWindow, SetForegroundWindow
使用条件:
Windows NT:可以。
Windows 95:可以。
Win32s: 可以。
头文件: 在Winuser.h中定义。
静态库: User32.lib.
示例代码:
移动到屏幕的左上角:
SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_NOSIZE);
使其成为Topmost窗口并移动到屏幕的左上角:
SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE);
显示窗口:
SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
隐藏窗口:
SetWindowPos(m_hWnd,NULL,0,0,0,0,SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
改变窗口大小:
CRect newRect;
::GetWindowRect(m_hWnd,&newRect);
::SetWindowPos(m_hWnd,NULL,0,0,newRect.Width()/2,newRect.Height()/2,SWP_NOMOVE);
使用API函数之前必须先在程序中声明如下:
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
其中各参数的意义如下:
参数意义
hwnd As Long 欲定位的窗口
hWndInsertAfter As Long窗口句柄。在窗口列表中,窗口hwnd会置于这个窗口句柄的后面
x,y Long窗口新的x,y坐标
cx,cy Long指定新的窗口宽度和高度
wFlags Long 包含了旗标的一个整数,是下列之一
返回值 Long非零表示成功,零表示失败
下面是部分wFlags参数和它们的意义:
参数意义和使用方法
SWP_DRAWFRAME 围绕窗口画一个框
SWP_HIDEWINDOW 隐藏窗口
SWP_NOACTIVATE 不激活窗口
SWP_NOMOVE 保持当前位置 (x和y设定将被忽略) &H2
SWP_NOREDRAW 窗口不自动重画
SWP_NOSIZE 保持当前大小 (cx和cy会被忽略) &H1
SWP_NOZORDER 保持窗口在列表的当前位置 (hWndInsertAfter将被忽略)
SWP_SHOWWINDOW 显示窗口 &H40
SWP_FRAMECHANGED 强迫一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有改变
函数的使用很简单,我们只须在Form_Load中加入如下语句即可:
retValue = SetWindowPos(Me.hwnd, HWND_TOPMOST, Me.CurrentX, Me.CurrentY, 300, 300, SWP_SHOWWINDOW)
这样窗体就能保持在所有窗体的前面了。
为了学习方便,下面提供了源码:
注释:-------------------------------------------
注释:让一个窗体总是处于最前的例子
注释:-------------------------------------------
注释:程序说明:
注释:本例应用SetWindowPos函数,设置窗体的显示属性
注释:来实现让一个窗体总是处于其他窗体的前面而不会
注释:被其他窗体所遮住。
注释:-------------------------------------------
Option Explicit
注释:【VB声明】
注释: Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
注释:【说明】
注释:这个函数能为窗口指定一个新位置和状态。它也可改变窗口在内部窗口列表中的位置。该函数与DeferWindowPos函数相似,只是它的作用是立即表现出来的(在vb里使用:
针对vb窗体,如它们在win32下屏蔽或最小化,则需重设最顶部状态。如有必要,请用一个子类处理模块来重设最顶部状态
注释:【返回值】
注释: Long,非零表示成功,零表示失败。会设置GetLastError
注释:【备注】
注释:窗口成为最顶级窗口后,它下属的所有窗口也会进入最顶级。一旦将其设为非最顶级,则它的所有下属和物主窗口也会转为非最顶级。Z序列用垂直于屏幕的一根假想Z轴量
化这种从顶部到底部排列的窗口顺序
注释:【参数表】
注释: hwnd ----------- Long,欲定位的窗口
注释: hWndInsertAfter - Long,窗口句柄。在窗口列表中,窗口hwnd会置于这个窗口句柄的后面。也可能选用下述值之一:
注释: HWND_BOTTOM将窗口置于窗口列表底部
注释: HWND_TOP将窗口置于Z序列的顶部;Z序列代表在分级结构中,窗口针对一个给定级别的窗口显示的顺序
注释: HWND_TOPMOST将窗口置于列表顶部,并位于任何最顶部窗口的前面 -1
注释: HWND_NOTOPMOST将窗口置于列表顶部,并位于任何最顶部窗口的后面 -2
注释: x -------------- Long,窗口新的x坐标。如hwnd是一个子窗口,则x用父窗口的客户区坐标表示
注释: y -------------- Long,窗口新的y坐标。如hwnd是一个子窗口,则y用父窗口的客户区坐标表示
注释: cx ------------- Long,指定新的窗口宽度
注释: cy ------------- Long,指定新的窗口高度
注释: wFlags --------- Long,包含了旗标的一个整数,是下列之一:
注释: SWP_DRAWFRAME围绕窗口画一个框
注释: SWP_HIDEWINDOW隐藏窗口
注释: SWP_NOACTIVATE不激活窗口 &H10
注释: SWP_NOMOVE保持当前位置 (x和y设定将被忽略) &H2
注释: SWP_NOREDRAW窗口不自动重画
注释: SWP_NOSIZE保持当前大小 (cx和cy会被忽略) &H1
注释: SWP_NOZORDER保持窗口在列表的当前位置 (hWndInsertAfter将被忽略)
注释: SWP_SHOWWINDOW显示窗口 &H40
注释: SWP_FRAMECHANGED强迫一条WM_NCCALCSIZE消息进入窗口,即使窗口的大小没有改变
用VB制作TopMost类型窗口
TopMost这个词也许你很陌生,但具有TopMost窗口的软件你应该早就接触过,如Office97、IE等。所谓TopMost窗口是指哪些始终出现在桌面的最前方且不会被其它窗口覆盖的窗口。
一般情况下,在运行VB程序时,窗口总有可能会被其它程序的窗口所覆盖。如何在自己的应用程序中实现TopMost类型的窗口呢?我们可以通过调用WindowsAPI函数SetWindowPos来实现。
一、SetWindowPos函数介绍
SetWindowPos函数功能是将一个窗口在三维空间中移动,利用它,你可以改变一个窗口的位置,甚至可以在Z轴上改变(Z轴决定了一个窗口和其它窗口的前后关系),你还可以改变窗口的尺寸。为了实现TopMost类型的窗口,我们只需调用该函数,将窗口放在所有窗口的前面并永远保持在最前面即可。要想在VB中使用SetWindowPos函数,必须在程序的代码模块中进行如下的函数声明:
Declare Function SetwindowPos Lib "user32.dll" (ByVal hwnd As Long,ByVal hWndInsertAfter As Long,ByVal x As Long,ByVal y As Long,ByVal cx As Long,ByVal cy As Long,ByVal wFlags as Long)As Long
SetWindowPos函数各个参数的含义见表1
表1 SetWindowPos函数的参数解释
参数名 | 参数含义 |
hwnd | 要移动的窗口的句柄(可以用窗体的hwnd属性) |
hWndInsertAfter | 关于如何在Z轴上放置窗口的标记(具体见表2) |
x | 相当于窗口的Left属性 |
y | 相当于窗口的Top属性 |
cx | 相当于窗口的Right属性 |
cy | 相当于窗口的Bottom属性 |
wFlags | 关于如何移动窗口的标记(具体见表3) |
表2 HWndInsertAfter参数的可能取值及含义
hWndInsertAfter的可能取值 | 功能 |
某一窗口的句柄 | 将窗口放在该句柄指定的窗口后面 |
HWND_BOTTOM(1) | 把窗口放在Z轴的最后,即所有窗口的后面 |
HWND_TOP(0) | 将窗口放在Z轴的前面,即所有窗口的前面 |
HWND_TOPMOST(-1) | 使窗口成为“TopMost”类型的窗口,这种类型的窗口总是在其它窗口的前面,真到它被关闭 |
HWND_NOTOPMOST(-2) | 将窗口放在所有“TopMost”类型窗口的后面、其它类型窗口的前面 |
表3 wFlags参数的可能值及含义
wFlags参数的可能值 | 功能 |
SWP_DRAWFRAME(&H20) | 移动窗口后重画窗口及其上的所有内容 |
SWP_HIDEWINDOW(&H80) | 隐藏窗口,窗口隐藏后既不出现在屏幕上也不出现在任务栏上,但它仍然处于激活状态 |
SWP_NOACTIVATE(&H10) | 窗口移动后不激活窗口,当然,如果窗口在移动前就是激活的则例外 |
SWP_NOCOPYBITS(&H100) | 当窗口移动后,不重画它上面的任何内容 |
SWP_NOMOVE(&H2) | 不移动窗口(即忽略X和Y参数) |
SWP_NOSIZE(&H1) | 不改变窗口尺寸(即忽略Cx和Cy参数) |
SWP_NOREDRAW(&H8) | Do not remove the image of the window in its former position from the screen. In other words,leave behind a ghost image of the window in its old position |
SWP_NOZORDER(&H4) | 不改变窗口听Z轴位置(即忽略hWndInsertAfter参数) |
SWP_SHOWWINDOW(&H40) | 显示窗口(之前必须使用过SWP_HIDEWINDOW隐藏窗口) |
前面已提到,利用SetWindowPos函数可以决定窗口在Z轴中的位置,具体如何放置,需根据表2给hWndInsertAfter参数赋予合适的值。
另外,wFlags参数为SetWindowPos函数移动窗口提供了附加的特性,我们可以通过or运算将表3中若干个wFlags结合在一起使用,如SWP_NOMOVEOrSWP_NOSIZE既不移动窗口又不改变窗口的尺寸。但是要注意不要将功能冲突的值结合使用,如SWP_HIDEWINDOWOrSWP_SHOWWINDOW。
二、程序举例
下面,我们以一个简单的例子说明SetWindowPos函数的用法及如何实现TopMost类型窗口。
新建工程,在普通窗体Form1上放置两个命令按钮cmdNormal和cmdTopMost,命令按钮的Caption属性分别为“变成普通窗口”和“变成TopMost窗口”。cmdNormal的Enabled属性为False。为工程添加代码模块Moudall,在其中放置如下声明代码:
DeclareFunctionSetWindowPosLib"user32"(ByValhwndAsLong,ByValhWndInsertAfterAsLong,ByValxAsLong,ByValyAsLong,ByValcxAsLong,ByValcyAsLong,ByValwFlagsAsLong)AsLong
Public Const SWP_NOMOVE=&H2'不移动窗体
Public Const SWP_NOSIZE=&H1'不改变窗体尺寸
Public Const Flag=SWP_NOMOVEOrSWP_NOSIZE
Public Const HWND_TOPMOST=-1'窗体总在最前面
Public Const HWND_NOTOPMOST=-2'窗体不在最前面
为窗体添加代码如下:
Private Sub cmdNormal_Click()
cmdTopMost.Enabled=True
cmdNormal.Enabled=False
Form1.Captio="现在是普通窗口"
SetWindowPosForm1.hwnd,HWND_NOTOPMOST,0,0,0,0,Flag
EndSub
PrivateSubcmdTopMost_Click()
cmdTopMost.Enabled=False
cmdNormal.Enabled=True
Form1.Caption="现在是TopMost窗口"
SetWindowPosForm1.hwnd,HWND_TOPMOST,0,0,0,0,Flag
EndSub
按下F5,运行程序,单击“变成TopMost窗体”命令按钮,此时窗口即成为TopMost类型。随意打开桌面上的其它窗口,Form1总是处在其它窗口的前面;如果单击“变成普通窗体”按钮。则一切又恢复正常,一旦打开了其它窗口,则其它窗口会将Form1窗口覆盖。
本程序用VisualBasic5.0编写,在Pwin95、Pwin97环境下运行正常。->