Главная » Delphi » Нестандартные окна

0

Прежде чем приступать к увлекательному занятию по созданию окон нетрадиционной формы, как следует подумайте над аопросом: а оно вам надо? Одной из причин (но, конечно, не единственной), по которой я никогда не пользуюсь программами из пакета Norton Utilities for Windows, было совершенно отталкивающее впечатление, произведенное на меня главным окном этой программы. На кого рассчитана эта картинка в стиле иллюстраций к Толкие- ну? Напомним, что речь идет не о Media Player, а о чисто вспомогательных программах, которые просто обязаны быть как можно незаметнее. Не рискуя сильно ошибиться, могу предположить, что разработчики из Symantec серьезно больны весьма распространенной болезнью— показать всему миру, какие они крутые программисты. Не дай бог вам, читатель, заболеть этим недугом — вылечиться бывает весьмв трудно. Конечно, на вкус и цвет, как говорится… но на всякий случай я обхожу как можно дальше продукцию этой фирмы, представив себе, что они могут наворотить, например, в Norton Antivirus, когда программа скрыта с глаз пользователя.

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

Для того чтобы менять форму окна, в Windows есть специально предусмотренный механизм создания регионов (regions). Регионы могут быть квадратные (CreateRectRgn), с закругленными краями (сгс-аteRoundRectRgn), эллиптические (CreateEllipticRgn), ПРОИЗВОЛЬНОЙ формы (Cre-atePolygonRgn) И даже составленными из набора произвольных полигонов либо стандартных форм (CreatePolyPolygonRgn, CombineRgn). Как ВЫ догадались, В скобках ДЛЯ каждого случая приведены функции, с помощью которых такой регион создается. Позже вы увидите практические примеры использования некоторых из них, а пока заметим, что параметры функций, естественно, для разных случаев разные, но общим для них остается указание дескриптора объекта, форму которого предполагается изменить. Вот общий порядок использования функций на примере создания круглого окна диаметром 400 пикселов:

var fReg:hRGN;

fReg:=CreateEl1ipticRgn(0,0,400, 400); SetWindowRgn(Formi.handle,fReg,True);

Если вставить эту процедуру в обработчик события, например, Formi.Create, то при создании окно главной формы сразу станет круглым. Причем в качестве первого параметра необязательно использовать дескриптор именно формы, это может быть любой компонент, и даже канва формы (Formi.Canvas.Handle) или другого компонента. Если вы зададите для канвы заставки в проекте SlideShow такую форму, то получите круглую картинку в прямоугольном окне. Только имейте в виду, что если объект, для которого задается конфигурация, изначально меньше по размерам, чем заданная область, то или ничего не произойдет вообще, или отрежется только часть компонента. Тут мы пришли к крупнейшему недостатку данного механизма: реально все эти функции управляют только отображением заданной области, деформировать регион нельзя. Нельзя, например, встввить картинку в непрямоугольный компонент так, чтобы она должным образом изменила свою форму. Нельзя создать круглую кнопку только с использованием этих функций — ее сначала придется отдельно нарисовать. Заголовок полукруглого окна также придется рисовать самостоятельно. Мало того, нельзя даже автоматически задать вывод текста в фигурный компонент так, чтобы текст не обрезался, придется придумывать собственные сложные процедуры. Если поразмыслить, то все это отчасти оправданно тем, что деформация любого изображения требует использования специальных алгоритмов и довольно значительного количества вычислительных ресурсов, но все же это ограничение намного снижает потенциал метода.

И все же указанные функции позволяют получить многие полезные эффекты. Для ориентировки читателя перечислим некоторые вспомогательные функции: FrameRgn обводит регион рамкой указанной кистью заданной ширины. FillRgn заполняет его указанной кистью в стиле, который может быть задан функцией setPolyFiliMode, и т. п. Приводить примеры мы не будем, они достаточно просты, и их при необходимости лег ко найти в Сети. Единственное, на что стоит обратить внимание: у начинающих обычно ничего не выходит с созданием полигонального региона (createPolygonRgn), т. к. в нем надо задавать многоугольник через параметр типа array of тPoint. Правильно координаты вершин будет задать, например, по такому образцу:

const

Points : array[0..3] of ТPoint = ((Х:80;Y:0), (X:0;Y:80), (X:80;Y:160), (X:160;Y:80));

И сразу ответим на известный вопрос, как перемещать по экрану форму, которая не имеет заголовка, или у которой заголовок сформирован искусственно. Для этого надо перехватывать сообщение wm nchittest. В простейшем виде реализация этого способа выглядит так:

private

procedure Wdrop (var msg: TMessage); message WM_NCHITTEST;

procedure TForml.Wdrop(var msg: TMessage); begin Inherited;

msg.Result := HTCAPTION; end;

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

Inherited; with msg do

{переводим экранные координаты мыши в оконные} with ScreenToClient(Point(XPos,YPos)) do if PtlnRegion(rTitle, X, Y) then Result := HTCAPTION;

Здесь rTitle— регион, определяющий область заголовка, а функция PtlnRegion определяет, принадлежит ли точка (х, y) этому региону. Можно тем же путем даже обеспечить имитацию системных кнопок, если при нажатии на нужные области возвращать через Result значения htmaxbuttok, htminbutton, htclose или htsysmenu. Далее мы покажем, как на практике не- рехватывать сообщения типа wk nc.v.-.x-v, т. е. сообщения, которые относятся, согласно терминологии разработчиков Windows, к событиям мыши "while the cursor is within the nonclient area of a window" (когда курсор находится в неклиентской области окна) — это цитата из официальной справки.

А сейчас мы перестанем заниматься, наконец, теорией и немножко разукрасим нашу заставку в проекте SiideShow.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

  • Комментарии