границы окна (при щелчке кнопкой мыши на верхней, нижней, правой и левой границе можно изменять размер окна, правда, если стиль окна это допускает);
четыре угла окна (предназначены для изменения размера окна с помощью мыши);
системные кнопки закрытия, разворачивания, сворачивания, контекстной справки (обычно расположены в строке заголовка окна);
горизонтальная и вертикальная полосы прокрутки;
системное меню (раскрывается щелчком кнопкой мыши на значке окна);
меню полоса меню (обычно расположена вверху окна);
клиентская область по умолчанию все пространство окна, кроме строки заголовка, меню и полос прокрутки.
Каждый раз, когда над окном перемещается указатель мыши либо происходит нажатие кнопки мыши, система посылает соответствующему окну сообщение WM_ NCHITTEST для определения того, над которой из перечисленных выше областей окна находится указатель. Обработчик этого сообщения, вызываемый по умолчанию, информирует систему о расположении элементов окна в привычных для пользователя местах: заголовка сверху, правой границы справа и т. д.
Как вы, наверное, уже догадались, реализовав свой обработчик сообщения WM_ NCHITTEST, можно изменить назначение элементов окна. Этот прием как раз и реализован в листинге 1.21.
Листинг 1.21. Перемещение окна за клиентскую областьprocedure TfrmMoveClient.WMNCHitTest(var Message: TWMNCHitTest);
var
rc: TRect;
p: TPoint;
begin
//Если точка приходится на клиентскую область, то заставим систему
//считать эту область частью строки заголовка
rc:= GetClientRect();
p.X:= Message.XPos;
p.Y:= Message.YPos;
p:= ScreenToClient(p);
if PtInRect(rc, p) then
Message.Result:= HTCAPTION
else
//Обработка по умолчанию
Message.Result:= DefWindowProc(Handle, Message.Msg, 0, 65536 * Message.YPos + Message.XPos);
end;
Приведенный в листинге 1.21 обработчик переопределяет положение только строки заголовка, возвращая значение HTCAPTION. Этот обработчик может возвращать следующие значения (целочисленные константы, возвращаемые функцией DefWindowProc):
HTBORDER указатель мыши находится над границей окна (размер окна не изменяется);
HTBOTTOM, HTTOP, HTLEFT, HTRIGHT указатель мыши находится над нижней, верхней, левой или правой границей окна соответственно (размер окна можно изменить, «потянув» за границу);
HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOPLEFT, HTTOPRIGHT указатель мыши находится в левом нижнем, правом нижнем, левом верхнем или правом верхнем углу окна (размер окна можно изменять по диагонали);
HTSIZE, HTGROWBOX указатель мыши находится над областью, предназначенной для изменения размера окна по диагонали (обычно в правом нижнем углу окна);
HTCAPTION указатель мыши находится над строкой заголовка окна (за это место окно перемещается);
HTCLIENT указатель мыши находится над клиентской областью окна;
HTCLOSE указатель мыши находится над кнопкой закрытия окна;
HTHELP указатель мыши находится над кнопкой вызова контекстной справки;
HTREDUCE, HTMINBUTTON указатель мыши находится над кнопкой минимизации окна;
HTZ OOM, HTMAXBUTTON указатель мыши находится над кнопкой максимизации окна;
HTMENU указатель мыши находится над полосой меню окна;
HTSYSMENU указатель мыши находится над значком окна (используется для вызова системного меню);
HTHSCROLL, HTVSCROLL указатель находится над вертикальной или горизонтальной полосой прокрутки, соответственно;
HTTRANSPARENT если возвращается это значение, то сообщение пересылается окну, находящемуся под данным окном (окна должны принадлежать одному потоку);
HTNOWHERE указатель не находится над какой-либо из областей окна (например, на границе между окнами);
HTERROR то же, что и HTNOWHERE, только при возврате этого значения обработчик по умолчанию (DefWindowProc) воспроизводит системный сигнал, сигнализирующий об ошибке.
Перемещаемые элементы управления
В завершение материала о перемещении окон приведу один совсем несложный, но довольно интересный пример, позволяющий прямо «на лету» изменять внешний вид приложения. Достигается это благодаря возможности перемещения и изменения размера элементов управления так, будто это обычные перекрывающиеся окна.
Чтобы вас заинтересовать, сразу приведу результат работы примера. На рис. 1.13 показан внешний вид формы в начале работы примера.
Рис. 1.13. Первоначальный вид формы
После установки флажка Перемещение элементов управления получается результат, показанный на рис. 1.14.