// на постоянную величину относительно правого края окна
for I := 0 to High(Arrow) do
begin
Arrow[I].X := ClientWidth - ArrowOffset - 1 - ArrowTemplate[I].X;
Arrow[I].Y := ArrowTemplate[I].Y + ArrowOffset;
end;
if ArrowTopRight <> 0 then DeleteObject(ArrowTopRight);
ArrowTopRight := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);
// Вычисление региона левой нижней стрелки
// Координаты по Y отражаются и смещаются
// на постоянную величину относительно нижнего края окна
for I := 0 to High(Arrow) do
begin
Arrow[I].X := ArrowTemplate[I].X + ArrowOffset;
Arrow[I].Y := ClientHeight - ArrowOffset - 1 - ArrowTemplate[I].Y;
end;
if ArrowBottomLeft <> 0 then DeleteObject(ArrowBottomLeft);
ArrowBottomLeft := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);
// Вычисление региона правой нижней стрелки
// Координаты по обеим осям отражаются и смещаются
// на постоянную величину относительно правого нижнего угла окна
for I := 0 to High(Arrow) do
begin
Arrow[I].X := ClientWidth - ArrowOffset - 1 - ArrowTemplate[I].X;
Arrow[I].Y := ClientHeight - ArrowOffset - 1 - ArrowTemplate[I].Y;
end;
if ArrowBottomRight <> 0 then DeleteObject(ArrowBottomRight);
ArrowBottomRight := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);
end;
Следующий шаг — рисование стрелки на форме. Делается это очень просто (листинг 1.56).
procedure TFormHole.FormPaint(Sender: TObject);
begin
// Закрашиваем регионы стрелок
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := clRed;
FillRgn(Canvas.Handle, ArrowTopLeft, Canvas.Brush.Handle);
FillRgn(Canvas.Handle, ArrowTopRight, Canvas.Brush.Handle);
FillRgn(Canvas.Handle, ArrowBottomLeft, Canvas.Brush.Handle);
FillRgn(Canvas.Handle, ArrowBottomRight, Canvas.Brush.Handle);
Остался последний шаг — объяснить системе, что пользователь может, ухватив за стрелки, изменять размеры формы. Очевидно, что делается это через обработчик WM_NCHITTEST
. Вопрос только в том, как узнать, когда координаты мыши попадают внутрь нарисованной стрелки, поскольку стрелка является объектом сложной формы, вычислить это не очень просто. Данная задача также решается с помощью регионов: попадание координат курсора в регион каждой из стрелок отслеживается с помощью стандартной функции PtInRegion
(листинг 1.57).
WM_NCHITTEST
формыprocedure TFormHole.WMNCHitTest(var Msg: TWMNCHitTest);
var
Pt: TPoint;
begin
// Чтобы правильно обрабатывать стандартную неклиентскую область,
// вызываем унаследованный обработчик
inherited;
// Не забываем, что параметры WM_NCHITTEST дают экранные,
// а не клиентские координаты
Pt := ScreenToClient(Point(Msg.XPos, Msg.YPos));
// Проверяем координаты на попадание в регионы стрелок
if PtInRegion(ArrowTopLeft, Pt.X, Pt.Y) then
Msg.Result := HTTOPLEFT
else if PtInRegion(ArrowTopRight, Pt.X, Pt.Y) then
Msg.Result := HTTOPRIGHT
else