Как же достигнут подобный эффект? Очень просто. Вы уже знаете, что элементы управления рисуются внутри своих собственных окон (дочерних по отношению к окну формы). Окна элементов управления отличает отсутствие в их стиле флагов (подробнее в гл. 2), позволяющих отображать рамку и изменять размер окна. Это легко изменить, самостоятельно задав нужные флаги в стиле окна с помощью API-функции SetWindowLong. Для удобства можно написать отдельную процедуру, которая будет дополнять стиль окна флагами, необходимыми для перемещения и изменения размера (как, собственно, и сделано в примере) (листинг 1.22).
Листинг 1.22. Разрешение перемещения и изменения размера
procedure MakeMovable(Handle: HWND);
var
style: LongInt;
flags: UINT;
begin
//Разрешаем перемещение элемента управления
style:= GetWindowLong(Handle, GWL_STYLE);
style:= style or WS_OVERLAPPED or WS_THICKFRAME or WS_CAPTION;
SetWindowLong(Handle, GWL_STYLE, style);
style:= GetWindowLong(Handle, GWL_EXSTYLE);
style:= style or WS_EX_TOOLWINDOW;
SetWindowLong(Handle, GWL_EXSTYLE, style);
//Перерисуем в новом состоянии
flags:= SWP_NOMOVE or SWP_NOSIZE or SWP_DRAWFRAME or SWP_NOZORDER;
SetWindowPos(Handle, 0, 0, 0, 0, 0, flags);
end;
Как можно увидеть, дополнительные флаги задаются в два этапа. Сначала считывается старое значение стиля окна. Потом с помощью двоичной операции ИЛИ стиль (задается целочисленным значением) дополняется новыми флагами. Это делается для того, чтобы не пропали ранее установленные значения стиля окна.
Вообще, процедура MakeMovable изменяет два стиля окна: обычный и расширенный. Расширенный стиль окна изменяется лишь для того, чтобы строка заголовка получившегося окна занимала меньше места (получаем так называемое окно панели инструментов). Полный перечень как обычных, так и расширенных стилей можно просмотреть в приложении 2.
Логично также реализовать процедуру, обратную MakeMovable, запрещающую перемещение окон элементов управления (листинг 1.23).
Листинг 1.23. Запрещение перемещения и изменения размера
procedure MakeUnmovable(Handle: HWND);
var
style: LongInt;
flags: UINT;
begin
//Запрещаем перемещение элемента управления
style:= GetWindowLong(Handle, GWL_STYLE);
style:= style and not WS_OVERLAPPED and not WS_THICKFRAME
and not WS_CAPTION;
SetWindowLong(Handle, GWL_STYLE, style);
style:= GetWindowLong(Handle, GWL_EXSTYLE);
style:= style and not WS_EX_TOOLWINDOW;
SetWindowLong(Handle, GWL_EXSTYLE, style);
//Перерисуем в новом состоянии
flags:= SWP_NOMOVE or SWP_NOSIZE or SWP_DRAWFRAME or SWP_NOZORDER;
SetWindowPos(Handle, 0, 0, 0, 0, 0, flags);
end;
Осталось только реализовать вызовы процедур MakeMovable и MakeUnmovable в нужном месте программы. В рассматриваемом примере вызовы заключены внутри обработчика изменения состояния флажка на форме (листинг 1.24).
Листинг 1.24. Управление перемещаемостью элементов управления
procedure TfrmMovingControls.chkSetMovableClick(Sender: TObject);
begin
if chkSetMovable.Checked then
begin
//Разрешаем перемещение элементов управления
MakeMovable(Memo1.Handle);
MakeMovable(ListBox1.Handle);
MakeMovable(Button1.Handle);
end
else
begin
//Запрещаем перемещение элементов управления
MakeUnmovable(Memo1.Handle);
MakeUnmovable(ListBox1.Handle);
MakeUnmovable(Button1.Handle);
end;
end;
Возможность масштабирования окон (форм) является интересным приемом, который может быть заложен в дизайн приложения. При этом имеется в виду масштабирование в буквальном смысле этого слова: как пропорциональное изменение размера элементов управления формы, так и изменение размера шрифта.
Использовать масштабирование при работе с Delphi крайне просто, ведь в класс TWinControl, от которого наследуются классы форм, встроены методы масштабирования. Вот некоторые из них:
• ScaleControls – пропорциональное изменение размера элементов управления на форме;
• ChangeScale – пропорциональное изменение размера элементов управления с изменением шрифта, который используется для отображения текста в них.
Оба приведенных метода принимают два целочисленных параметра: числитель и знаменатель нового масштаба формы. Пример задания параметров для методов масштабирования приведен в листинге 1.25.
Листинг 1.25. Масштабирование формы с изменением шрифта
procedure TfrmScaleBy.cmbSmallerClick(Sender: TObject);
begin
ChangeScale(80, 100); //Уменьшение на 20 % (новый масштаб – 80 %)
end;
procedure TfrmScaleBy.cmbBiggerClick(Sender: TObject);
begin
ChangeScale(120, 100); //Увеличение на 20 % (новый масштаб – 120 %)
end;
Чтобы размер шрифта правильно устанавливался, для элементов управления нужно использовать шрифты семейства TrueType (в данном примере это шрифт Times New Roman).
На рис. 1.16 показан внешний вид формы до изменения масштаба.
Рис. 1.16. Форма в оригинальном масштабе
Читать дальше