1. 程式人生 > >SetWindowPos函式詳解及CenterWindow()的用法

SetWindowPos函式詳解及CenterWindow()的用法

WinAPI: SetWindowPos - 改變視窗的位置與狀態

SetWindowPos(
hWnd: HWND; {視窗控制代碼}
hWndInsertAfter: HWND; {視窗的 Z 順序}
X, Y: Integer; {位置}
cx, cy: Integer; {大小}
uFlags: UINT {選項}
): BOOL;

//hWndInsertAfter 引數可選值:
HWND_TOP = 0; {在前面}
HWND_BOTTOM = 1; {在後面}
HWND_TOPMOST = HWND(-1); {在前面, 位於任何頂部視窗的前面}
HWND_NOTOPMOST = HWND(-2); {在前面, 位於其他頂部視窗的後面}

//uFlags 引數可選值:
SWP_NOSIZE = 1; {忽略 cx、cy, 保持大小}
SWP_NOMOVE = 2; {忽略 X、Y, 不改變位置}
SWP_NOZORDER = 4; {忽略 hWndInsertAfter, 保持 Z 順序}
SWP_NOREDRAW = 8; {不重繪}
SWP_NOACTIVATE = $10; {不啟用}
SWP_FRAMECHANGED = $20; {強制傳送 WM_NCCALCSIZE 訊息, 一般只是在改變大小時才傳送此訊息}
SWP_SHOWWINDOW = $40; {顯示視窗}
SWP_HIDEWINDOW = $80; {隱藏視窗}

--------------------------------------------------------------------------------------

SetWindowPos()
函式功能:該函式改變一個子視窗,彈出式視窗式頂層視窗的尺寸,位置和Z序。子視窗,彈出式視窗,及頂層視窗根據它們在螢幕上出現的順序排序、頂層視窗設定的級別最高,並且被設定為Z序的第一個視窗。
函式原型:BOOL SetWindowPos(HWN hWnd,HWND hWndlnsertAfter,int X,int Y,int cx,int cy,UNIT.Flags);
引數:
hWnd:視窗控制代碼。
hWndlnsertAfter:在z序中的位於被置位的視窗前的視窗控制代碼。該引數必須為一個視窗控制代碼,或下列值之一:
HWND_BOTTOM:將視窗置於Z序的底部。如果引數hWnd標識了一個頂層視窗,則視窗失去頂級位置,並且被置在其他視窗的底部。
HWND_DOTTOPMOST:將視窗置於所有非頂層視窗之上(即在所有頂層視窗之後)。如果視窗已經是非頂層視窗則該標誌不起作用。
HWND_TOP:將視窗置於Z序的頂部。
HWND_TOPMOST:將視窗置於所有非頂層視窗之上。即使視窗未被啟用視窗也將保持頂級位置。

檢視該引數的使用方法,請看說明部分。
x:以客戶座標指定視窗新位置的左邊界。
Y:以客戶座標指定視窗新位置的頂邊界。
cx:以畫素指定視窗的新的寬度。
cy:以畫素指定視窗的新的高度。

uFlags:視窗尺寸和定位的標誌。該引數可以是下列值的組合:
SWP_ASNCWINDOWPOS:如果呼叫程序不擁有視窗,系統會向擁有視窗的執行緒發出需求。這就防止呼叫執行緒在其他執行緒處理需求的時候發生死鎖。
SWP_DEFERERASE:防止產生WM_SYNCPAINT訊息。
SWP_DRAWFRAME:在視窗周圍畫一個邊框(定義在視窗類描述中)。
SWP_FRAMECHANGED:給視窗傳送WM_NCCALCSIZE訊息,即使視窗尺寸沒有改變也會發送該訊息。如果未指定這個標誌,只有在改變了視窗尺寸時才傳送WM_NCCALCSIZE。
SWP_HIDEWINDOW;隱藏視窗。
SWP_NOACTIVATE:不啟用視窗。如果未設定標誌,則視窗被啟用,並被設定到其他最高階視窗或非最高階組的頂部(根據引數hWndlnsertAfter設定)。
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序(忽略hWndlnsertAfter引數)。
SWP_SHOWWINDOW:顯示視窗。

返回值:如果函式成功,返回值為非零;如果函式失敗,返回值為零。若想獲得更多錯誤訊息,請呼叫GetLastError函式。
備註:如果設定了SWP_SHOWWINDOW和SWP_HIDEWINDOW標誌,則視窗不能被移動和改變大小。如果使用SetWindowLoog改變了視窗的某些資料,則必須呼叫函式SetWindowPos來作真正的改變。使用下列的組合標誌:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED。
有兩種方法將視窗設為最頂層視窗:一種是將引數hWndlnsertAfter設定為HWND_TOPMOST並確保沒有設定SWP_NOZORDER標誌;另一種是設定視窗在Z序中的位置以使其在其他存在的視窗之上。當一個視窗被置為最頂層視窗時



DWORD_PRT SetWindowPos(HWND hWnd,HWND hInsertAfter,int x,int y,int cx,int cy,UINT nFlag)

SetWindowPos函式功能是將一個視窗在三維空間中移動,利用它,你可以改變一個視窗的位置,甚至可以在Z軸上改變(Z軸決定了一個視窗和其它視窗的前後關係),你還可以改變視窗的尺寸。為了實現TopMost型別的視窗,我們只需呼叫該函式,將視窗放在所有視窗的前面並永遠保持在最前面即可


表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
隱藏視窗)


註釋:

假如指定了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);
SWP_NOCOPYBITS = $100; {丟棄客戶區}
SWP_NOOWNERZORDER = $200; {忽略 hWndInsertAfter, 不改變 Z 序列的所有者}
SWP_NOSENDCHANGING = $400; {不發出 WM_WINDOWPOSCHANGING 訊息}
SWP_DRAWFRAME = SWP_FRAMECHANGED; {畫邊框}
SWP_NOREPOSITION = SWP_NOOWNERZORDER;{}
SWP_DEFERERASE = $2000; {防止產生 WM_SYNCPAINT 訊息}
SWP_ASYNCWINDOWPOS = $4000; {若呼叫程序不擁有視窗, 系統會向擁有視窗的執行緒發出需求}

CenterWindow()的用法為:
void CenterWindow( CWnd* pAlternateOwner = NULL );
其中引數pAlternateOwner指向所想居中的視窗的指標。
然後利用函式GetSystemMetrics( int nIndex )得到系統當前設定如螢幕解析度等。
nIndexs= SM_CXSCREEN 時函式返回螢幕的寬度;返回值單位為畫素點。
nIndexs= SM_CYSCREEN 時函式返回螢幕的高度;返回值單位為畫素點。
函式BOOL GetWindowPlacement( WINDOWPLACEMENT* lpwndpl ) 是最重要的。他的引數為一個指向結構變數WINDOWPLACEMENT的指標(lpwndpl);其中WINDOWPLACEMENT結構變數資料結構具體為:
typedef struct tagWINDOWPLACEMENT {
UINT length;
UINT flags;
UINT showCmd;
POINT ptMinPosition;
POINT ptMaxPosition;
RECT rcNormalPosition;
} WINDOWPLACEMENT;
他包含了視窗在螢幕上的定位資訊。其中成員變數的含義為:
length:指結構變數的長度,單位位元組。
flags: 標誌值,控制視窗最小化或視窗還原的方法,可以取如下值:
WPF_SETMINPOSITION:指定視窗最小化時的x位置和y位置。
WPF_RESTORETOMAXIMIZED:指定視窗以最大化方式還原,儘管可能視窗並不是在最大化時最小化的。不改變視窗的預設還原方式。
showCmd:指定視窗的當前顯示狀態。可以取值:
SW_HIDE:隱藏視窗並激活另一視窗。
SW_MINIMIZE:最小化指定視窗並激活系統視窗列表中最頂層視窗。
SW_RESTORE:啟用並顯示視窗,如果視窗處於最小化或最大化狀態,則視窗還原到原始大小和位置。
SW_SHOW:以視窗的當前大小和位置啟用並顯示視窗。
SW_SHOWMAXIMIZED:以最大化方式啟用並顯示視窗。
SW_SHOWMINIMIZED:以圖示方式啟用並顯示視窗。
SW_SHOWMINNOACTIVE:以圖示方式視窗。 但不改變視窗的活動狀態。
SW_SHOWNA:以視窗的當前狀態顯示視窗。
SW_SHOWNOACTIVATE:以視窗最近一次的大小和位置顯示視窗。 但不改變視窗的活 動狀態。
SW_SHOWNORMAL:啟用並顯示視窗。如果視窗被最大化或最小化,則視窗還原到原始大小和位置。
ptMinPosition:指定視窗最小化時的左傷角座標。
ptMaxPosition:指定視窗最大化時的左傷角座標。
rcNormalPosition:指定視窗在還原時的座標。
通過靈活使用函式GetWindowPlacement()就可以得到視窗的配置資訊。
看到這,可能有些讀者已經想到了GetWindowPlacement()函式的姐妹函式SetWindowPlacement(),不用多說,其用法如下:
BOOL SetWindowPlacement( WINDOWPLACEMENT* lpwndpl );
顯然,通過函式SetWindowPlacement(),再加以簡單的計算,我們就可以來設定視窗的位置、大小以及狀態等,從而可以自如地控制視窗顯示與否以及視窗的大小、位置等