Excel. Трюки и эффекты
Шрифт:
Как же достигнут подобный эффект? Очень даже просто. Ведь вы уже знаете, что элементы управления рисуются внутри своих собственных окон (дочерних по отношению к окну формы). Окна элементов отличает отсутствие в их стиле флагов (по – дробнее в гл. 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;
1.6. Масштабирование окон
Возможность масштабирования окон (форм) является интересным приемом, который может быть заложен в дизайн приложения.
При этом имеется
Использовать масштабирование при работе с 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. Форма в оригинальном масштабе
Внешний вид формы после уменьшения масштаба в 1,25 раза (новый масштаб составляет 80 % от первоначального) демонстрируется на рис. 1.17.
То, что форма не изменяет своего размера при масштабировании, можно легко исправить, установив, например, свойство AutoSize в True при помощи редактора свойств объектов (Object Inspector).
Если по каким-либо причинам использование свойства AutoSize вас не устраивает, то можно рассчитать новый размер формы самостоятельно. Только пересчитывать нужно размер не всего окна, а его клиентской области, ведь строка заголовка при масштабировании остается без изменений. Расчет размера окна можно выполнить так:
1. Получить прямоугольник клиентской области окна (GetClientRect).
2. Посчитать новый размер клиентской области.
3. Рассчитать разницу между новой и первоначальной шириной, новой и первоначальной высотой клиентской области; сложить полученные значения с первоначальными размерами самой формы.
Пример расчета приводится ниже (для увеличения размера клиентской области в 1,2 раза):GetClientRect(Handle, rc);
newWidth := (rc.Right – rc.Left) * 120 div 100;
newHeight := (rc.Bottom – rc.Top) * 120 div 100;
Width := Width + newWidth – (rc.Right – rc.Left);
Height := Height + newHeight – (rc.Bottom – rc.Top);
Примечание
Чтобы после уменьшения или увеличения масштаба формы можно было вернуться в точности к первоначальному масштабу (при помощи соответствующей обратной операции), нужно для уменьшения или увеличения использовать коэффициенты, произведение которых равно 1. Например, при уменьшении масштаба на 20 % (в 0,8 раза) его нужно увеличивать при обратной операции на 25 % (в 1/0,8 = 1,25 раза).