Красота - это страшная сила MostInfo.net (http://mostinfo.net/article/9/47.htm) В этой статье я рассматриваю несколько способов сделать форму красивой... |
||||
Ян Валерьевич delphimaster.ru 10-05-2004 |
||||
В этой статье я рассматриваю несколько способов сделать форму красивой. Примеры, рассмотренные здесь, имеют скорее эстетическую, чем практическую ценность, но, я думаю, ими можно воспользоваться при оформлении окон вашей, уважаемые читатели,программы. Для оформления я рассмотрю несколько способов залития формы градиентной заливкой (пример такой заливки - инсталляторы, в которых пользователь любуется красивым окном, пока программа делает своё чёрное дело). В различных Faq я встречал примеры, заливающие форму каким - либо градиентом, и существуют компоненты, применяющие градиентную заливку для оформления (например TRxGradientCaption из RxLib), но статьи, систематизирующей информацию по этому вопросу я не встречал. Поэтому я надеюсь, что этот материал окажется вам полезным. Для заполнения холста (Canvas) формы я использую код, основа которого взята мною у достопочтенного Nomadic"а из Озеровского FAQ. Его код я преобразовал в одно событие OnPaint (у Nomadic"а в примере был размещён Timer и обрабатывлись FormCreate,Timer.OnTimer, FormDestroy). Вот этот код: procedure TForm1.FormPaint(sender:TObject); type TRGB=record b,g,r:byte; end; ARGB=array [0..1] of TRGB; PARGB=^ARGB; var b:TBitMap; p:PARGB; x,y:integer; begin b:=TBitMap.Create; b.pixelformat:=pf24bit; b.width:=Clientwidth; b.height:=Clientheight; for y:=0 to b.height-1 do begin p:=b.scanline[y]; for x:=0 to b.width-1 do begin //эту часть кода будем изменять p[x].r:=random(256); p[x].g:=random(256); p[x].b:=random(256); end; end; canvas.draw(0,0,b); b.free; end; Это - способ быстрого (в отличие, например, от Canvas.Pixels) рисования на холсте формы. Результат действия этого кода - заполнение формы точками случайного цвета (рис.1). Дальнейшие изменения кода будут прозводится мною в основном с тремя строками, вкоторых происходит заполнение точки холста - в коде они выделены красным цветом. Для получени горизонтального градиента (я буду использовать термины градиент или заливка вместо градиентная заливка) нужно изменять величину r,g,b не случайным образом, а в цикле по х. Например, зафиксирова два цвета и измняя третий от 0 до 255 мы получим горизонтальную заливку от белого до смеси фиксированных цветов. Следующий код даст нам бело - жёлтый градиент на форме (рис. 2): p[x].r:=255; p[x].g:=255; p[x].b:=-255*x div b.width ; При применении горизонтальной заливки следует учесть, что пустой залитый объект кажется неустойчивым и его нужно уравновесить, разместив что-то на нём (рис.3). Вертикальную заливку получить не намного сложней. Для этого нужно изменять цвета не по х, а по у. Например, следующий код даст нам столь любимую инсталляторами сине - белую заливку ( рис. 4). p[x].r:=255*y div b.Height; p[x].g:=255*y div b.Height; p[x].b:=255; Обратите внимание - чтобы получить сине - белый градиент я изменяю красный и зелёный цвета, а синий оставляю неизменным. Вообще получение нужной цветовой растяжки я считаю одним из самых хитрым вопросов данной темы, и я вернусь к нему в конце данной статьи. Ещё более красивого эффекта можно достигнуть накложив градиенты друг на друга. Например изменяя красный цвет по вертикали, а зелёный по вертикали мы получим следующую картину (рис. 5) p[x].r:=255*y div b.Height; p[x].g:=255*x div b.Width; p[x].b:=255; Полученному градиенту можно придать зернистую структуру, изменяя один или несколько основных цветов случайным образом. Что вы скажете о заливках на рисунках 6 и 7? p[x].r:=random(250); p[x].g:=255; p[x].b:=255*x div b.Width; (рис. 6) p[x].r:=random(250); p[x].g:=255*y div b.Height; p[x].b:=255*x div b.Width; (рис.7) Для получения более сложного распределения градиента по форме придётся использовать более сложные формулы при присвоении значений цветов. Рассмотрим получение заливки "к центру". Очевидно изменяемый цвет должен уменьшаться или увеличиваться от края к центру формы, а затем изменяться в обратном порядке. Этого можно достичь с помощью условного оператора (более наглядный способ) (рис 8). p[x].r:=0; if y <= b.Height div 2 then p[x].g:=255*y*2 div b.Height else p[x].g:=-255*y*2 div b.Height ; if abs(y - b.Height div 2)<3 then p[x].g:=255; {без этой строки образуется полоса в центре заливки при увеличении размеров формы} p[x].b:=200; Более сложный способ - составить функцию, изменяющую цвет нужным образом. Для следующего примера нам понадобится функция Sgn: function Sgn(i:integer):integer; begin if i<>0 then Sgn:=round(i/abs(i)) else Sgn:=1 end; Функция Sign из модуля Math не подходит, т.к. возвращает 0 при значении аргумента 0. Следующий код даёт такой вариант заливки (рис. 9): p[x].r:=150; p[x].g:=Sgn(b.Width div 2-x)*(255*x*2 div b.Width); p[x].b:=50; На рисунке 9а показан результат замены функции Sgn, определённой нами на функцию Sign из модуля Math. Возвращаемый ноль приводит к появлению полосы в середине формы. Комбинируя рассмотренные способы заливок можно получить формы, вид которых изумит всех, включая создателя (рис 10 - 12). p[x].r:=50; p[x].g:=sgn(b.Width div 2-x)*(255*x*2 div b.Width); p[x].b:=sgn(b.Height div 2-y)*(255*y*2 div b.Height); { Зелёная составляющая изменяется к центру по горизонтали, а синяя по вертикали} (рис. 10) p[x].r:=150*x div b.Width; p[x].g:=sgn(b.Width div 2-x)*(255*x*2 div b.Width); p[x].b:=155*y div b.Height; {Красная составляющая изменяется слева направо, зелёная по горизонтали к центру, синяя сверху вниз}(рис. 11) p[x].r:=150*x div b.Width; p[x].g:=sgn(b.Width div 2-x)*(255*x*2 div b.Width); p[x].b:=155%2Brandom(100); {Тоже, но синий цвет изменяется случайным образом}(рис. 12) Вас не интригует число 255, присутствующее в формулах? Очевидно, уменьшая его мы изменяем цвет, с которого начинается заливка, а вот увеличение числа приводит к интересному эффекту "жалюзи" - дублированию градиентной заливки по форме (рис. 13) p[x].r:=0; p[x].g:=255*4*y div b.Height; p[x].b:=155; Здесь я не стал писать 1020 вместо 255*4, чтобы было видно откуда взялись четыре "волны" градиентной заливки. Ещё один эффект (рис. 14) - плавно переходящие градиентные волны получаются с помощью следующего, правда довольно неуклюжего кода: p[x].g:=0; if (x <= b.Width div 4) or ((x <= 3*b.Width div 4) and (x >= b.Width div 2)) then p[x].r:=255*x*4 div b.Width else p[x].r:=-255*x*4 div b.Width ; if abs(x - b.Width div 2)<3 then p[x].r:=0; if (abs(x -b.Width div 4)<3) or (abs(x - 3*b.Width div 4)<3) then p[x].r:=255; p[x].b:=0; Впрочем, этот эффект будет получен в конце статьи другим, более простым способом. Итак, вы получили красиво залитую форму и стали изменять её размеры. И тут вы столкнулись с некрасивым эффектом - на форме отпечатываются артефакты от заливки (рис 15). Способов исправить эту ситуацию существует много. Воспользуемся самым очевидным из них: procedure TForm1.FormResize(Sender: TObject); begin form1.DoubleBuffered:=true; form1.Repaint; end; Теперь при изменении размеров формы внешний вид заливки не изменяется. Следующий вопрос, который нельзя обойти вниманием в этой статье - это вопрос выбора цветов для создания градиента. Для его исследования в общем случае нужно иметь представление о RGB цветовой модели. Цветовой переход градиента представляет собой кривую в этой модели, уравнение которой нужно задать в программе. Изучение цветовой модели и создание произвольного цветового градиента - задача не для статьи. Здесь рассмотрим, как получить двухцветный переход. Довольно понятно решение для основных цветов (красный, синий, зелёный) и их смесей. Так RG даёт жёлтый цвет, RB - фиолетовый, GB - лазурный. Например, для получения сине - жёлтой раcтяжки нужно изменять B от 255 до 0, R и G от 0 до 255 - вот так (рис. 16).
Применять эту процедуру можно к любому объекту имеющему Canvas, например к TImage (рис. 17) Image1.Stretch:=true // где-нибудь, можно на этапе проектирования. procedure TForm1.FormResize(Sender: TObject); Оригинал статьи находится по адресу http://mostinfo.net/article/9/47.htm | ||||