SetWindowPos 和Z序


參考文檔:http://www.cnblogs.com/findumars/p/3948315.html

 

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


頭文件: 在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; {若調用進程不擁有窗口, 系統會向擁有窗口的線程發出需求}

 

 

 Z 序:一個重疊窗口的堆,每個窗口在Z 序中 都有唯一一個位置。一個窗口的Z 序 ,指明了該窗口在重疊窗口堆中的位置。這個窗口堆 是沿着一個虛擬的軸——“ Z 軸”,從屏幕上垂直向屏幕外延伸。 Z 序頂部的窗口覆蓋 Z 序中的其他窗口。 Z 序底部的窗口被 Z 序中的其他窗口覆蓋。

   系統用一個單鏈表維護 Z 序。系統按照頂端窗口、頂層窗口和子窗口的分類 ,將窗口插入到 Z 序表中。頂端窗口覆蓋其他所有非頂端窗口,而不管它是不是活動窗口或是不是前台窗口。頂端窗口有 WS_EX_TOPMOST 風格。在 Z 序中,所有頂端窗口都在非頂端窗口之前。在 Z 序中,子窗口是按着他的父窗口進行分組的。

   應用程序一旦創建了一個窗口,系統就將其放入Z 序中 同類窗口的頂部。可以調用 BringWindowToTop() 函數,把某窗口拉到 Z 序中同類窗口的頂部。可以利用 SetWindowPos() 和 DeferWindowPos() 函數對 Z 序進行重新排列。

     用戶在激活不同的窗口過程中會改變 Z 序。因為系統會將活動窗口,放置在 Z 序中同類窗口的頂部 。當一個窗口變成 Z 序中的頂層窗口時,它的所有子窗口也變為頂層窗口。可以用 GetTopWindow() 來查找一個父窗口的所有子窗口,並返回( Z 序中)頂部子窗口的句柄。用 GetNextWindow() 函數,可以獲得 Z 序中的前一個或后一個窗口的句柄。

對於頂端窗口,頂層窗口和子窗口,如果只考慮同一類的話,如果有多個,總會一個覆蓋另一個。但是這三類是按照上面講的排列的。也就是有人講的: 
1.TopMost在最上面 
2,頂級窗口次之 
3,子窗口在父窗口之上 
4,同級窗口當前激活窗口在前

 

HDWP hdwp = BeginDeferWindowPos(2);

hdwp = DeferWindowPos( hdwp, hStatic, NULL, 0, 0,100, 20, SWP_NOACTIVATE | SWP_NOZORDER |SWP_NOMOVE );
hdwp = DeferWindowPos( hdwp, hEdit, NULL, 0, 0, 100, 20, SWP_NOACTIVATE | SWP_NOZORDER |SWP_NOMOVE );
EndDeferWindowPos( hdwp );

其作用和SetWindowPos()差不多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM