我尝试的第一件事没有奏效:我猜这个问题与 Vista 上较宽的窗口边框有关。我认为 VCL 中的 UpdateAnchorRules 由于设计宽度与 Vista 上窗口的实际宽度之间的差异而以某种方式计算不正确。查看 VCL 源代码,很明显更改锚点会导致再次调用 UpdateAnchorRules 并(希望)正确计算,因为它现在具有可用表单的实际宽度。
我添加了
TAnchors t = BlahBtn->Anchors;
t >> akRight;
BlahBtn->Anchors = t;
t << akRight;
BlahBtn->Anchors = t;
到我的表单的构造函数。
没有喜悦。行为完全不受影响。
我认为这在此过程中可能为时过早,因此将相同的代码移至 FormShow 方法,同样不成功。作为最后一次尝试,我将表单的设计更改为按钮不再具有 akRight 并将代码更改为
TAnchors t = BlahBtn->Anchors;
t << akRight;
BlahBtn->Anchors = t;
...这也失败了 - 行为完全不受影响,除了我打破了 XP 上按钮的定位,以防保存的表单大小(我从注册表中读取并应用于 FormShow 中的表单)不是默认值。
在表单生命周期的各个时间点添加了一吨的调试代码,输出表单的宽度、按钮的宽度、按钮的左侧、表单的 ClientRect 等,我发现了问题。出于某种原因(可能仍然与窗口边框相关 - 我没有设法找出确切的原因),VCL 正在打开窗口,其宽度低于应有的 4 个像素。此后不久,宽度得到了纠正,但到那时,锚定(和 UpdateAnchorRules)已经将按钮的位置固定在右侧太远 4 个像素处。
解决方法是:
void __fastcall TFooBarDlg::CreateParams(TCreateParams &Params)
{
TForm::CreateParams(Params);
int i = GetSystemMetrics(SM_CXSIZEFRAME);
Params.Width=Params.Width+(2*(i-4));
}
这使用 Vista 报告的不同边框大小来更正表单的初始宽度。它会在 Vista 上导致正确的行为,同时在其他 Windows 版本(以及具有“经典”外观的 Vista)上保留它。
希望这可以帮助某人。