Логин: Пароль:    Регистрация Всеми возможностями сайта можно пользоваться
только после авторизации.
   Забыли пароль?

Поиск
L



Статистика
u
Пользователи онлайн: нет
Гостей онлайн: 4
Всего онлайн: 4
Зарегистрировано юзеров: 6362
Комментариев на сайте: 645
Новый юзер: Pseulairrerve



Последние комментарии
c
Aqel прокомментировал "Урок 71 - Работа с сжатыми файлами":
GZip псевдоархив, на мой вопрос тоже не отвечают, как распаковать отдельные файлы/папки...
Pingitrus прокомментировал "Урок 71 - Работа с сжатыми файлами":
Есть еще кто нибудь живой на этом сайте, кто сможет помочь? Так то все работает, zip и rar распаковывает, но у меня есть файл dat который сжат GZip, почему то его не удается распаковать или так не получится так как этот файл не является архивом или является?)) пишет ошибку что неверная функция



Мы в соцсетях
c
Delphi
Липкие окошки

В статье рассматривается приём создания обработчиков сообщений, которые позволяют форме при перетаскивании "прилипать" к краям экранной области.

Конечно же в WinAPI такой возможности не предусмотрено, поэтому мы воспользуемся сообщениями Windows. Как нам известно, Delphi обрабатывает сообщения через события, генерируя их в тот момент, когда Windows посылает сообщение приложению. Однако некоторые сообщения не доходят до нас. Например, при изменении размеров формы генерируется событие OnResize, соответствующее сообщению WM_SIZE, но при перетаскивании формы никакой реакции не происходит. Конечно же форма может получить это сообщение, но изначально никаких действий для данного сообщения не предусмотрено.

Итак, при перемещении окну посылается сообщение WM_MOVING. Обрабатывая данное сообщение, приложение может отслеживать размер и расположение перетаскиваемого квадрата и при необходимости изменять их.

Также существует сообщение WM_WINDOWPOSCHANGING, которое посылается окну в случае, если его размер, расположение или место в Z-порядке собираются измениться, как результат вызова функции SetWindowPos либо другой функции управления окном.

Чаще всего с сообщением передаются дополнительные параметры, которые сообщают нам необходимую информацию. Например, сообщение WM_MOVE, указывающее на то, что форма изменила своё местоположение, также передаёт в параметре LPARAM новые координаты X и Y.

Сообщение WM_WINDOWPOSCHANGING передаёт нам только один параметр - указатель на структуру WindowPos, которая содержит информацию о новом размере и местоположении окна. Вот как выглядит структура WindowPos:

TWindowPos = packed record 
  hwnd: HWND; {Identifies the window.} 
  hwndInsertAfter: HWND; {Window above this one} 
  x: Integer; {Left edge of the window} 
  y: Integer; {Right edge of the window} 
  cx: Integer; {Window width} 
  cy: Integer; {Window height} 
  flags: UINT; {Window-positioning options.} 
end;
Наша задача проста: нам необходимо, чтобы форма прилипла к краю экрана, если она находится на определённом расстоянии от него (допустим, 20 пикселей).

Пример

К новой форме добавьте Label, один Edit и четыре Checkbox. Измените имя Edit на edStickAt. Измените имена чекбоксов на chkLeft, chkTop, и т.д. Для установки количества пикселей используем edStickAt, который будет использоваться для определения необходимого расстояния до края экрана, достаточного для приклеивания формы.

Нас интересует только одно сообщение - WM_WINDOWPOSCHANGING. Обработчик для данного сообщения будет объявлен в секции private. Ниже приведён полный код этого процедуры "прилипания" вместе с комментариями. Обратите внимание, что Вы можете предотвратить "прилипание" формы к определённому краю путём снятия нужной галочки.

Для получения рабочей области декстопа (минус панель задач, панель Microsoft и т.д.), используем SystemParametersInfo, первый параметр которой SPI_GETWORKAREA.
... 

  private 
   procedure WMWINDOWPOSCHANGING 
            (var Msg: TWMWINDOWPOSCHANGING); 
             message WM_WINDOWPOSCHANGING; 

... 

procedure TfrMain.WMWINDOWPOSCHANGING 
          (var Msg: TWMWINDOWPOSCHANGING); 
const 
  Docked: Boolean = FALSE; 
var 
  rWorkArea: TRect; 
  StickAt : Word; 
begin 
  StickAt := StrToInt(edStickAt.Text); 
   
  SystemParametersInfo 
     (SPI_GETWORKAREA, 0, @rWorkArea, 0); 

  with Msg.WindowPos^ do begin 
    if chkLeft.Checked then 
     if x <= rWorkArea.Left + StickAt then begin 
      x := rWorkArea.Left; 
      Docked := TRUE; 
     end; 

    if chkRight.Checked then 
     if x + cx >= rWorkArea.Right - StickAt then begin 
      x := rWorkArea.Right - cx; 
      Docked := TRUE; 
     end; 

    if chkTop.Checked then 
     if y <= rWorkArea.Top + StickAt then begin 
      y := rWorkArea.Top; 
      Docked := TRUE; 
     end; 

    if chkBottom.Checked then 
     if y + cy >= rWorkArea.Bottom - StickAt then begin 
      y := rWorkArea.Bottom - cy; 
      Docked := TRUE; 
     end; 

    if docked then begin 
      with rWorkArea do begin 
      // не должна вылезать за пределы экрана 
      if x < Left then x := Left; 
      if x + cx > Right then x := Right - cx; 
      if y < Top then y := Top; 
      if y + cy > Bottom then y := Bottom - cy; 
      end; {ширина rWorkArea} 
    end; {} 
  end; {с Msg.WindowPos^} 

  inherited; 
end; 
end.
Теперь достаточно запустить проект и перетащить форму к любому краю экрана. Вот собственно и всё. А вот другой более короткий (и может быть, даже лучший) способ:
procedure TCustomGlueForm.WMWindowPosChanging1(var Msg: TWMWindowPosChanging); 
var 
WorkArea: TRect;   
StickAt : Word;   
begin 
StickAt := 10;   
SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea, 0);   
with WorkArea, Msg.WindowPos^ do     
begin 
// Сдвигаем границы для сравнения с левой и верхней сторонами   
Right:=Right-cx;   
Bottom:=Bottom-cy;   
if abs(Left - x) <= StickAt then x := Left;   
if abs(Right - x) <= StickAt then x := Right;   
if abs(Top - y) <= StickAt then y := Top;   
if abs(Bottom - y) <= StickAt then y := Bottom;   
end;   
inherited;   
end;

Вот и всё, Удачи!

Источник: www.thedelphi.ru
Автор: Савельев Александр
Опубликовано: 9 Февраля 2014
Просмотров:


Зарегистрируйтесь или авторизуйтесь, чтобы добавлять комментарии.