Как сделать, чтобы форма прилипала к краям экрана

Хотя многие сообщения Windows обрабатываются Delphi, но некоторые необходимо доработать. Например, мы узнаем, если форма поменяет размер (при помощи события OnResize и обработке сообщения WM_SIZE). Но как мы узнаем, что форма была перемещена? Delphi может получить сообщение, но изначально ничего с ним не делает.
Сообщение WM_MOVING посылается окну, когда пользователь его перемещает. Обрабатывая это сообщение, приложение может отслеживать размер и положение перемещаемого окна и при необходимости, изменить его размер или положение.
Сообщение WM_WINDOWPOSCHANGING посылается окну, когда меняется его размер, положение или Z-порядок в результате вызова функции SetWindowPos или иной функции управления окном.
Простого сообщения нам не достаточно, нам нужно знать и другие параметры. Например, сообщение WM_MOVE говорит нам, что изменилась позиция у формы, но оно также имеет параметр LPARAM, который может нам дать X и Y позицию.
У сообщения WM_WINDOWPOSCHANGING всего один параметр, который указывает на структуру WINDOWPOS, который содержит информацию о новом размере и положении окна. Структура WINDOWPOS определяется так:
type
TWindowPos = packed record
hwnd: HWND; { идентификатор окна }
hwndInsertAfter: HWND; { окно над ним }
x: Integer; { левый край окна }
y: Integer; { правый край окна }
cx: Integer; { ширина окна }
cy: Integer; { высота окна }
flags: UINT; { опции позиции окна }
end;
В нашем случае, сделаем, чтобы форма прилипала к краю экрана на определенном расстоянии, например, в 20 пикселах от края.
Сообщение WM_WINDOWPOSCHANGING
Поместите объявление процедуры WMWINDOWPOSCHANGING в части private формы.
Отменить прилипание к какому-либо краю экрана просто, нужно лишь удалить часть кода, который отвечает за свой участок.
SystemParametesInfo вызывается с SPI_GETWORKAREA в качестве первого параметра и получает размер рабочей области экрана (Рабочий стол). Мы будем использовать его для определения полезной площади за исключением Панели Задач, Панелей инструментов и т.д.
Код программы:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
private
{ Private declarations }
procedure WMWINDOWPOSCHANGING(
var Msg: TWMWINDOWPOSCHANGING); message WM_WINDOWPOSCHANGING;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Types;
{$R *.dfm}
procedure TForm1.WMWINDOWPOSCHANGING(
var Msg: TWMWINDOWPOSCHANGING);
var
Docked: boolean;
rWorkArea: TRect;
StickAt: Word; // расстояние от края экрана
begin
Docked:= false;
StickAt:= 20; // 20px от края экрана
SystemParametersInfo(SPI_GETWORKAREA, 0, @rWorkArea, 0);
with Msg.WindowPos^ do
begin
// Прилипание к левому краю
if x <= rWorkArea.Left + StickAt then
begin
x:= rWorkArea.Left;
Docked:= true;
end;
// Прилипание к правому краю
if x + cx >= rWorkArea.Right - StickAt then
begin
x:= rWorkArea.Right - cx;
Docked:= true;
end;
// Прилипание к верхнему краю
if y <= rWorkArea.Top + StickAt then
begin
y:= rWorkArea.Top;
Docked:= true;
end;
// Прилипание к низу экрана
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;
end;
end;
inherited;
end;
end.
Теперь запустите проект и перемещайте окно к границам экрана, чтобы посмотреть эффект прилипания.
Комментарии