Электронная библиотека » Александр Чиртик » » онлайн чтение - страница 2


  • Текст добавлен: 10 ноября 2013, 00:08


Автор книги: Александр Чиртик


Жанр: Программирование, Компьютеры


сообщить о неприемлемом содержимом

Текущая страница: 2 (всего у книги 24 страниц)

Шрифт:
- 100% +
Закругленные окна и многоугольники

Сначала самые простые примеры: создание регионов без операций над ними. Формы всех трех приведенных здесь примеров содержат по три кнопки различной ширины и высоты, которым также задаются области отсечения.

Примечание

В приведенных далее примерах регионы для области отсечения окна создаются при обработке события FormCreate. Однако это сделано только для удобства отладки и тестирования примеров и ни в коем случае не должно наталкивать вас на мысль, что этот способ является единственно правильным. На самом деле, если в приложении много окон, использующих области отсечения сложной формы, то запуск приложения (время от момента запуска до показа первой формы) может длиться, по крайней мере, несколько секунд. Так происходит потому, что все формы создаются перед показом первой (главной) формы (см. DPR-файл проекта). Исправить ситуацию можно, создавая формы вручную в нужный момент времени либо создавая регионы для областей отсечения, например, перед первым отображением каждой конкретной формы.

В приведенном ниже обработчике события FormCreate создается окно в форме эллипса с тремя кнопками такой же формы (листинг 1.10).

Листинг 1.10. Окно и кнопки в форме эллипсов

procedure TfrmElliptic.FormCreate(Sender: TObject);

var

formRgn, but1Rgn, but2Rgn, but3Rgn: HRGN;

begin

//Создаем регионы кнопок

but1Rgn:= CreateEllipticRgn(0, 0, Button1.Width–1, Button1.Height–1);

SetWindowRgn(Button1.Handle, but1Rgn, False);

but2Rgn:= CreateEllipticRgn(0, 0, Button2.Width–1, Button2.Height–1);

SetWindowRgn(Button2.Handle, but2Rgn, False);

but3Rgn:= CreateEllipticRgn(0, 0, Button3.Width–1, Button3.Height–1);

SetWindowRgn(Button3.Handle, but3Rgn, False);

//Регион для окна

formRgn:= CreateEllipticRgn(0, 0, Width–1, Height–1);

SetWindowRgn(Handle, formRgn, True);

end;


Ширина и высота эллипсов в приведенном примере равна, соответственно, ширине и высоте тех окон, для которых создаются регионы. При необходимости это можно изменить, например, если требуется, чтобы все кнопки были одной величины независимо от размера, установленного во время проектирования формы.

Результат выполнения кода листинга 1.10 можно увидеть на рис. 1.5.

Рис. 1.5. Окно и кнопки в форме эллипсов


Далее рассмотрим не менее интересный (возможно, даже более полезный на практике) пример – округление углов формы и кнопок на ней, то есть применение области отсечения в форме прямоугольника с округленными углами. Ниже приведен код реализации соответствующего обработчика события FormCreate (листинг 1.11).

Листинг 1.11. Окно и кнопки с округленными краями

procedure TfrmRoundRect.FormCreate(Sender: TObject);

var

formRgn, but1Rgn, but2Rgn, but3Rgn: HRGN;

begin

//Создаем регионы для кнопок

but1Rgn:= CreateRoundRectRgn(0, 0, Button1.Width–1, Button1.Height–1,

Button1.Width div 5, Button1.Height div 5);

SetWindowRgn(Button1.Handle, but1Rgn, False);

but2Rgn:= CreateRoundRectRgn(0, 0, Button2.Width–1, Button2.Height–1,

Button2.Width div 5, Button2.Height div 5);

SetWindowRgn(Button2.Handle, but2Rgn, False);

but3Rgn:= CreateRoundRectRgn(0, 0, Button3.Width–1, Button3.Height–1,

Button3.Width div 5, Button3.Height div 5);

SetWindowRgn(Button3.Handle, but3Rgn, False);

//Регион для окна

formRgn:= CreateRoundRectRgn(0, 0, Width–1, Height–1,

Width div 5, Height div 5);

SetWindowRgn(Handle, formRgn, False);

end;


В листинге 1.11 размеры округляющих эллипсов вычисляются в расчете из размеров конкретного окна (20 % от его ширины и 20 % от высоты). Это смотрится не всегда красиво. В качестве альтернативы для ширины и высоты скругляющих эллипсов можно использовать фиксированные небольшие значения.

Результат выполнения кода листинга 1.11 можно увидеть на рис. 1.6.

Рис. 1.6. Окно и кнопки с округленными краями


Теперь самый интересный из предусмотренных примеров – создание окна и кнопок в форме многоугольников, а именно: окна в форме звезды, кнопок в форме треугольника, пяти– и шестиугольника (рис. 1.7).

Рис. 1.7. Окно и кнопки в форме многоугольников


Код создания регионов для областей отсечения данного примера приведен в листинге 1.12.

Листинг 1.12. Окно и кнопки в форме многоугольников

procedure TfrmPoly.FormCreate(Sender: TObject);

var

points: array [0..5] of TPoint;

formRgn, but1Rgn, but2Rgn, but3Rgn: HRGN;

begin

//Создаем регионы для окна и кнопок

//..шестиугольная кнопка

Make6Angle(Button1.Width, Button1.Height, points);

but1Rgn:= CreatePolygonRgn(points, 6, WINDING);

SetWindowRgn(Button1.Handle, but1Rgn, False);

//..треугольная кнопка

Make3Angle(Button2.Width, Button2.Height, points);

but2Rgn:= CreatePolygonRgn(points, 3, WINDING);

SetWindowRgn(Button2.Handle, but2Rgn, False);

//..пятиугольная кнопка

Make5Angle(Button3.Width, Button3.Height, points);

but3Rgn:= CreatePolygonRgn(points, 5, WINDING);

SetWindowRgn(Button3.Handle, but3Rgn, False);

//..форма в виде звезды

MakeStar(Width, Height, points);

formRgn:= CreatePolygonRgn(points, 5, WINDING);

SetWindowRgn(Handle, formRgn, False);

end;


Особенностью создания регионов в приведенном листинге является использование дополнительных процедур для заполнения массива points координатами точек-вершин многоугольников определенного вида. Все эти процедуры принимают, помимо ссылки на сам массив points, ширину и высоту прямоугольника, в который должен быть вписан многоугольник. Описание процедуры создания треугольника приведено в листинге 1.13.

Листинг 1.13. Создание треугольника

procedure Make3Angle(width, height: Integer; var points: array of TPoint);

begin

points[0].X:= 0;

points[0].Y:= height – 1;

points[1].X:= width div 2;

points[1].Y:= 0;

points[2].X:= width – 1;

points[2].Y:= height – 1;

end;


В листинге 1.14 приведено описание процедуры создания шестиугольника.

Листинг 1.14. Создание шестиугольника

procedure Make6Angle(width, height: Integer; var points: array of TPoint);

begin

points[0].X:= 0;

points[0].Y:= height div 2;

points[1].X:= width div 3;

points[1].Y:= 0;

points[2].X:= 2 * (width div 3);

points[2].Y:= 0;

points[3].X:= width – 1;

points[3].Y:= height div 2;

points[4].X:= 2 * (width div 3);

points[4].Y:= height – 1;

points[5].X:= width div 3;

points[5].Y:= height – 1;

end;


Листинг 1.15 содержит описание процедуры создания пятиугольника (неправильного).

Листинг 1.15. Создание пятиугольника

procedure Make5Angle(width, height: Integer; var points: array of TPoint);

var a: Integer; //Сторона пятиугольника

begin

a:= width div 2;

points[0].X:= a;

points[0].Y:= 0;

points[1].X:= width – 1;

points[1].Y:= a div 2;

points[2].X:= 3 * (a div 2);

points[2].Y:= height – 1;

points[3].X:= a div 2;

points[3].Y:= height – 1;

points[4].X:= 0;

points[4].Y:= a div 2;

end;


Пятиугольная звезда, используемая как область отсечения формы, создается с помощью описанной в листинге 1.15 процедуры Make5Angle. После ее создания изменяется порядок следования вершин пятиугольника, чтобы их обход при построении региона выполнялся в той же последовательности, как рисуется звезда карандашом на бумаге (например, 1-3-5-2-4) (листинг 1.16).

Листинг 1.16. Создание пятиугольной звезды

procedure MakeStar(width, height: Integer; var points: array of TPoint);

begin

Make5Angle(width, height, points);

//При построении звезды точки пятиугольника обходятся не по порядку,

//а через одну

Swap(points[1], points[2]);

Swap(points[2], points[4]);

Swap(points[3], points[4]);

end;


Процедура MakeStart (листинг 1.16) использует дополнительную процедуру Swap, меняющую местами значения двух передаваемых в нее аргументов. Процедура Swap реализуется чрезвычайно просто и потому в тексте книги не приводится.

Комбинированные регионы

Вы уже научились создавать и использовать простые регионы. Однако многим может показаться недостаточным тех форм окон, которые можно получить с использованием в качестве области отсечения лишь одного несложного региона. Пришло время заняться созданием окон более сложной формы, применяя рассмотренные ранее операции над регионами.

«Дырявая» форма

Этот простейший пример сомнительной полезности предназначен для первого знакомства с операциями над регионами. Здесь применяется только одна из возможных операций – операция XOR для формирования «дырок» в форме (рис. 1.8).

Рис. 1.8. «Дырки» в форме


На рис. 1.8 явно видно, как в «дырках» формы просвечивает одно из окон среды разработки Delphi. При этом, когда указатель находится над «дыркой», сообщения от мыши получают те окна, части которых видны в «дырке».

Программный код, приводящий к созданию формы столь необычного вида, приведен в листинге 1.17.

Листинг 1.17. Создание «дырок» в форме

procedure TfrmHole.FormCreate(Sender: TObject);

var

rgn1, rgn2: HRGN; //"Регионы-дырки" в форме

formRgn: HRGN;

begin

//Создание региона для формы

formRgn:= CreateRectRgn(0, 0, Width – 1, Height – 1);

//Создание регионов для "дырок"

rgn1:= CreateEllipticRgn(10, 10, 100, 50);

rgn2:= CreateRoundRectRgn(10, 60, 200, 90, 10, 10);

//Создание "дырок" в регионе формы

CombineRgn(formRgn, formRgn, rgn1, RGN_XOR);

CombineRgn(formRgn, formRgn, rgn2, RGN_XOR);

SetWindowRgn(Handle, formRgn, True);

//Регионы для "дырок" больше не нужны

DeleteObject(rgn1);

DeleteObject(rgn2);

end;


Сложная комбинация регионов

Теперь пришла очередь рассмотреть более сложный, но и гораздо более интересный пример. Последовательное применение нескольких операций над регионами приводит к созданию формы, показанной на рис. 1.9 (белое пространство – «вырезанные» части формы).

Рис. 1.9. Сложная комбинация регионов


Описание процедуры, выполняющей операции над регионами, приведено в листинге 1.18.

Листинг 1.18. Сложная комбинация регионов

procedure TfrmManyRgn.FormCreate(Sender: TObject);

var

r1, r2, r3, r4, r5, r6, r7: HRGN;

formRgn: HRGN;

butRgn: HRGN;

begin

//Создание регионов

r1:= CreateRoundRectRgn(100, 0, 700, 400, 40, 40);

r2:= CreateRectRgn(280, 0, 300, 399);

r3:= CreateRectRgn(500, 0, 520, 399);

r4:= CreateEllipticRgn(140, 40, 240, 140);

r5:= CreateEllipticRgn(0, 300, 200, 500);

r6:= CreateEllipticRgn(500, 40, 600, 140);

r7:= CreateEllipticRgn(540, 40, 640, 140);

//Комбинирование

//..разрезы в основном регионе

CombineRgn(r1, r1, r2, RGN_XOR);

CombineRgn(r1, r1, r3, RGN_XOR);

//..круглая "дырка" в левой стороне

CombineRgn(r1, r1, r4, RGN_XOR);

//..присоединение круга в левой нижней части

CombineRgn(r1, r1, r5, RGN_OR);

//..создание "дырки" в форме полумесяца

CombineRgn(r7, r7, r6, RGN_DIFF);

CombineRgn(r1, r1, r7, RGN_XOR);

formRgn:= CreateRectRgn(0, 0, 0, 0);

CombineRgn(formRgn, r1, 0, RGN_COPY);

DeleteObject(r1);

DeleteObject(r2);

DeleteObject(r3);

DeleteObject(r4);

DeleteObject(r5);

DeleteObject(r6);

DeleteObject(r7);

//Создание круглой кнопки закрытия

butRgn:= CreateEllipticRgn(50, 50, 150, 150);

SetWindowRgn(Button1.Handle, butRgn, False);

SetWindowRgn(Handle, formRgn, True);

end;


В этом листинге подписано, какие операции предназначены для создания каких элементов итогового региона. В операциях участвуют семь регионов. Расположение используемых в операциях регионов показано на рис. 1.10.

Рис. 1.10. Элементарные регионы, используемые для получения формы, представленной на рис. 1.9


Использование шаблона

Предыдущий пример наглядно демонстрирует мощь функции CombineRgn при построении регионов сложной формы. Однако существует огромное количество предметов, контуры которых крайне сложно повторить, комбинируя простые регионы. Построение многоугольных регионов с большим количеством точек может в этом случае выручить, но ведь это крайне нудно и утомительно.

Если есть изображение предмета, контуры которого должны совпадать с контурами региона, то гораздо проще при построении региона обрабатывать само изображение, выбирая все точки, для которых выполняется определенное условие. Используемое изображение и будет тем шаблоном, по которому «вырезается» регион нужной формы.

Рассмотрим простейший пример: есть изображение, каждая точка которого должна попасть в результирующий регион, если ее цвет не совпадает с заданным цветом фона. При этом изображение анализируется по так называемым «скан-линиям», то есть построчно. Из подряд идущих точек не фонового цвета формируются прямоугольные регионы, которые объединяются с результирующим регионом. Пример возможного используемого шаблона приведен на рис. 1.11.

Рис. 1.11. Пример растрового изображения-шаблона


Код функции построения региона указанным способом приведен в листинге 1.19.

Листинг 1.19. Построение региона по шаблону

function RegionFromPicture(pict:TPicture; backcolor: TColor): HRGN;

var

rgn, resRgn: HRGN;

x, y, xFirst: Integer;

begin

resRgn:= CreateRectRgn(0, 0, 0, 0); //Результирующий регион

//Анализируем каждую скан-линию рисунка (по горизонтали)

for y:= 0 to pict.Height – 1 do

begin

x:= 0;

while x < pict.Width do

begin

if (pict.Bitmap.Canvas.Pixels[x, y] <> backcolor) then

begin

xFirst:= x;

Inc(x);

//Определим часть линии, окрашенной не цветом фона

while (x < pict.Width) and

(pict.Bitmap.Canvas.Pixels[x, y] <> backcolor) do Inc(x);

//Создаем регион для части скан-линии и добавляем его к

//результирующему региону

rgn:= CreateRectRgn(xFirst, y, x–1, y+1);

CombineRgn(resRgn, resRgn, rgn, RGN_OR);

DeleteObject(rgn);

end;

Inc(x);

end;

end;

RegionFromPicture:= resRgn;

end;


Загрузка изображения-шаблона и создание региона могут происходить, например, при создании формы (листинг 1.20).

Листинг 1.20. Создание региона для области отсечения формы

procedure TfrmTemplate.FormCreate(Sender: TObject);

var

pict: TPicture;

begin

//Загрузка изображения и создание региона

//(считаем, что цвет фона – белый)

pict:= TPicture.Create;

pict.LoadFromFile('back.bmp');

SetWindowRgn(Handle, RegionFromPicture(pict, RGB(255,255,255)), True);

end;


В листинге 1.20 подразумевается, что используется файл back.bmp, находящийся в той же папке, что и файл приложения. Цвет фона – белый. Таким образом, если шаблон, показанный на рис. 1.11, хранится в файле back.bmp, то в результате получается форма, показанная на рис. 1.12.

Рис. 1.12. Результат построения региона по шаблону

Немного о перемещении окон

Кроме придания необычного вида окнам способами, рассмотренными выше, можно также несколько разнообразить интерфейс за счет оригинального использования перемещения окон. Ниже показано, как можно самостоятельно назначать области, позволяющие перетаскивать форму. Еще один пример демонстрирует один из способов дать пользователю возможность самому определять расположение элементов управления на форме.

Перемещение за клиентскую область

Здесь на конкретном примере (перемещение формы за любую точку клиентской области) продемонстрировано, как можно самостоятельно определять положение некоторых важных элементов окна. Под элементами окна здесь подразумеваются:

• строка заголовка (предназначена не только для отображения текста заголовка, но и служит областью захвата при перемещении окна мышью);

• границы окна (при щелчке кнопкой мыши на верхней, нижней, правой и левой границе можно изменять размер окна, правда, если стиль окна это допускает);

• четыре угла окна (предназначены для изменения размера окна с помощью мыши);

• системные кнопки закрытия, разворачивания, сворачивания, контекстной справки (обычно расположены в строке заголовка окна);

• горизонтальная и вертикальная полосы прокрутки;

• системное меню (раскрывается щелчком кнопкой мыши на значке окна);

• меню – полоса меню (обычно расположена вверху окна);

• клиентская область – по умолчанию все пространство окна, кроме строки заголовка, меню и полос прокрутки.

Каждый раз, когда над окном перемещается указатель мыши либо происходит нажатие кнопки мыши, система посылает соответствующему окну сообщение 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.

Рис. 1.14. Элементы управления можно перемещать (флажок не учитывается)


В результате выполнеия произвольных перемещений, изменения размера окон, занявших место элементов управления, снятия флажка получаем измененный интерфейс формы (рис. 1.15).

Рис. 1.15. Внешний вид формы после перемещения элементов управления


Как же достигнут подобный эффект? Очень просто. Вы уже знаете, что элементы управления рисуются внутри своих собственных окон (дочерних по отношению к окну формы). Окна элементов управления отличает отсутствие в их стиле флагов (подробнее в гл. 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Следующая
  • 0 Оценок: 0

Правообладателям!

Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.


Популярные книги за неделю


Рекомендации