ManualFloat不使用指定的Rect

时间:2012-04-04 01:34:48

标签: delphi docking

如果(在Delphi中)我做

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

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

编辑:只是为了清楚说明。我希望上面的代码使得面板相对于屏幕的左上角位于(500x500)的100x100正方形,而不是。形状是正确的,但位置不正确。如果后续控件浮动,则它们会在屏幕上级联。

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

2 个答案:

答案 0 :(得分:5)

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

ManualFloat创建一个浮动窗口,并在Top中设置其LeftTControl.CreateFloatingDockSite(Bounds: TRect)值,然后设置其ClientWidth

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

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

并调用Window的默认定位(级联yadda yadda ...)重置TopLeft

修复方法是在ClientWidth

中设置ClientHeightTop属性之前设置LeftTControl.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;

答案 1 :(得分:1)

TRect参数的名称the function - 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));