1

我在 dll 中有一个实用程序函数,可将我的表单置于主机应用程序屏幕的中心。我正在使用 RAD Studio XE2。我必须手动完成,因为主机应用程序是非 VCL 并且 TForm 的表单放置参数无法正常工作。下面的代码有效。这两个函数都声明为静态的,并且我之前已将 Application 句柄属性设置为主机应用程序。

   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 代码改用了 Rect * 并返回了正确的值,但是当我设置 f->Left 时抛出了访问冲突异常。谁能解释为什么?

   // 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
   }
4

2 回答 2

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

这是不正确的。GetWindowRect需要一个有效的RECT*参数,以便它填充此指针指向的内存。相反,您传递的是一个未初始化的指针,期望一些魔法会使它有效。相反,您会遇到访问冲突。你需要:

  RECT Rect;
  GetWindowRect(Application->Handle, &Rect); // <<--- Note &
  //Rect.left 
于 2013-02-28T18:30:53.973 回答
3

GetWindowRect期望调用者拥有矩形结构。

在您的原始版本中,您*Rect没有指向任何有效的内存。因此,当您尝试使用它时,您正在访问一些您不拥有的随机内存块。操作系统否认这一点。我只是惊讶于调用GetWindowRect不会导致崩溃。

另一方面,您的更新版本声明RECT Rect,它在堆栈上分配内存。调用函数时会自动分配该内存,并在函数完成时清理该内存。

澄清一下,这个问题与指针和引用之间的差异无关。问题完全是由于内存分配/所有权。

于 2013-02-28T18:32:37.950 回答