2013-02-28 92 views
1

我在dll中有一個實用程序功能,可以在主機應用程序屏幕上居中顯示我的表單。我正在使用RAD Studio XE2。我必須手動執行它,因爲主機應用程序是非VCL並且TForm的表單放置參數無法正常工作。下面的代碼工作。這兩個函數都聲明爲靜態的,並且我以前將應用程序句柄屬性設置爲主機應用程序。爲什麼使用指針調用GetWindowRect會導致異常,但地址不是

void MyClass::GetAppCenter(POINT * pos) { 
     RECT Rect; 
     GetWindowRect(Application->Handle, &Rect); 
     pos->x = (Rect.left + Rect.right)/2; 
     pos->y = (Rect.top + Rect.bottom)/2; 
    } 

    void MyClass::PlaceForm(TForm * f) { 
     POINT pos; 
     GetAppCenter(&pos); 
     for (int i = 0; i < Screen->MonitorCount; i++) { 
     TRect r = Screen->Monitors[i]->WorkareaRect; 
     if (r.Contains(pos)) { 
      f->Left = (r.Left + r.Right)/2 - f->Width/2; 
      f->Top = (r.Top + r.Bottom)/2 - f->Height/2; 
      return; 
     } 
     } 
    } 

我最初GetAppCenter代碼使用矩形*代替,並返回正確的值,但扔了訪問衝突異常當我設置F->左。誰能解釋爲什麼?

// original version 
    void OasisUtils::GetOasisCenter(POINT * pos) { 
     RECT *Rect; 
     GetWindowRect(Application->Handle, Rect); 
     pos->x = (Rect->left + Rect->right)/2; 
     pos->y = (Rect->top + Rect->bottom)/2; 
     delete Rect; // tried with and without this 
    } 

回答

3

GetWindowRect預計調用方擁有矩形結構。

在您的原始版本中,您的*Rect不指向任何有效的內存。所以當你嘗試使用它時,你正在訪問一些你不擁有的隨機內存塊。操作系統否認這一點。我很驚訝,撥打GetWindowRect不會導致崩潰。

另一方面,您的更新版本聲明RECT Rect,它在堆棧上分配內存。當您的功能被調用時,該內存會自動分配,並在您的功能完成時被清除。

爲了澄清,這個問題不必與指針和引用之間的差異。問題完全是由於內存分配/所有權。

+0

謝謝@Philip,當然。初學者錯誤。 – marcp 2013-02-28 19:07:49

4
RECT *Rect; 
    GetWindowRect(Application->Handle, Rect); 
    //Rect->left 

這是不正確。 GetWindowRect需要一個有效的RECT*參數,以便它填充指針指向的內存。而是傳遞一個未初始化的指針,期望某些魔法會使其有效。相反,您正在訪問違規。您需要:

RECT Rect; 
    GetWindowRect(Application->Handle, &Rect); // <<--- Note & 
    //Rect.left 
+0

感謝@羅曼,兩個答案同樣有幫助和正確,但我只能標記1作爲答案,所以我選擇了第一次提交。 – marcp 2013-02-28 19:08:14

+0

@marcp:沒問題,你選擇最適合你的一個(即使我比其他人早一分鐘和兩分鐘)。 – 2013-02-28 19:25:21

相關問題