2014-10-06 188 views
1

我在Visual Studio 2008 C++中工作。我有一個MFC對話框,裏面有一個控件。我正試圖在控件中放置另一個對話框。GetWindowRect座標不是屏幕相對的

SetWindowPos()在第二個對話框上清楚地使用了屏幕座標,所以我需要獲取控件的屏幕座標或父對話框。 MSDN文檔說GetWindowRect()提供了「屏幕座標相對於顯示屏幕的左上角」,但這不是我所得到的。在控件上,它給出了相對於父項的座標。在父項上,它給出了left = 0和top = 0。我也嘗試了GetWindowPlacement()中的矩形,它給出了同樣的事情。一切都與父母有關。

爲什麼GetWindowRect()不返回屏幕相對座標?有沒有另一種方法來獲得他們?我不是新的編程,但對於Windows編程,Visual Studio和MFC來說是相當新穎的,所以我可能會錯過某些明顯的東西。

這是我在OnInitDialog正在做父對話框:

// TestApp message handlers 

BOOL TestApp::OnInitDialog() 
{ 
    CDialog::OnInitDialog(); 

    FILE * pFile = fopen("out.txt","w"); 
    CRect winRect; 
    GetWindowRect(&winRect); 
    fprintf(pFile,"left=%li top=%li right=%li bottom=%li\n",winRect.left,winRect.top,winRect.right,winRect.bottom); fflush(pFile); 
    fclose(pFile); 

    return TRUE; // return TRUE unless you set the focus to a control 
} 

運行時,對話框不會在屏幕的左上角出現,但out.txt包含:

left=0 top=0 right=297 bottom=400 
+0

從來沒有! GetWindowRect永遠不會返回任何相對座標。你總是得到屏幕座標。告訴我們你的代碼來澄清這一點! – xMRi 2014-10-06 16:20:17

+0

而不是描述,顯示你的代碼。海報宣稱他們在做「這個和那個」的次數太多了,結果他們沒有做他們自稱的東西。 – PaulMcKenzie 2014-10-06 16:21:09

+0

如果您不熟悉Windows編程,請不要使用需要熟悉Windows API的框架(如MFC)。相反,首先要了解Windows API。這既容易學習和理解,也容易直接影響。 [學習使用C++編程Windows](http://msdn.microsoft.com/en-us/library/windows/desktop/ff381399.aspx)是一個很好的起點。 – IInspectable 2014-10-06 16:24:03

回答

0

寫在對方的回答:

的OnInitDialog被稱爲前的窗口移動到其最終位置。如果稍後調用GetWindowRect,則會看到它返回適當的座標。

只需使用帶有WM_APP + n消息的PostMessage即可。該消息將在消息泵運行時到達,並且消息將在窗口定位並顯示在屏幕上時到達。

或使用計時器。這具有相同的效果。

+0

向您發佈消息不是解決方案。發佈的消息以嚴格的FIFO順序由窗口接收。如果您發佈信息太早,將會過早處理。您必須在系統發佈其「WM_WINDOWPOSCHANGED」消息後立即發佈消息。既然你不知道系統何時做,你就回到原點。另一方面,使用定時器具有非常不同的效果:低優先級消息被移動到消息隊列的後面,並且只有在沒有可用的發佈消息或輸入消息時,窗口才會收到它們。 – IInspectable 2014-10-07 13:07:10

+0

WM_WINDOWPOSCHANGED與SendMessage一起發送。它不通過消息隊列發送。所以沒有先入先出!任何使用SendMessage發送的消息都將在對話框的消息泵啓動之前到達。只需設置一個斷點並查看調用堆棧!並且因爲窗口在消息循環開始之前顯示,所有事情都完成了...... – xMRi 2014-10-07 19:45:08

+0

@IInspectable:使用PostMessage WM_APP + n的代碼完美地工作。窗口位置在消息到達時設置。沒有必要在WM_WINDOWPOSCHANGED中發佈此消息!在WM_INITDIALOG中完成它就足夠了。 – xMRi 2014-10-08 06:51:21

0

OnInitDialog在之前被稱爲窗口被移動到其最終位置。如果您稍後致電GetWindowRect,則會看到它返回適當的座標。

+0

是否有一個OnSomething函數,我可以把它放在窗口移動到最終位置後立即調用它?我查看了CWnd的成員函數,但我不知道要使用哪一個。 – blippi 2014-10-06 17:32:39

0

OnInitDialog在顯示對話框之前由框架調用。在這點上,既沒有最終尺寸也不位置是已知的:

視窗期間CreateCreateIndirect,或DoModal呼叫時,顯示對話框之前其立即發生發送WM_INITDIALOG消息到對話框。

對話框的最終大小和位置是窗口定位協商的結果。發送到可用信息的對話框的第一條消息是WM_WINDOWPOSCHANGED。使用MFC,此消息通過CWnd::OnWindowPosChanged處理。自定義處理代碼可以通過在您的CDialog派生類中重寫OnWindowPosChanged來實現。

+0

這裏的缺點是您不止一次收到該消息... – xMRi 2014-10-08 06:52:01

+0

@xMRi:問題中沒有提到應用程序只需要通知一次。如果存在額外的需求,我相信你甚至可以解決跨呼叫存儲狀態信息的挑戰。總而言之,這是一個相當蹩腳的解釋,用於解決一個合適的答案。 – IInspectable 2014-10-08 10:52:07