2013-02-28 95 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

相关问题