这个对话框正好显示在按钮下面,但是在Windows 8中,对话框被移动到左边和上面。如何在所有Windows版本中获得相同的结果?
procedure TForm1.Button3Click(Sender: TObject);
var p: TPoint;
begin
p := Button3.ClientToScreen(Point(0, Button3.Height));
MessageDlgPos('', mtInformation, [mbOK], 0, p.X, p.Y);
end;

更新:如果我们打开表单而不是对话框,如果该表单具有BorderStyle bsSizeable或bsSizeToolWin,那么一切都正常。否则(bsDialog、bsSingle、bsToolWindow),窗体将以对话框形式从上面的示例中移开。
发布于 2015-04-12 02:12:42
运行您在Windows 7上显示的确切代码,我无法再现您在Windows 7剪贴画中显示的相同的对话框位置。MessageDlgPos窗口以与Windows 8截图相同的方式向左偏移:

尽管如此,我注意到您正在将您的MessageDlg窗口相对于按钮的工作区定位

如果希望对话框相对于其实际底部边缘定位,则需要在按钮的Parent上调用Parent,而不是在按钮本身上调用:
p := Button3.Parent.ClientToScreen(Point(Button3.Left, Button3.Top+Button3.Height));

不过,最终的结果几乎是一样的:

现在,为什么重叠首先会发生呢?由于窗口的位置使得其非客户区域的左上角落在指定的坐标处:

您可以调整窗口坐标以解决以下问题:
p := Button3.Parent.ClientToScreen(Point(Button3.Left, Button3.Top + Button3.Height));
Inc(p.X, GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXBORDER));
Inc(p.Y, GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYBORDER));这让你更接近你想要的位置:

请注意,Aero“调整”了一些系统度量,因此您可能需要使用诸如DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS)和/或GetThemeSysSize()之类的方法来获得更精确的度量。
发布于 2015-04-12 17:31:25
在你的回答和评论以及一些额外的研究之后,我找到了这个解决方案。在Windows 8上进行测试,使用Aero测试7次,使用Aero和XP测试7次。我希望有更简单更稳定的东西但是..。
uses DwmApi;
type
TNonClientMetricsX = packed record
cbSize: UINT;
iBorderWidth: Integer; iScrollWidth: Integer;
iScrollHeight: Integer; iCaptionWidth: Integer;
iCaptionHeight: Integer; lfCaptionFont: TLogFontA;
iSmCaptionWidth: Integer; iSmCaptionHeight: Integer;
lfSmCaptionFont: TLogFontA; iMenuWidth: Integer;
iMenuHeight: Integer; lfMenuFont: TLogFontA;
lfStatusFont: TLogFontA; lfMessageFont: TLogFontA;
iPaddedBorderWidth: Integer; // not defined in Delphi 2007
end;
function GetExtendedFrameOffset(BorderStyle: TFormBorderStyle): integer;
var
IsEnabled: BOOL;
NCM: TNonClientMetricsX;
begin
Result := 0;
if (DwmIsCompositionEnabled(IsEnabled) = S_OK) and IsEnabled and
(BorderStyle in [bsdialog, bsSingle, bsToolWindow]) then
begin
NCM.cbSize := SizeOf(NCM);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, SizeOf(NCM), @NCM, 0);
Result := NCM.iBorderWidth + NCM.iPaddedBorderWidth;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var p: TPoint; offset: integer;
begin
p := Button3.ClientToScreen(Point(0, Button3.Height));
offset := GetExtendedFrameOffset(bsDialog);
MessageDlgPos('', mtInformation, [mbOK], 0, p.X + offset, p.Y + offset);
end;

更新: D2007包括DwmApi,所以不需要复杂的LoadLibrary
https://stackoverflow.com/questions/29576140
复制相似问题