7

如果(在德尔福)我做

Panel1.ManualFloat(Rect(500,500,600,600));

面板不是在指定的 Rect 位置浮动,而是在某种窗口默认位置。如何让面板(或其他控件)浮动在指定位置。然而,它似乎确实具有正确的形状。我需要设置其他一些属性以使其正常工作吗?

编辑:只是为了让事情清楚。我希望上面的代码可以使面板成为相对于屏幕左上角 (500x500) 的 100x100 正方形,但事实并非如此。形状正确,但位置不正确。如果后续控件浮动,它们会在屏幕下方层叠。

Edit2:这在 Delphi 7 中似乎不是问题,但在 Delphi 2007 到 XE2 中(可能更早)

4

2 回答 2

5

不要再看了:它是 VCL 中的一个错误。

ManualFloat创建一个浮动窗口并设置它的Top,Left值,TControl.CreateFloatingDockSite(Bounds: TRect)然后设置它的ClientWidth.

这是一个错误,因为这样做会强制创建 WindowHandle(它还没有 Handle)

function TCustomForm.GetClientRect: TRect;
begin
  if IsIconic(Handle) then // <===

这调用了窗口的默认定位(级联 yadda yadda ...)重置TopLeft

解决方法是在设置ClientWidthand属性ClientHeight之前设置TopandLeftTControl.CreateFloatingDockSite(Bounds: TRect)

更新:Controls.pas 中的固定代码

function TControl.CreateFloatingDockSite(Bounds: TRect): TWinControl;
begin
  Result := nil;
  if (FloatingDockSiteClass <> nil) and
    (FloatingDockSiteClass <> TWinControlClass(ClassType)) then
  begin
    Result := FloatingDockSiteClass.Create(Application);
    with Bounds do
    begin
      // Setting Client area can create the window handle and reset Top and Left
      Result.ClientWidth := Right - Left;
      Result.ClientHeight := Bottom - Top;
      // It is now safe to position the window where asked
      Result.Top := Top;
      Result.Left := Left;
    end;
  end;
end;
于 2012-04-04T19:12:17.280 回答
1

就像函数TRect的参数名称一样-已经说过了,坐标是屏幕单位而不是父单位的坐标。ScreenPos

如果您希望面板保持在原来的位置,请转换相对于屏幕的坐标:

  with Panel1.ClientToScreen(Point(0, 0)) do
    Panel1.ManualFloat(Bounds(X, Y, 100, 100));

或者,要包括面板的边框:

  if Panel1.HasParent then
    with Panel1.Parent.ClientToScreen(Panel1.BoundsRect.TopLeft) do
      Panel1.ManualFloat(Bounds(X, Y, 100, 100));

或者,要转换为相对于父级的特定坐标,请使用:

  if Panel1.HasParent then
    with Panel1.Parent.ClientOrigin do
      Panel1.ManualFloat(Bounds(X + 500, Y + 500, 100, 100));
于 2012-04-04T03:04:07.537 回答