Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Полупрозрачная форма, Форма, через которую виден стол? 
:(
    Опции темы
-Vadim-
  Дата 12.8.2003, 03:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 10.8.2003

Репутация: нет
Всего: нет



Как бы мне увидеть раб. стол через окно моей формы?


PM MAIL   Вверх
Vit
Дата 12.8.2003, 04:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 48
Всего: 207



Delphi 7 (не помню может опция уже в Д6 появилась, но гарантировать не могу) - свойство alfablend или как-то похоже.


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
p0s0l
Дата 12.8.2003, 08:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



AlphaBlend, AlphaBlendValue - D6, D7 (% прозрачности)
TransparentColor, TransparentColorValue - D7 (указывает цвет, вместо которого будет показываться то, что под окном)



--------------------
С уважением, г-н Посол.
PM   Вверх
Medved
Дата 12.8.2003, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 14
Всего: 154



Ключом к созданию прозрачных форм и компонентов является функция SetWindowRgn:

unit TransparentForm;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;

type
TTransparentForm = class(TForm)
// это просто кнопка на форме - для демонстрации
Button1: TButton;
protected
procedure RebuildWindowRgn;
procedure Resize; override;
public
constructor Create(AOwner: TComponent); override;
end;

var
TransparentForm: TTransparentForm;

implementation

// ресурс этой формы
{$R *.DFM}

{ TTransparentForm }

constructor TTransparentForm.Create(AOwner: TComponent);
begin
inherited;
// убираем сколлбары, чтобы не мешались
// при изменении размеров формы
HorzScrollBar.Visible:= False;
VertScrollBar.Visible:= False;
// строим новый регион
RebuildWindowRgn;
end;

procedure TTransparentForm.Resize;
begin
inherited;
// строим новый регион
RebuildWindowRgn;
end;

procedure TTransparentForm.RebuildWindowRgn;
var FullRgn, Rgn: THandle;
ClientX, ClientY, I: Integer;
begin
// определяем относительные координаты клиенской части
ClientX:= (Width - ClientWidth) div 2;
ClientY:= Height - ClientHeight - ClientX;
// создаем регион для всей формы
FullRgn:= CreateRectRgn(0, 0, Width, Height);
// создаем регион для клиентской части формы
// и вычитаем его из FullRgn
Rgn:= CreateRectRgn(ClientX, ClientY, ClientX + ClientWidth, ClientY +
ClientHeight);
CombineRgn(FullRgn, FullRgn, Rgn, rgn_Diff);
// теперь добавляем к FullRgn регионы каждого контрольного элемента
for I:= 0 to ControlCount -1 do
with Controls[I] do begin
Rgn:= CreateRectRgn(ClientX + Left, ClientY + Top, ClientX + Left +
Width, ClientY + Top + Height);
CombineRgn(FullRgn, FullRgn, Rgn, rgn_Or);
end;
// устанавливаем новый регион окна
SetWindowRgn(Handle, FullRgn, True);
end;

end.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Medved
Дата 12.8.2003, 08:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 14
Всего: 154



Способ 2.

Для этого необходимо пеpеопpеделить обpаботчик события OnCreate:
Код

procedure TForm1.FormCreate(Sender: TObject);
begin
 Brush.Style:=bsClear;
end;





--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
-Vadim-
Дата 13.8.2003, 01:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 10.8.2003

Репутация: нет
Всего: нет



O'Key. Вижу базу дали. Потом разберусь. Спасибо.
PM MAIL   Вверх
Fedor
Дата 13.8.2003, 07:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Днепрянин
****


Профиль
Группа: Участник
Сообщений: 2090
Регистрация: 8.2.2003
Где: Великий

Репутация: нет
Всего: 32



А вот продолжение этого вопроса... А как сделать форму, например со скругленными углами...


--------------------
Мы - Днепряне. Мы всех сильней.
PM ICQ   Вверх
Medved
Дата 13.8.2003, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 14
Всего: 154



Модератор: Пожалуйста, один топик - один вопрос.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
p0s0l
Дата 13.8.2003, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 58
Всего: 112



Цитата
А вот продолжение этого вопроса... А как сделать форму, например со скругленными углами...

По-моему можно сделать на примере Pegas'а, хотя не пробовал.



--------------------
С уважением, г-н Посол.
PM   Вверх
-Vadim-
Дата 14.8.2003, 02:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 10.8.2003

Репутация: нет
Всего: нет



А вот продолжение этого вопроса... А как сделать форму, например со скругленными углами...


ОТВЕТ:
Округленные формы получаються так.
var MyRegion: HRGN;

//Задаеться регион...
MyRegion:= CreateRoundRectRgn(0, 0, Width, Height, 50, 50);
//(Здесь последнии 50,50 и есть "коэф. приломления")

//Который передаеться функции...
SetWindowRgn (Handle, MyRegion, true);
PM MAIL   Вверх
Medved
Дата 14.8.2003, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 14
Всего: 154



Откройте отдельный топик, и кину я пример вам и круглых форм и треугольных и хоть тристоугольных.

P.S. Только не нарушайте правила. А то придется закрою тему.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
-Сергей-
Дата 15.8.2003, 05:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: нет
Всего: 1



А как тебе эта прозрачная форма?

Я её делал ещё в Delphi3 для Windows 95!

Код
unit Unit1;

{  Как сделать полупрозрачное окно

  Прежде всего, хочу предупредить, что этот текст рассчитан на людей,
  знакомых с функциями WinAPI и сообщениями Windows и поэтому вряд ли
  будет полезен тем, кто предпочитает ограничиваться работой на уровне
  компонентов Delphi. А тем, кто решит всё-таки прочитать это всё,
  настоятельно рекомендую сначала запустить программу и немного
  поиграться с окном, чтобы представлять себе некоторые особенности
  его поведения, о которых я буду упоминать.

  Теперь ещё три предупреждения: во-первых, механизм перерисовки окон
  в Windows не предусматривает создания полупрозрачных окон. Поэтому
  приходится выискивать лазейки и действовать в обход правил Windows.
  Крайне маловероятно, чтобы это могло привести к нестабильности системы,
  но вот само полупрозрачное окно иногда перерисовывается не совсем
  правильно. Во-вторых, кое-что в этом примере подобрано методом проб и
  ошибок, и даже я сам не всегда могу объяснить, почему это работает.
  В таких случаях я честно признаюсь в этом. И в-третьих, эта программа
  написана только для демонстрации самого принципа создания полупрозрачных
  окон и кое-что в ней можно (и иногда даже нужно) улучшить. По ходу текста
  я постараюсь указать на такие места.

  Внутренняя логика перерисовки окон в Windows такова, что каждый раз
  перерисовывается только та его часть, которая не закрыта другими окнами и,
  следовательно, видна на экране. Это ускоряет процесс обновления экрана.
  Но полупрозрачное окно должно каким-то образом получать информацию о том,
  что нарисовано под ним. Здесь мы вступаем в противоречие с правилами
  Windows, поэтому следует прибегнуть к некоторому обману. При необходимости
  перерисовать полупрозрачное окно надо это окно ненадолго убрать с экрана.
  Как только все нижележащие окна будут перерисованы, надо запомнить ту
  область экрана, которая будет закрыта окном, вновь вывести на экран это
  окно и отрисовать его с учётом сохранённой картинки. Первая трудность на
  этом пути - как узнать, что перерисовка всех окон закончилась? Windows
  не считает нужным информировать программу об этом. Единственный способ,
  который я знаю, - выждать определённое количество времени, надеясь, что
  этого хватит. Недостатки этого способа настолько очевидны, что я даже не
  хочу писать о них. Скажу только, что времени задержки 400 мс, которое
  установлено в этом примере хватало на моём компьютере (почти уже музейном
  экспонате, если честно). Но всегда может найтись долго перерисовывающаяся
  программа, для которой не хватит даже Pentium !!!-500 со всеми возможными
  ускорителями. Вторая трудность - если вдруг окно, лежащее под
  полупрозрачным, обновилось, то это не приведёт сразу же к перерисовке
  этого окна. Особенно некрасиво получается, когда обновлённое окне только
  частично находится под полупрозрачным. Тогда видимая его часть уже
  содержит обновлённое изображение, а скрытая под полупрозрачным - всё
  ещё старое.

  Теперь о том, как осуществить всё это на практике. Перерисовка окна
  определяется обработкой двух сообщений: WM_EraseBkgnd и WM_Paint.
  Я пробовал и то, и другое - оказалось, что WM_Paint лучше по трём
  причинам. Во-первых, WM_EraseBkgnd почему-то может посылаться по
  несколько раз, соответственно окно перерисовывается до трёх раз подряд,
  а выглядит это некрасиво, особенно если вспомнить, что каждая
  перерисовка сопровождается задержкой. Во-вторых, между WM_EraseBkgnd и
  WM_Paint есть существенная разница: в первом случае Windows сам (сама?
  само? Windows - он кто? Мужчина или женщина?) определяет, какая часть
  окна должна перерисоваться, и рисовать за пределами этой части просто
  не разрешает. А полупрозрачное окно, вообще говоря, обладает нетрадиционной
  точкой зрения на этот вопрос, что и приводит к конфликтам, особенно
  тогда, когда полупрозрачное окно частично закрыто другими окнами. Что
  же касается WM_Paint, то и тут Windows, конечно же, держит всё под
  контролем и тоже следит за тем, какая область окна должна быть перерисована.
  Однако, к счастью для полупрозрачных окон, это всё не выливается в
  прямые запреты, как в случае с WM_EraseBkgnd, здесь Windows ограничивается
  только выдачей ценных указаний (ЦУ) (через BeginPaint и TPaintStruct). Ну,
  а мы, естественно, пренебрегаем этими ЦУ и внаглую отрисовываем окно
  целиком. И наконец, в-третьих, Windows зачем-то генерирует WM_EraseBkgnd
  после выполнения ShowWindow, поэтому попытка спрятать окно при обработке
  этого сообщения приведёт к бесконечной рекурсии. Оно конечно, можно вставить
  в программу переменную-семафор, с помощью которой будет блокироваться
  повторный вызов ShowWindow, но зачем писать код, без которого можно
  обойтись? Надеюсь, я убедил вас, что WM_Paint лучше, чем WM_EraseBkgnd.
  Впрочем, пренебрегать WM_EraseBkgnd тоже не стоит. Дело в том, что во
  время запуска программы этому процессу, видимо, присваивается повышенный
  приоритет (а может, и не повышенный приоритет, а я даже и не знаю, что,
  но все остальные программы почти останавливаются на это время). Вот это
  самое не знаю что приводит к тому, что наше окно начинает рисоваться,
  Windows посылает WM_EraseBkgnd, стандартная процедура обработки этого
  события закрашивает всю клиентскую часть окна красивым серым цветом
  (как обычно), затем обрабатывается WM_Paint, в котором окно прячется с
  экрана, после чего остальные окна должны быстро перерисоваться и, когда
  пройдёт заданное время, программа посмотрит, что там нарисовано, начнёт
  наложение светофильтра... Опаньки! Окна-то не успели перерисоваться!
  Программа увидит своё собственное окно, которое не успели стереть. Это
  не входит в наши планы, поэтому, чтобы не увеличивать время ожидания,
  нужно заблокировать вызов стандартного обработчика WM_EraseBkgnd. Это,
  естественно, никак не отразится на скорости перерисовки остальных окон,
  но ведь и само окно ничего не нарисует на экране, и после ожидания
  программа увидит то, что надо. Это я как мог изложил теорию процесса,
  а как это реализовано на практике - читайте комментарии в тексте самих
  процедур.

  Должен заметить, что Windows поддерживает стиль окна WS_EX_TRANSPARENT.
  Если верить описанию, то такое окно должно получать WM_Paint только
  после того, как все нижележащие окна нарисованы. Звучит заманчиво,
  но эксперименты с этим окном показывают, что оно ведёт себя, мягко
  говоря, невразумительно. Мне пока не удалось получить что-либо путное
  от этого окна. Будем думать дальше.

  И последний штрих: при перемещении окна Windows, во избежание ненужных
  действий, не запускает механизм перерисовки, а просто переносит изображение
  с одного места на другое. Для полупрозрачных окон это недопустимо, изображение
  должно обновляться при каждом переносе. Для этого надо отслеживать
  сообщение WM_Move, которое возникает в таких случаях. И, соответственно,
  запускать перерисовку окна. Если WM_Move вам почему-то не подходит
  (не знаю, почему бы это могло быть, ну да ладно; может, у вас аллергия
  на него или он оскорбляет ваши убеждения), вы можете использовать
  WM_WindowPosChanged. Я пробовал и то, и другое и не заметил разницы.
  Вот если бы мы использовали не WM_Paint, а WM_EraseBkgnd, то эти два
  способа были бы неравноценны, но мы договорились использовать WM_Paint,
  поэтому не будем на этом останавливаться.

  Но Windows не был бы (Не была бы? Не было бы? См. выше) Windows'ом, если бы
  не приготовил (-а? -о?) бы ещё хотя бы один сюрприз. Дело в том, что, когда
  пользователь таскает по экрану окна, они могут либо перерисовываться целиком,
  либо может рисоваться только рамочка. Управляется это специальными системными
  установками, которые, во-первых, могут быть разными в разных версиях и,
  во-вторых, настраиваются разными утилитами вроде MS-Plus! С рамочкой всё
  просто: мы её подвинули, куда надо (Или не мы. Или куда не надо. Неважно.),
  окно переместилось, и начался процесс перерисовки: спрятались, подождали,
  нарисовались (в смысле появились) и нарисовались (в прямом смысле). Всё
  просто замечательно в том смысле, что наше окно всё это прекрасно делает.
  Единственный минус - задержка перед окончательным появлением. А теперь
  представьте, что будет, если таскается не рамка, а всё окно целиком. Чуть
  двинули мышью, и началось: спрятались, подождали и далее по тексту. Выглядит
  всё это более чем ужасно, такую издёвку над конечным пользователем может
  позволить себе только Microsoft, а вот к нам требования повыше будут. Так
  что напряжёмся ещё немного и сделаем что-нибудь с этим. Во-первых, нам надо
  найти способ узнать, чем вызвана перерисовка окна - тем, что его куда-то
  поволокли, или чем-то ещё. И, соответственно, вести себя по-разному.
  Во-вторых, неплохо бы знать, что должно быть под окном. С первым всё просто:
  есть сообщения WM_EnterSizeMove и WM_ExitSizeMove, которые сообщают о
  начале и конце перетаскивания. А вот со вторым - проблемы. Старый
  проверенный способ нам не подходит, слишком медленный, а за скорость
  приходится платить, обычно - памятью. Надо запоминать не только ту область
  экрана, которая нас интересует в данный момент, а думать и о будущем тоже,
  то есть, проще говоря, запоминать сразу весь экран. Чтобы коварный
  пользователь не застал внезапным перетаскиванием программу врасплох, она
  должна всегда запоминать весь экран. Для справки - при разрешении
  1024х768 точек при любом числе цветов на это уйдёт два с четвертью
  мегабайта. Возникает желание не тратиться так каждый раз, а начинать
  запоминать весь экран только после начала перетаскивания, а до этого
  довольствоваться лишь необходимым куском. Но представьте себе такую
  ситуацию: пользователь пытается зацепить окно и потащить его, а оно сразу
  же после нажатия кнопки мыши исчезает на полсекунды, чтобы запомнить, что
  же там под ним нарисовано. Скорее всего, непредупреждённый пользователь
  сразу же отпустит мышь. Окно появится, он снова попытается зацепить его,
  окно снова исчезнет. Догадайтесь с трёх раз, кого из родственников автора
  программы он вспомнит после этого. Кроме того, если установлен режим
  перетаскивания не всего окна, а только рамки, то на это время перерисовка
  всех остальных окон, и даже если наша программа будет ждать не 400
  миллисекунд, а 49.7 дней - ничего под окном не перерисуется. (Почему
  49.7 дней? Именно за такое время внутренний счётчик миллисекунд системы
  переполняется, и Windows 95 благополучно виснет. Windows NT, правда,
  покрепче будет, но и более длительное ожидание нам не поможет.) В общем,
  если мы хотим, чтобы окошко нормально вело себя при перетаскивании, мы
  должны постоянно запоминать весь экран. Исключения возможны только если
  применить какой-нибудь алгоритм, по которому во время перемещения окно
  отображается по-другому. Самый грубый способ - сделать его на это время
  просто непрозрачным, более тонкий - использовать в качестве фона при
  перемещении тот кусок экрана, над которым окно находилось до начала
  перемещения. Будет не совсем то, что надо, но и не слишком ужасно.
  Непонятно только, что делать, если пользователь решит увеличить размеры
  окна. Так что этот способ подходит только для окон с постоянным размером.
  Но я не буду больше отвлекаться, потому что придумывание таких методов -
  работа для дизайнера, а не для программиста. А мы будем использовать
  самый универсальный способ - постоянно запоминать весь экран.

  Если вы уже посмотрели мой код, то, наверное, заметили, что его можно
  существенно ускорить без потери функциональности. Речь идёт опять-таки
  о перетаскивании окон в режиме перетаскивания окна целиком. Действительно,
  каждый раз перед перерисовкой на вырезанную часть запомненного ранее
  экрана накладывается светофильтр. На это наложение уходит время. А
  ведь можно было один раз, сразу после запоминания экрана, наложить на
  всю эту картинку светофильтр и при перетаскивании не тратить на это
  время, а просто вырезать нужный кусок. Но ведь мы договорились, что
  пишем универсальную программу. Этот же метод приемлем только тогда,
  когда мы накладываем однородный светофильтр. А если мы захотим применить
  какой-то особый эффект? (Об эффектах см. подробнее в комментариях в тексте
  программы.) Тогда цвет и прозрачность каждой точки будет зависеть от её
  координаты, и мы не сможем один раз применить этот эффект так, чтобы
  результат потом подходил для любого положения окна. Тем же, кто
  намеревается ограничится однородным светофильтром, я настоятельно рекомендую
  переделать мой код.

  Ну вот, окно и создано. Смотрится оно вполне прилично, но всё же не
  лишено некоторых недостатков. Наверное, их число можно уменьшить.
  Присылайте мне свои замечания (о некоторых особенностях поведения окна
  я могу и сам не знать), предложения и советы на адрес [email protected] или
  [email protected].

                                               Осокин Сергей
                                               16.08.03

   P.S. Этот пример распространяется абсолютно свободно и может быть без
  каких-либо ограничений использован для создания как коммерческих, так
  и некоммерческих приложений. Если вдруг этот пример поможет кому-нибудь
  написать что-то хорошее, то я попросил бы этого человека по возможности
  написать что-нибудь про меня в окне About. (Вот такой я тщеславный. А что
  делать?). Впрочем, если такой возможности не будет, то и не надо.

  P.P.S. Привет всем землякам-юргинцам, если такие вдруг найдутся. }

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, Spin;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   ColorDialog1: TColorDialog;
   SpinEdit1: TSpinEdit;
   Label2: TLabel;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure SpinEdit1Change(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   BM:TBitmap; {  картинка, в которой хранится изображение экрана  }
   BM2:TBitmap; {  картинка, в которой хранится фон окна  }
   Moving:Boolean; {   а эта переменная равна True, если окно в данный момент
                       перетаскивается пользователем  }
   procedure WMEraseBkgnd(var Msg:TWMEraseBkgnd);message WM_EraseBkgnd;
   procedure WMPaint(var Msg:TWMPaint);message WM_Paint;
   procedure WMMove(var Msg:TMessage);message WM_Move; //  Если вместо WM_Move поставить
                                                       //  WM_WindowPosChanged, ничего
                                                       //  не изменится.
   procedure WMEnterSizeMove(var Msg:TMessage);message WM_EnterSizeMove;
   procedure WMExitSizeMove(var Msg:TMessage);message WM_ExitSizeMove;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

const Transparency:Integer=40;  {  Прозрачность в процентах. Должна быть от 0 до 100  }
     TranspColor:TColor=clBlack;  {  Цвет окна  }
     DelayTime:Integer=400; {  Время задержки в миллисекундах  }

implementation

{$R *.DFM}

type PRGBArray=^TRGBArray;
    TRGBArray=array[0..1000000] of TRGBTriple;
    {  Вместо 1000000 может быть любое число, даже 0, только тогда придётся
       отключить проверку диапазона. Экземпляры массивов этого типа всё равно
       не создаются  }

procedure Delay(DelayTime:Integer);
var TicksNow:Integer;
 begin
  TicksNow:=GetTickCount;
  repeat
   Application.ProcessMessages;
  until GetTickCount-TicksNow>=DelayTime;
 end;

{  Эта процедура приостанавливает линейное выполнение программы на заданное число
  миллисекунд, не прерывая, тем не менее, фоновых процессов.   }

procedure TForm1.WMEraseBkgnd;
begin
 Msg.Result:=1;
 {  В общем-то, мы ничего не сделали в ответ на это сообщение, но
    зато послали отчёт, что всё сделано в лучшем виде. Если это
    будут читать маленькие дети, то пусть они помнят, что обманывать
    всё равно нехорошо, хоть я и показываю плохой пример.  }
end;

procedure TForm1.WMPaint;
var DC:HDC;    //  Контекст устройства. Он нам понадобится целых два раза
    PS:TPaintStruct;  //  А сюда будут записаны те самые ЦУ, которые мы проигнорируем.
    CW,CH,CX,CY:Integer;  //  размеры клиентской части окна
    SL:PRGBArray;  //  Указатель на строку пикселей
    X,Y:Integer;   //  Нужно для организации циклов
 begin
  CW:=ClientWidth;
  CH:=ClientHeight;    //  На всякий случай запоминаем все необходимые размеры.
  CX:=ClientOrigin.X;  //  Может быть, после того, как окно будет спрятано, они изменятся.
  CY:=ClientOrigin.Y;  //  А может, и нет. Проверьте сами, если не лень

  if not Moving then           //  Этот кусок кода не стоит выполнять, когда окно
   begin                       //  перетаскивается пользователем.
    ShowWindow(Handle,SW_Hide);   //  Прячем окно. Кстати, я пробовал не прятать окно,
                                  //  а использовать SetWindowRgn, чтобы вырезать его
                                  //  клиентскую часть. Почему-то не сработало.
                                  //  Что касается этого механизма, то он не будет
                                  //  работать с окнами типа MDIChild, потому что
                                  //  такие окна нельзя спрятать.

    SetActiveWindow(0);  //  Эта строка заслуживает более подробного комментария.
                         //  Когда наше окно прячется, будучи активным, то активным
                         //  становится другое окно. Цвет его заголовка меняется, и
                         //  в результате не выполнена главная задача: сделать так,
                         //  чтобы на экране было всё то же самое, но без нашего окна.
                         //  Поэтому делаем все окна неактивными, и получаем нужный
                         //  результат. Если же наше окно было неактивным, то эта
                         //  строчка никому не мешает (сам не знаю, почему, но факт!)

    Delay(400);    //  Ждём и молимся, чтобы все окна успели перерисоваться!



    DC:=GetDC(0);       //  Получаем контекст рабочего стола

    BitBlt(BM.Canvas.Handle,0,0,BM.Width,BM.Height,DC,0,0,SrcCopy);

    ReleaseDC(0,DC);    //  Больше этот контекст нам не нужен, о чём мы и сообщаем
   end;

  //  Начиная с этого места, код выполняется при любом значении Moving

  BM2.Width:=CW+1;          //  Ну, это даже не интересно рассказывать...
  BM2.Height:=CH+1;         //  Просто готовим картинку к тому, что сейчас будем рисовать
  BM2.PixelFormat:=pf24bit;
  BM2.Canvas.Draw(-CX,-CY,BM);
  for Y:=0 to CH do   //  А в этих циклах на записанный нами кусок экрана
   begin              //  Накладывается светофильтр
    SL:=BM2.ScanLine[Y];
    for X:=0 to CW do
     begin
      SL[X].rgbtRed:=(Transparency*SL[X].rgbtRed+(100-Transparency)*GetRValue(TranspColor)) div 100;
      SL[X].rgbtGreen:=(Transparency*SL[X].rgbtGreen+(100-Transparency)*GetGValue(TranspColor)) div 100;
      SL[X].rgbtBlue:=(Transparency*SL[X].rgbtBlue+(100-Transparency)*GetBValue(TranspColor)) div 100;
      {  Предыдущие три строчки - реализация алгоритма смешения цветов
         Pr:=(Pa*Wa+Pb*Wb)/(Wa+Wb), где Pr - результирующий цвет,
         Pa и Pb - исходные цвета, Wa и Wb - веса этих цветов.
         У нас в качестве Pa берётся цвет пикселя скопированной с экрана картинки,
         В качестве Pb - заранее заданный цвет TranspColor, Wa=Transparency,
         Wb=100-Transparency. Очевидно, что эту операцию необходимо выполнить для
         каждого из основных цветов в отдельности.
         Здесь открывается широкое поле для деятельности. Можно, например, сделать
         Transparency не постоянным, а зависящим от координаты - получится градиентная
         прозрачность. Или можно в качестве Pb взять не фиксированный цвет, а цвет
         пикселя другой картинки - получится окно, фоном которого служит
         полупрозрачная картинка. В конце концов, можно изменить алгоритм смешения
         цветов, и тогда откроются новые возможности.

         Кстати, вот пример градиентной прозрачности:
           SL[X].rgbtRed:=((CH-Y)*SL[X].rgbtRed+Y*GetRValue(TranspColor)) div CH;
           SL[X].rgbtGreen:=((CH-Y)*SL[X].rgbtGreen+Y*GetGValue(TranspColor)) div CH;
           SL[X].rgbtBlue:=((CH-Y)*SL[X].rgbtBlue+Y*GetBValue(TranspColor)) div CH;
         {Хочу добавить, что это смотрится нормально только в режимах True Color.
         High Color для этого недостаточно. А в режимах, худших, чем High Color,
         полупрозрачные окна выглядят страшнее, чем ядерная война.
           }
     end;
   end;

  ShowWindow(Handle,SW_Show);  //  Снова показываем окно

  DC:=BeginPaint(Handle,PS);   //  Получаем разрешение начать перерисовку вместе с ЦУ.
                               //  Кстати, если разобраться с исходниками стандартных
                               //  модулей Delphi, то видно, что их авторы тоже
                               //  проигнорировали все ЦУ. Наводит на размышления...

  BitBlt(DC,0,0,BM2.Width,BM2.Height,BM2.Canvas.Handle,0,0,SrcCopy);  //  Рисуем получившуюся картинку

  Msg.DC:=DC;    //  Эти две строчки учитывают особенности обработки WM_Paint в Delphi.
  inherited;     //  Windows всегда посылает это сообщение с параметром wParam=0.
                 //  Обработчик Delphi сделан так, что он может обрабатывать это
                 //  сообщение при wParam<>0. В этом случае этот параметр интерпретируется
                 //  как дескриптор контекста, BeginPaint и EndPaint не вызываются.
                 //  Это позволяет писать вот такие обработчики.

  EndPaint(Handle,PS);  //  Ну, в общем-то и всё...
 end;

procedure TForm1.WMMove;
begin
 Invalidate;   //  Всё, пора перерисовываться
 inherited
end;

procedure TForm1.WMEnterSizeMove;
begin
 Moving:=True;
 inherited
end;

procedure TForm1.WMExitSizeMove;
begin
 inherited;
 Moving:=False;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 BM:=TBitmap.Create;
 BM.Width:=GetSystemMetrics(SM_CXScreen);     //  Так мы узнаём размеры экрана. В принципе,
 BM.Height:=GetSystemMetrics(SM_CYScreen);    //  если TaskBar виден постоянно, то нам,
                                              //  казалось бы, нужно запоминать несколько
                                              //  меньшую часть экрана. Но окна, не
                                              //  имеющие рамки и заголовка, могут занимать
                                              //  и эту область, а когда они занимают,
                                              //  то и нормальные окна тоже могут
                                              //  покушаться на эту территторию. Так что
                                              //  не будем мелочиться.
 BM.PixelFormat:=pf24bit;
 BM2:=TBitmap.Create;
 Moving:=False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 if ColorDialog1.Execute then
  begin
   TranspColor:=ColorDialog1.Color;
   Invalidate;
  end
end;

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
 Transparency:=SpinEdit1.Value;
 Invalidate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 BM.Free;
 BM2.Free;
end;

end.


Это сообщение отредактировал(а) -Сергей- - 16.8.2003, 07:21
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0609 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.