Jak przesuwać myszą płynnie komponenty po formie

Dryobates

Chcesz przesuwać przyciski tak jak w Delphi? Przytrzymujesz przycisk i przenosisz. Trzeba wykorzystać nieudokumentowaną stałą $F012.

Oto przykład dla przycisku:

procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  ReleaseCapture;
  SendMessage(TWinControl(Sender).Handle, WM_SYSCOMMAND, $F012, 0);
end;

Gdzie jest haczyk? To działa jedynie dla pochodnych TWinControl (tylko one mogą otrzymać komunikat). Np. dla TLabel nie zadziała :( (ale TStaticText tak).

Dla odważnych proponuję poeksperymentować z innymi wartościami parametru. Czasem można otrzymać zadziwiające efekty. Przenoszenie okien nie wymienionych w procedurze (np pasek start), zmiany kolorów ekranu (np. wygląd w negatywie) oraz wyłączanie monitora. Ale pamiętajcie: robicie to na własną odpowiedzialność.

FAQ

7 komentarzy

A ja znalazłem takie jeszcze wartośći zdefiniowane w Delphi.
Znajdziecie tam jeszcze np. włączenie wygaszacza :)
Powodzenia

{ System Menu Command Values }
{$EXTERNALSYM SC_SIZE}
SC_SIZE = 61440;
{$EXTERNALSYM SC_MOVE}
SC_MOVE = 61456;
{$EXTERNALSYM SC_MINIMIZE}
SC_MINIMIZE = 61472;
{$EXTERNALSYM SC_MAXIMIZE}
SC_MAXIMIZE = 61488;
{$EXTERNALSYM SC_NEXTWINDOW}
SC_NEXTWINDOW = 61504;
{$EXTERNALSYM SC_PREVWINDOW}
SC_PREVWINDOW = 61520;
{$EXTERNALSYM SC_CLOSE}
SC_CLOSE = 61536;
{$EXTERNALSYM SC_VSCROLL}
SC_VSCROLL = 61552;
{$EXTERNALSYM SC_HSCROLL}
SC_HSCROLL = 61568;
{$EXTERNALSYM SC_MOUSEMENU}
SC_MOUSEMENU = 61584;
{$EXTERNALSYM SC_KEYMENU}
SC_KEYMENU = 61696;
{$EXTERNALSYM SC_ARRANGE}
SC_ARRANGE = 61712;
{$EXTERNALSYM SC_RESTORE}
SC_RESTORE = 61728;
{$EXTERNALSYM SC_TASKLIST}
SC_TASKLIST = 61744;
{$EXTERNALSYM SC_SCREENSAVE}
SC_SCREENSAVE = 61760;
{$EXTERNALSYM SC_HOTKEY}
SC_HOTKEY = 61776;
{$EXTERNALSYM SC_DEFAULT}
SC_DEFAULT = 61792;
{$EXTERNALSYM SC_MONITORPOWER}
SC_MONITORPOWER = 61808;
{$EXTERNALSYM SC_CONTEXTHELP}
SC_CONTEXTHELP = 61824;
{$EXTERNALSYM SC_SEPARATOR}
SC_SEPARATOR = 61455;

{ Obsolete names }
{$EXTERNALSYM SC_ICON}
SC_ICON = SC_MINIMIZE;
{$EXTERNALSYM SC_ZOOM}
SC_ZOOM = SC_MAXIMIZE;

my_nick ::
we wczesnych windowsach (i w starszych X'ach) pulpit to było osobne okno a pod nim było tylko czarne 'nic' :) a okna aplikacji nie mogły wyjść poza obszar pulpitu (p. Aplikacje MDI)

a ja jeszcze dodam swoje 3 grosze ;) zamiast $F012 (przesuwanie) można dać takie co służą do zmiany rozmiaru. czyli tak jak by chwycić za krawędź okna.

$F008 - prawy dolny róg
$F007 - lewy dolny
$F006 - dół
$F005 - prawa góra
$F004 - lewa góra
$F003 - góra
$F002 - prawa strona
$F001 - lewa strona

i jeszcze:
$F020 - minimalizacja
$F030 - maksymalizajca

Nie działa dla TLabel, ale to nie przeszkadza, aby za pomocą takiego labelka przenosić np. TPanel. Wystarczy powyższy kod wpisać w zdarzeniu OnMouseDown takiego Labela a w miejsce SENDER wpisać np. PANEL1 (zakładam, że tak nazwywa się ten komponent):

procedure TForm1.LabelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
SendMessage(TWinControl(Panel1).Handle, WM_SYSCOMMAND, $F012, 0);
end;

Czasami w ten sposób robię sobie na przykład podręczne okienka narzedziowe itp.

Kombinujcie....

Pozdrawiam

Ciekawe czy można w ten sposób zdjąć pulpit z pulpitu :) (klasa ShellListView32 chyba pochodzi od czysto windowsowego odpowiednika TWinControl, w końcu jej obiekty mają uchwyt i są traktowana jako okienka potomne...)

hehe. mi sie udalo zminimalizowac button:)
albo zrobic cos takiego z myszka, ze kuror sie mogl poruszac, ale na nic wiecej:)

Całkiem ciekawe..