1

ホスト アプリケーション画面の中央にフォームを配置するためのユーティリティ関数が dll に含まれています。RAD Studio XE2 を使用しています。ホスト アプリケーションが非 VCL であり、TForm のフォーム配置パラメータが正しく機能しないため、手動で行う必要があります。以下のコードは機能します。どちらの関数も静的に宣言されており、以前にアプリケーション ハンドル プロパティをホスト アプリに設定しました。

   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 を設定すると Access Violation 例外がスローされました。誰でも理由を説明できますか?

   // 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 に答える