我在dll中有一个实用程序功能,可以将我的表单放在主机应用程序屏幕上。我正在使用RAD Studio XE2。我必须手动执行此操作,因为主机应用程序是非VCL并且TForm的表单放置参数无法正常工作。以下代码有效。这两个函数都声明为static,我之前已将Application handle属性设置为host app。
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-&gt; 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
}
答案 0 :(得分:4)
RECT *Rect;
GetWindowRect(Application->Handle, Rect);
//Rect->left
这是不正确的。 GetWindowRect
需要一个有效的RECT*
参数,以便填充此指针指向的内存。你正在传递一个未初始化的指针,期望一些魔法会使它有效。相反,您将获得访问冲突。你需要:
RECT Rect;
GetWindowRect(Application->Handle, &Rect); // <<--- Note &
//Rect.left
答案 1 :(得分:3)
GetWindowRect期望调用者拥有矩形结构。
在原始版本中,*Rect
未指向任何有效内存。因此,当您尝试使用它时,您将访问一些您不拥有的随机内存块。操作系统否认了这一点。我很惊讶调用GetWindowRect
不会导致崩溃。
另一方面,您的更新版本声明RECT Rect
,它在堆栈上分配内存。调用函数时会自动分配该内存,并在函数完成时清除该内存。
为了澄清,这个问题与指针和引用之间的差异无关。问题完全是由于内存分配/所有权。