讓視窗始終在最前面顯示 VB
最近想做一個桌面的類似檯曆的VB程式,其中最主要的就是顯示效果的問題,一般我們可能要求有一個異樣的外觀,另外我們還可能要讓它總是顯示在最前面,所以我就將我做的讓VB視窗總是在最前面顯示的總結寫出來大家參考一下,其實想要讓視窗始終在最前面顯示,只需要一個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
函式的具體用法如下:
VB宣告 | ||
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 | ||
說明 | ||
這個函式能為視窗指定一個新位置和狀態。它也可改變視窗在內部視窗列表中的位置。該函式與DeferWindowPos函式相似,只是它的作用是立即表現出來的(在vb裡使用:針對vb窗體,如它們 在win32下遮蔽或最小化,則需重設最頂部狀態。如有必要,請用一個子類處理模組來重設最頂部狀態 | ||
返回值 | ||
Long,非零表示成功,零表示失敗。會設定GetLastError | ||
引數表 | ||
引數 | 型別及說明 | |
hwnd | Long,欲定位的視窗 | |
hWndInsertAfter | Long,視窗控制代碼。在視窗列表中,視窗hwnd會置於這個視窗控制代碼的後面。也可能選用下述值之一: | |
HWND_BOTTOM | 將視窗置於視窗列表底部 | |
HWND_TOP | 將視窗置於Z序列的頂部;Z序列代表在分級結構中,視窗針對一個給定級別的視窗顯示的順序 | |
HWND_TOPMOST | 將視窗置於列表頂部,並位於任何最頂部視窗的前面 | |
HWND_NOTOPMOST | 將視窗置於列表頂部,並位於任何最頂部視窗的後面 | |
x | Long,視窗新的x座標。如hwnd是一個子視窗,則x用父視窗的客戶區座標表示 | |
y | Long,視窗新的y座標。如hwnd是一個子視窗,則y用父視窗的客戶區座標表示 | |
cx | Long,指定新的視窗寬度 | |
cy | Long,指定新的視窗高度 | |
wFlags | Long,包含了旗標的一個整數 | |
SWP_DRAWFRAME | 圍繞視窗畫一個框 | |
SWP_HIDEWINDOW | 隱藏視窗 | |
SWP_NOACTIVATE | 不啟用視窗 | |
SWP_NOMOVE | 保持當前位置(x和y設定將被忽略) | |
SWP_NOREDRAW | 視窗不自動重畫 | |
SWP_NOSIZE | 保持當前大小(cx和cy會被忽略) | |
SWP_NOZORDER | 保持視窗在列表的當前位置(hWndInsertAfter將被忽略) | |
SWP_SHOWWINDOW | 顯示視窗 | |
SWP_FRAMECHANGED | 強迫一條WM_NCCALCSIZE訊息進入視窗,即使視窗的大小沒有改變 | |
註解 | ||
視窗成為最頂級視窗後,它下屬的所有視窗也會進入最頂級。一旦將其設為非最頂級,則它的所有下屬和物主視窗也會轉為非最頂級。Z序列用垂直於螢幕的一根假想Z軸量化這種從頂部到底部排列的視窗順序 |
在VB中宣告此函式之後,我們就可以用以下呼叫將視窗放置在最前面了
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
其中SWP_NOMOVE是常量H1,SWP_NOSIZE是常量H2
一個簡單的例子:
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
Private Const HWND_TOPMOST& = -1 ' 將視窗置於列表頂部,並位於任何最頂部視窗的前面
Private Const SWP_NOSIZE& = &H1 ' 保持視窗大小
Private Const SWP_NOMOVE& = &H2 ' 保持視窗位置
Private Sub Form_Load()
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE '將視窗設為總在最前
End Sub
但是我們在用的時候可能發現這樣不能保證視窗總是在最前面的,這樣我們可以採用一些辦法,在我做的桌面檯曆中我就是使用定時器實現的,即每當我我時間發生改變的時候我都會讓該視窗重新置到最前端。
使用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 Long 欲定位的視窗
hWndInsertAfter 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訊息進入視窗,即使視窗的大小沒有改變
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
Const HWND_TOPMOST = -1
Const SWP_SHOWWINDOW = &H40
Private Sub Form_load()
Dim retValue As Long
註釋:將窗體設定為處於所有視窗的頂層,注意在 VB 中執行時,
’可能不行,但編譯成EXE後就可以了
retValue = SetWindowPos(Me.hwnd, HWND_TOPMOST, Me.CurrentX,
Me.CurrentY, 300, 300, SWP_SHOWWINDOW)
End Sub
'呼叫一個API函式SetWindowPos可實現此功能?
'首先新增一個公用模組,將下面的程式碼放到模組的宣告段中。
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
Public Const HWND_TOPMOST = -1
Public Const SWP_NOMOVE = &H2
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOZORDER = &H8
'將下面的子程式放到模組中
Public Sub SetFormTopmost(TheForm As Form)
SetWindowPos TheForm.hwnd, HWND_TOPMOST, 0, 0, 0, 0, _
SWP_NOZORDER + SWP_NOMOVE + SWP_NOSIZE
End Sub
'最後,通過呼叫該子程式設定你想要放置的窗體。例如,你想將窗體frmMyForm放在最前面,程式碼如下:
Private Sub Form_Load()
SetFormTopmost frmMyForm
End Sub