许多软件,特别是占桌面面积不是很大的软件,通常都提供了一个常居顶端的功能(可能有的软件不是这么叫法,但作用是相同的),它的作用是保持窗口一直在其他窗口的上面,可以省去频繁切换窗口的动作。
如果你想这么做,有一个API可以实现: SetWindowPos,声明是这样的:
Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (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是窗口的句柄,x、y、cx、cy分别是窗口的x和y坐标、宽和高度。hWndInsertAfter用来指定窗口的Z位置(或称Z顺序)。如果你经常接触3D方面的软件,你就知道Z代表深度。这个参数接受5种值:HWND_BOTTOM、 HWND_NOTOPMOST、HWND_TOP、HWND_TOPMOST或者另一个窗口的句柄。而wFlags用来指定附加的选项。
你可以用它改变窗口的位置和大小,而且它允许你同时改变Z位置(当然,在VB中不用API你也可以改变窗体大小和位置)。比如让窗口退到最下面,可以这么使用:
SetWindowPos Me.hWnd, HWND_BOTTOM, 10&, 10&, 80&, 120&, 0&
想要常居顶端,只需把HWND_BOTTOM改为 HWND_TOPMOST,而HWND_NOTOPMOST则是取消常居顶端,HWND_TOP是把窗口的Z位置改为最前。如果这个参数传递的是另一个窗口的句柄,则是把该窗口的Z 位置更改为在另一个窗口的下面。
非常简单的事情。不过如果像上面一样做,是不是单单改个Z位置也要计算窗口位置和大小?最后一个参数又是干什么用的呢?wFlags可以让SetWindowPos忽略或执行某种行为。这里给出一部分:
SWP_DRAWFRAME和SWP_FRAMECHANGED:强制发送 WM_NCCALCSIZE消息给窗口
SWP_HIDEWINDOW:隐藏窗口
SWP_NOACTIVATE:不激活窗口
SWP_NOMOVE:保持当前位置(忽略x和y)
SWP_NOREDRAW:窗口不自动重画
SWP_NOSIZE:保持当前大小(忽略cx和cy)
SWP_NOZORDER:保持窗口在列表的当前位置(忽略hWndInsertAfter)
SWP_SHOWWINDOW:显示窗口
这些参数可以使用Or运算组合,所以如果你不希望改变窗口位置和大小,你只需要给最后一个参数传递(SWP_NOMOVE Or SWP_NOSIZE)即可。如下:
SetWindowPos Me.hWnd, HWND_TOPMOST, 0&, 0&, 0&, 0&, SWP_NOMOVE Or SWP_NOSIZE
这里的x、y、cx、cy的值将被忽略。其他值的组合,你可以自己去试试。
好了,这个看起来好像有点复杂的API已经变得很清晰,那么轮到上一话的收尾。
WM_NCCALCSIZE消息是在计算窗口的客户区大小时被发送的,它主要是让程序可以收到该消息后重新计算客户区的大小。我们先不管它是不是也能像许多以WM_开头的消息一样由我们发送给程序让它产生作用,但它使用起来的复杂程度让我宁可选择改变窗体大小再改回去。当我们改变窗口的大小时,很明显的就是它一定会重新计算客户区大小以调整外观。既然这个函数可以强制发送WM_NCCALCSIZE消息,那么我们就应该试一试。
SetWindowPos Me.hwnd, 0&, 0&, 0&, 0&, 0&, SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOMOVE Or SWP_FRAMECHANGED
为了不改变窗口大小、位置和Z顺序(就是要窗口保持原状),我使用SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOMOVE,让它忽略前面所有的参数,最后加个 Or SWP_FRAMECHANGED 就是让它重新计算客户区大小。把上面的一行放到前一话中更改风格的那一句下面,再执行程序。
MSDN上的 解释 :::
其内部定义:
BOOL SetWindowPos(
HWND hWnd, // handle of window
HWND hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
UINT uFlags // window-positioning flags
);
参数解释:
hWnd
Identifies the window. 窗口句柄
hWndInsertAfter 窗口叠层位置
Identifies the window to precede the positioned window in the Z order. This parameter must be a window handle or one of the following values:
Value Meaning
设置值:
HWND_BOTTOM =1在底层的"普通层"
Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
HWND_NOTOPMOST= -2 在所有非"普通层"之上的"普通层"
Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.
HWND_TOP =0在顶层的"普通层"
Places the window at the top of the Z order.
HWND_TOPMOST = -1在所用"普通层"之上的"最顶层"
Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
X 窗口左坐标
Specifies the new position of the left side of the window.
Y 窗口上坐标
Specifies the new position of the top of the window.
cx 窗口宽度(单位为pixels)
Specifies the new width of the window, in pixels.
cy 窗口高度(单位为pixels)
Specifies the new height of the window, in pixels.
uFlags 附加参数
Specifies the window sizing and positioning flags. This parameter can be a combination of the following values:
Value Meaning 参数值:
SWP_DRAWFRAME =0x0020窗口带边框
Draws a frame (defined in the window’s class description) around the window.
SWP_FRAMECHANGED =0x0020发送边框改变消息
Sends a WM_NCCALCSIZE message to the window, even if the window’s size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window’s size is being changed.
SWP_HIDEWINDOW =0x0080窗口隐藏
Hides the window.
SWP_NOACTIVATE =0x0010不激活窗口
Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).
SWP_NOCOPYBITS =0x0100不保留显示缓存的拷贝
Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.
SWP_NOMOVE =0x0002不可移动窗口(忽略X,Y参数)
Retains the current position (ignores the X and Y parameters).
SWP_NOOWNERZORDER =0x0200不改变父窗口叠层顺序
Does not change the owner window’s position in the Z order.
SWP_NOREDRAW =0x0008不重画窗口
Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.
SWP_NOREPOSITION =0x0200
Same as the SWP_NOOWNERZORDER flag.
SWP_NOSENDCHANGING =0x0400不接受窗口位置改变的消息
Prevents the window from receiving the WM_WINDOWPOSCHANGING message.
SWP_NOSIZE =0x0001窗口大小不变(忽略CX,CY参数)
Retains the current size (ignores the cx and cy parameters).
SWP_NOZORDER =0x0004不改变叠层顺序(忽略hWndInsertAfter参数)
Retains the current Z order (ignores the hWndInsertAfter parameter).
SWP_SHOWWINDOW =0x0040显示窗口
Displays the window.
注意:如果要使用上述多个uFlags参数, 只要将几个参数相加的和赋给uFlags即可.
Return Values返回值
函数执行成功返回非0值, 不成功返回0.
Remarks 特别说明(不翻译了)
If the SWP_SHOWWINDOW or SWP_HIDEWINDOW flag is set, the window cannot be moved or sized.
All coordinates for child windows are client coordinates (relative to the upper-left corner of the parent window’s client area).
A window can be made a topmost window either by setting the hWndInsertAfter parameter to HWND_TOPMOST and ensuring that the SWP_NOZORDER flag is not set, or by setting a window’s position in the Z order so that it is above any existing topmost windows. When a non-topmost window is made topmost, its owned windows are also made topmost. Its owners, however, are not changed.
If neither the SWP_NOACTIVATE nor SWP_NOZORDER flag is specified (that is, when the application requests that a window be simultaneously activated and its position in the Z order changed), the value specified in hWndInsertAfter is used only in the following circumstances:
· Neither the HWND_TOPMOST nor HWND_NOTOPMOST flag is specified in hWndInsertAfter.
· The window identified by hWnd is not the active window.
An application cannot activate an inactive window without also bringing it to the top of the Z order. Applications can change an activated window’s position in the Z order without restrictions, or it can activate a window and then move it to the top of the topmost or non-topmost windows.
If a topmost window is repositioned to the bottom (HWND_BOTTOM) of the Z order or after any non-topmost window, it is no longer topmost. When a topmost window is made non-topmost, its owners and its owned windows are also made non-topmost windows.
A non-topmost window can own a topmost window, but the reverse cannot occur. Any window (for example, a dialog box) owned by a topmost window is itself made a topmost window, to ensure that all owned windows stay above their owner.
If an application is not in the foreground, and should be in the foreground, it must call the SetForegroundWindow function.
以上来源于MSDN.