VR
Virtual Reality On-line   Журнал
Новости   |     Журнал    |    Хаkер    |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]

[ Download  ]
[  Конкурс  ]
[ Анекдоты  ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
Язык программирования Delphi
Плавающие окна
:
Logo

Мы продолжаем учиться программировать. И снова я покажу, что достаточно сложные на первый взгляд вопросы решаются очень легко. Сегодня ты научишься заставлять окна плавать. Плавать они будут не в бассейне, а по экрану, наше окно можно будет перетащить за любую его часть. А самое главное, мы рассмотрим аж два способа решения этой задачи.

Сначала рассмотрим тот, что попроще. Для этого создайте новый проект. В разделе private новой формы напишите:

procedure WMNCHitTest(var M: TWMNCHitTest); message wm_NCHitTest;

Теперь нажми клавиши Ctrl+Alt+C , после этого Delphi создаст пустую процедуру:

procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
begin

end;

Внутри неё напиши следующее:

inherited;
 if  M.Result = htClient then
   M.Result := htCaption;

Теперь запусти программу и попробуй перетащить окно за форму. Получилось? Это хорошо, теперь рассмотрим, что мы для этого сделали. Самое первое, это мы объявили процедуру - обработчик для события HitTest. Это событие происходит, когда тестируется щёлчок мышки по окну. Это событие мы объявляли не так как предыдущие (через Object Inspector), а вручную как обычную процедуру. О том что это обработчик события говорит надпись в объявлении после точки с запятой: message wm_NCHitTest; .

Внутри обработчика события мы вызываем предка с помощью inherited; , чтобы сначала он обработал это событие. А после этого мы проверяем следующее: если щелчок был по форме, то мы заставляем Microsoft думать, что щелчок был по заголовку окна. Всё очень просто. Взгляни ещё раз на этот код, и ты это поймёшь.

Теперь мы сделаем тоже самое вторым способом. Он немного тяжелее, но зато он позволяет перетаскивать окна за любой компонент. Приготовь новый проект, мы начинаем.

В объявлении private напиши следующее:

private
 { Private declarations }
 OldX,
 OldY,
 OldLeft,
 OldTop   : Integer;
 ScreenDC : HDC;
 MoveRect : TRect;
 Dragging   : Boolean;
Logo
Рис 1. Форма

Создай на форме из палитры компонентов TPanel (рис 1.) и создай для неё обработчик события OnMouseDown . В этой процедуре напиши следующее:

procedure TForm1.Panel1MouseDown(Sender: TObject; 
Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
Begin
 if Button = mbLeft then 
 begin
   ScreenDC := GetDC(0); 
   OldX := X; // сохраняем Х координату щелчка
   OldY := Y; // сохраняем Y координату щелчка
   OldLeft := X; // сохраняем Х координату щелчка
   OldTop := Y; // сохраняем Y координату щелчка
   MoveRect := BoundsRect; // // сохраняем размеры и положение окна
   DrawFocusRect(ScreenDC, MoveRect); // Рисуем рамочку окна.
   Dragging := True; // Начинаем перемещение.
  end;
end;

Процедура нам передаёт параметр Button , в котором хранится значение нажатой кнопки мыши (возможны значения mbLeft, mbRight и mbMiddle). В первой строчке мы проверяем, нажата ли левая кнопка. Если это была левая, то мы начинаем приготовления к перетаскиванию окна. Практически всё ты сможешь понять по комментариям, но некоторые вещи я объясню.

GetDC создаёт контекст устройства к указанному в скобках окну, и записывает это, в объявленную нами переменную ScreenDC. В качестве параметра мы передаём ноль, а не ссылку на окно. В этом случае мы получим контекст рисования на всём экране. Контекст устройства - это нечто похожее на Canvas, только второй имеет больше возможностей и более удобен в работе.

DrawFocusRect эта функция рисует рамочку на контексте, переданном в качестве первого параметра, и размерами, переданными в качестве второго параметра. В качестве размера мы передаём текущее положение экрана.

Теперь нужно создать обработчик события OnMouseMove (когда переместили мышку). Внутри обработчика напиши следующее:

  if Dragging then begin //Если происходит перемещение то ….
    DrawFocusRect(ScreenDC,MoveRect);
    OldX := X; // Сохраняем новое положение экрана
    OldY := Y; // Сохраняем новое положение экрана
    MoveRect := Rect(Left+OldX-OldLeft,Top+OldY-OldTop,
          Left+Width+OldX-OldLeft,Top+Height+OldY-OldTop);
    DrawFocusRect(ScreenDC,MoveRect);
  end;

Первый вызов процедуры DrawFocusRect рисует рамку поверх предыдущей. Это нужно для того, чтобы стереть её. Если дважды вывести рамку в одном и том же месте, то результат будет нулевым. Затем сохраняются новое положение окна, переданные нам обработчиком. Далее вычисляются новые размеры рамки, и записываются в MoveRect . И снова вызывается DrawFocusRect , которая рисует рамку в новом положении окна.

Теперь создаём обработчик события OnMouseUp (когда отпустили мышку) и записываем следующее:

  if Button = mbLeft then begin // Если это была левая кнопка
    DrawFocusRect(ScreenDC,MoveRect); //Стираем рамку
    Left := Left+X-OldLeft;//Устанавливаем новое левое положение окна
    Top := Top+Y-OldTop; //Устанавливаем новое верхнее положение окна
    ReleaseDC(0,ScreenDC);// Уничтожаем контекст устройства
    Dragging := False; // Перемещение закончено.
  end;

Всё, что здесь происходит ты сможешь разобраться по комментариям. Скажу только, что когда мы создавали контекст устройства (GetDC), мы выделили память. Любую память нужно освобождать после использования, для этого мы воспользовались процедурой ReleaseDC.

 Исходники примера забирай здесь


Design by FMk group ©
Copyright©: Horrific aka Флёнов Михаил ©