The Unofficial Newsletter of Delphi Users - by Robert Vivrette

"Магнитное" окошко

by Wang Zhen- delphiques@email.com

Перевод Руденко Е.В.   janer@newmail.ru    апрель 2002 года

 

Пользователи программы  Winamp знают, что все его дочерние окошки (эквалайзер, броузер и т.д.) автоматически сцепляются при приближении друг к другу, как магниты. После нескольких часов раздумий и поисков, я нашел путь эмулировать такую замечательную способность в моем плагине для Winamp. Если вы захотите использовать такую возможность в своем приложении, пожалуйста просмотрите демо программу , показывающую основную идею такого решения. Демонстрационная форма "прилипает" к  основной форме Winamp при приближении к ней. Данный пример хорошо работает в  Delphi 3 и , я полагаю, будет работать в других версиях.

Во-первых, создадим новое приложение и изменим BorderStyle для Form1 в bsNone. Разместим на Форме кнопку (button). Дважды щелкнем не ней мышкой и напишем : "close;". Позже вы найдете ее полезной. Теперь напишем некоторый код. 

Здесь находятся глобальные переменные.

var
     Form1: TForm1;                   //само "магнитное" окошко...
     LastX, LastY: Integer;        //хранят координаты курсора
     WinampRect:TRect;           //хранит область окошка
     hwnd_Winamp:HWND;      //заголовок основного окна  Winamp

Теперь заполним события  OnMouseDown и  OnMouseMove для Form1 как показано ниже.

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer);
const

      ClassName='Winamp v1.x';   //  имя класса оснвного окошка  Winamp
      { Заменяет линию "ClassName='TAppBuilder'" при необходимости. }
begin

//сохраняем координаты
LastX := X;
LastY := Y;

//ищем Winamp
hwnd_Winamp := FindWindow(ClassName,nil);
if hwnd_Winamp>0 then
      GetWindowRect(hwnd_Winamp, WinampRect);

end;


procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
     nLeft,nTop:integer;
begin

//проверяем перемещение формы
     if HiWord(GetAsyncKeyState(VK_LBUTTON)) > 0 then
     begin

           //вычисляем новую позицию
           nleft := Left + X - LastX;
           nTop := Top + Y - LastY;

//регулируем позицию, если нашли  Winamp 
ifhwnd_Winamp>0 then
        Magnetize(nleft,ntop);
     SetBounds(nLeft,nTop,width,height);
   end;

end;

Сделаем паузу. Перед тем , как выдать собственно код  "магнетизма", я хочу вначале определить свойство  "намагниченности окошек". То есть, "процесс регулирования положения основного и дополнительного окошек на плоской поверхности при сближении их на некоторое заданное расстояние". 

Давайте продолжим ...

procedure TForm1.Magnetize(var nl,nt:integer);
     //две простых функции
     function Min(a,b:integer):integer;
     begin
     ifa>b then result:=b else result:=a;
     end;
     function Max(a,b:integer):integer;
     begin
     if a < b then result:=b else result:=a;
     end;

var
     H_Overlapped,V_Overlapped:boolean;
     tw,ww,wh:integer;
const
     MagneticForce:integer=50;

     { другими словами, когда два окошка ближе 50 пикселей, они автоматически выравниваются.  Помните, 50 используется только для демонстрационных целей. Этого вполне достаточно для имитации  Winamp. }
begin

ww := WinampRect.Right-WinampRect.Left;
tw := Max(WinampRect.Right,nl+Width)-Min(WinampRect.Left,nl);
H_Overlapped := tw<=(Width+ww);

wh := WinampRect.Bottom-WinampRect.Top;
tw := Max(WinampRect.Bottom,nt+Height)-Min(WinampRect.Top,nt);
V_Overlapped := tw<=(Height+wh);


//изменение позиции при сближении окошек
if H_Overlapped then
     begin
          if Abs(WinampRect.Bottom-nt)< MagneticForce then nt := WinampRect.Bottom
          else if Abs(nt+Height-WinampRect.Top)< MagneticForce then nt := WinampRect.Top-Height;
     end;

if V_Overlapped then
     begin
          if Abs(WinampRect.Right-nl)< MagneticForce then nl := WinampRect.Right
          else if Abs(nl+Width-WinampRect.Left)< MagneticForce then nl := WinampRect.Left-Width;
     end;

end;

Теперь нажмите  F9 и наслаждайтесь!

Если у вас есть лучшее решение или дополнения  (например, "многооконный магнетизм"),или вопросы, пожалуйста мой адрес:   delphiques@email.com.

Возврат в Tips&Tricks