Главная » Delphi » Прозрачная форма и окно flystyle

0

Функция combineRgn очень удобна, ее механизм применения напоминает способы копирования канвы методом CopyRect. И там и там задаются параметры комбинации накладываемого изображения (региона) с фоном, только CombineRgn обладает более широкими возможностями, т. к. позволяет складывать различными способами участки произвольной формы и, самое главное, позволяет вычитать накладываемый регион из фона, получая прозрачные области. В Windows ХР, как мы уже не раз упоминали, есть механизм обеспечения прозрачности участков формы. Причем даже два механизма: один есть чистая (как в Photoshop) реализация альфа-канала с переменной прозрачностью (свойства AlphaBlend и A.lphaBien-iValue), а другой аналогичен заданию "прозрачного" цвета для BitMap (TransparentCoior и TransparentColorValue). Но они, к сожалению, не работают в Windows 9д\ A CombineRgn предоставляет универсальный механизм для такого рода операций, причем не только для равномерно закрашенных областей. Однако задавать прозрачный регион вам придется вручную, что при сложной его форме может стать достаточно громоздким занятием. Пример такой операции можно найти в [5] — идея автора состоит в том, что мы просматриваем последовательно строка за строкой (или столбец за столбцом) весь массив пикселов, и последовательно присоединяем к первоначальному региону одномерные области— фрагменты строки, цвет которых отличается от заданного "прозрачным". Мы же продемонстрируем некоторые возможности этого механизма на примере создания окна flystyle — т. е. окна, которое при запуске имеет только звголовок, а полностью раскрывается при щелчке на нем, подобно пунктам меню. Похожим образом реализованы, например, управляющие панели инструментов в графическом редакторе Paint Shop Pro версии 7.0 и выше.

Создадим пробный проект под названием Region (папка Glaval2\2) и установим ДЛЯ формы следующие свойства: BorderStyle В bsDialog, Color В clBlack. Position В poDesktopCenter, HorzScrollBar.Visible И VertScrollBar.Visible 5 False. Чтобы не возиться с загрузкой в канву, установим на форму компонент image и сразу загрузим в него через свойство Picture картинку, в качестве которой я использовал портрет своего любимого шотландского вислоухого кота по кличке Бакс. В заголовке формы я так и написал на чистом русском языке Kot, чтобы ни у кого не возникало сомнений, что перед вами не кошка. Картинка имеет ширину 433 пиксела и под нее подогнаны все остальные размеры (рис. 12.1).

Добавим следующие переменные в тексте модуля формы и напишем обработчик События onCreate:

var

Formi: TForml;

fReg,cReg:hRGN; ClientX,ClientY,i: Integer; fView:boolean=True;

procedure TForml.FormCreate(Sender: TObject); begin

ClientX:=0;

ClientY:-Height-ClientHeight;

fReg:=CreateRectRgn(0,0,Width,Height); /вся форма) cReg:=CreateRectRgn(ClientX,Cl?entY,ClientX+Width, ClientY+ClientHeight); {клиентская часть формы)

CombineRgn(fReg,fReg,cReg,rgn_Diff); {вычитаем} SetWindowRgn(handle,fReg,True);{демонстрируем} end;

Рис. 12.1. Форма с картинкой на этапе конструирования

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

ClientX:= (Width – ClientWidth) div 2; ClientY:= Height-ClientHeight-ClientX;

Теперь нужно создать обработчик события щелчка по заголовку, в котором мы будем показывать и убирать обратно картинку — т. е. реализуем режим flystyle. Для того чтобы определять текущее состояние — видна картинка или не видна— я ввел переменную-флаг fv.iew, по умолчанию имеющую значение True. Объявим в секции private процедуру-ловушку под названием captionciick, на этот раз для сообщения wm_w с lbutt on down . Вопрос о том, какое именно сообщение использовать, нв самом деле тут довольно принципиален— так, если мы будем раскрывать/закрывать окно по простому щелчку, как я предлагаю, то при попытке просто подвигать заголовок, форма все равно раскроется, что может раздражать. Если мы хотим, чтобы форма раскрывалась не по щелчку, а, например, просто при наведении курсора, то можно попробовать использовать сообщение vjm ncmousemove— правда, при этом придется крепко подумать над логикой работы процедуры. При использовании двойного щелчка— пользователь может просто не понять, что от него ждут именно этого. Наилучшим вариантом является логика, аналогичная той, которую используют в Windows при работе с иконками на рабочем столе — если просто щелкнули, то при отпускании происходит раскрытие, а если хоть чуть-чуть подвигали, то больше ничего не будет. Но здесь мы не будем усложнять— просто продемонстрируем, как это делается в принципе. Итак, дописываем объявление процедуры и ее обработчик:

private

procedure CaptionClick(var msg: TMessage); message WM_NCLBUTT0NIX3WN;

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

if msg.WParam=HTCAPTTON then begin

if fView = True then begin

fView:=False;

fReg:=CreateRectRgn(0,O.Width,Height); (вся форма} cReg:=CreateRectRgn(ClientX,ClientY,ClientX+Width,

ClientY+ClientHeight); (клиентская часть формы/

CombineRgn(fReg,fReg,cReg,rgn_Diff); (вычитаем) for i:= 0 to ControlCount-1 do (собираем "контролы"}

with Controls[I] do begin

cReg:= CreateRectRgn(ClientX+Left, ClientY+Top, ClientX+Le ft+Width,CIientY+Top+Height); CombineRgn(fReg,fReg,cReg,rgn_Or); end; end else begin

fView:=True;

fReg:=CreateRectRgn(0,0,Width,Height); {вся форма} cReg:=CreateRectRgri (ClientX,ClientY,ClientX+Width,

ClientY+ClientHeight); {клиентская часть формы)

CombineRgn(fReg,fReg,cReg,rgn_Diff); {вычитаем) end; end;

SetWindowRgn(handle,fReg,True);{демонстрируем} end;

Рис. 12.2. Раскрытое окно с картинкой после щелчка на заголовке

Что мы тут делаем? При первом щелчке мы сначала заново создаем тот же самый регион, состоящий из одного видимого заголовка, но добавляем к нему все визуальные объекты-"контролы", расположенные на форме, — в этом случае фон окна останется прозрачным, а все имеющиеся компоненты станут видимыми. На самом деле у нас здесь всего один такой объект — imagei, но я опять же написал в общем виде для удобства усовершенствования программы. В результате мы при щелчке на заголовке получим вот такую картинку (рис. 12.2) — я ее специально воспроизвел на фоне текста этого примера. А при втором щелчке окно опять свернется в заголовок.

Все эти механизмы открывают необычайные перспективы для создания нестандартных программ: от полноправных Windows-приложений, остающихся тем не менее невидимыми, или псевдоиконок на рабочем столе, до серьезных приложений с полупрозрачными дочерними окнами и управляющими элементами, экономящими экранную площадь. Главное— не позволить себе слишком увлечься.

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

По теме:

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