2012-04-04 13 views
7

if (w Delphi) zrobićnie ManualFloat użyciu określonego Rect

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

panel jest nie unosił się w określonej lokalizacji Rect, ale zamiast w rodzaju okna domyślnej lokalizacji. Jak uzyskać panel (lub inny element sterujący) do unoszenia się w określonej lokalizacji. Wygląda jednak na to, że ma prawidłowy kształt. Czy jest jakaś inna właściwość, którą muszę ustawić, aby działała poprawnie?

Edytuj: Tylko po to, aby wszystko było jasne. Spodziewam się, że powyższy kod sprawi, że panel będzie miał kwadrat 100 x 100 położony w (500 x 500) względem lewego górnego rogu ekranu, którego nie ma. Kształt jest poprawny, ale lokalizacja nie jest. Jeśli kolejne elementy sterujące zostaną uniesione, zostaną sprowadzone kaskadowo w dół ekranu.

Edit2: To nie wydaje się być problemem w Delphi 7, ale jest w Delphi 2007 przez XE2 (i ewentualnie wcześniej)

+0

Przy zastosowaniu 'ManualFloat'' Rect (500, 500, 600, 600) jest '500 pikseli w dół i w lewo od górnej części ekranu , zawsze. (Zasadniczo jest to obszar typu "domyślna lokalizacja okna", ponieważ 'ManualFloat' używa współrzędnych ekranu, a nie współrzędnych okna). Czy spodziewasz się, że będzie on współrzędnych klienta zamiast (w oparciu o lokalizację twojego formularza)? –

+0

@KenWhite, dziękuję Kenowi, ale nie dzieje się tak.Panel jest kwadratem 100x100, jak można się było spodziewać, ale nie w miejscu (500 500) w stosunku do lewego górnego rogu ekranu – Alister

+0

@KenWhite, spróbuj jego kodu i przekonaj się sam ... –

Odpowiedz

5

Nie patrz dalej : Jest to błąd w VCL.

ManualFloat tworzy pływające okno i ustawia jego Top, Left wartości TControl.CreateFloatingDockSite(Bounds: TRect) a później ustawia ClientWidth.

Jest to błąd, ponieważ robi to wymusza tworzenie windowhandle (nie ma jeszcze Handle) w

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

A to wywołuje domyślną pozycję okna (kaskadowe bla bla ...) resetowanie Top i Left

poprawka byłoby ustawić ClientWidth i ClientHeight przed ustawieniem Top i Left właściwości w TControl.CreateFloatingDockSite(Bounds: TRect)

Aktualizacja: ustalony kod w 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; 
+0

Ale domyślna klasa strony pływającego dokowania 'Forms.TCustomDockForm' ma' BorderStyle = bsSizeToolWin' i nie jest ikoniczna. Dlatego zapytałem, czy OP ma własny "FloatingDockSiteClass" przypisany do panelu. – NGLN

+0

@NGLN. BorderStyle lub iconic są nieistotne. Ustawienie góry i lewej przed utworzeniem klamki okiennej jest pewną drogą do ich zgubienia ... Po prostu spróbuj jak OP z prostym przykładem: formularz, panel, przycisk z jego kodem, aby ustawić panel pływający i zobaczyć .. –

+0

Ustawienie lub uzyskanie 'ClientRect' nie odtwarza okna. I nie, nie widzę: Próbowałem wszystkich przykładów z mojej odpowiedzi, a także kodu OP i działają jak przy VCL intention _ (w D7). – NGLN

1

jak nazwa parametru TRect z the function - ScreenPos - niby mówi już, współrzędne są w jednostkach ekranu, a nie w jednostce macierzystej.

Jeśli chcesz panel pozostać w tym samym miejscu, gdzie to było, tłumaczyć współrzędne względne do ekranu:

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

Albo, to granicę panelu użytkownika:

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

Or , aby przetłumaczyć na konkretną współrzędną w stosunku do rodzica, użyj:

if Panel1.HasParent then 
    with Panel1.Parent.ClientOrigin do 
     Panel1.ManualFloat(Bounds(X + 500, Y + 500, 100, 100)); 
+0

Tak, wiem o wymaganym tłumaczeniu współrzędnych ekranu. Problem polega na tym, że ManualFloat ignoruje X i Y (aby użyć twoich zmiennych od góry). Działa doskonale z Forms, ale nie mogę go uruchomić z panelem. Szerokość i wysokość są jednak prawidłowe. Jeśli ustawię X i Y na 0, oczekiwałbym, że panel pojawi się w lewym górnym rogu ekranu, ale nie jest to miejsce, w którym utknąłem. – Alister

+0

Czy używasz własnej 'FloatingDockSiteClass'? W przeciwnym razie nie mógłbym wyjaśnić, dlaczego to nie działa. – NGLN

+0

@NGLN * "W przeciwnym razie nie potrafiłbym wyjaśnić, dlaczego to nie działa." *, Wypróbuj jego kod i zobacz ... –

Powiązane problemy