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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Полупрозрачные окна, Не бейте :) 
V
    Опции темы
bems
Дата 14.6.2006, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Хочу поизвращаться с дизайном окна. Я просто замечательно придумал как это должно выглядеть, но не имею понятия как это сделать. Идея такова: полупрзрачное окно неправильной формы. На нем область с другим AlphaBlend, и тоже неправильной формы. и в этой области и в остальной части окна больше чем один цвет. Сделать это нужно только на апи. Подскажите какой-нить изврат, пожалуйста... 


--------------------
Обижено школьников: 8
PM MAIL   Вверх
~FoX~
Дата 14.6.2006, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЕ рыжий!!!
****


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

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



Неправильная форма - работа с регионами.
Полупрозрачность - SetLayeredWindowAttributes
Юзаем поиск и ФАК, темы поднимались не однократно! 


--------------------
user posted image
…множественность никогда не следует полагать без необходимости…
PM MAIL WWW ICQ Jabber   Вверх
bems
Дата 15.6.2006, 00:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Цитата(~FoX~ @  14.6.2006,  13:49 Найти цитируемый пост)
Полупрозрачность - SetLayeredWindowAttributes
Для больше, чем одного значения прозрачности на одном окне, не знаю как преминять. И поиск и MSDN не дают ответа на вопрос.
 


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Snowy
Дата 15.6.2006, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

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



Не. На всё окно одна прозрачность.
А для раздельной ничего стандартного нет.
Тут уже идут глючные извращения. 
PM MAIL   Вверх
Romikgy
Дата 15.6.2006, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

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



bems, имхо нужно создать не одно окно , а несколько smile 


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
bems
Дата 15.6.2006, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Цитата(Romikgy @  15.6.2006,  09:04 Найти цитируемый пост)
 имхо нужно создать не одно окно , а несколько 

да, буду извращаться таким образом.
Цитата(Snowy @  15.6.2006,  08:18 Найти цитируемый пост)
Тут уже идут глючные извращения.  

А как сделать это безглючно?

В большом окне сделаю дырку для маленького. Как сделать чтобы оно всегда оставалось в этой дырке и в Z - порядке всегда было рядом?
WM_WINDOWPOSCHANGED вроде не всегда получаю. Хотя в оконной процедуре у меня не без боков...


  

Это сообщение отредактировал(а) bems - 15.6.2006, 10:23


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Snowy
Дата 15.6.2006, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

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



Цитата(bems @  15.6.2006,  10:20 Найти цитируемый пост)
А как сделать это безглючно?
Этого еще никому не удавалось...
Во всех реализациях имеются свои недостатки...

Цитата(bems @  15.6.2006,  10:20 Найти цитируемый пост)
Как сделать чтобы оно всегда оставалось в этой дырке и в Z - порядке всегда было рядом?
Прибить намертво к десктопу.
Иначе всё равно будет эффект отставания при перетаскивании. 
PM MAIL   Вверх
urix
Дата 15.6.2006, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



можете глянуть это:
http://urixsoft.nm.ru/ru/index.htm?soft-Sc...amp;frameleft_s
и это
http://urixsoft.nm.ru/ru/index.htm?soft-St...amp;frameleft_s

(с исходниками).

Всё нехватает времени засесть за оптимизацию скорости, потому что работает значительно медленнее, чем я предполагаю возможно. Ну, и конечно же - как же без глюков...
(в висте, например, эта реализация не работает, в XP - дефекты, когда друг над другом,...) 
PM MAIL   Вверх
bems
Дата 18.6.2006, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



А вот теперь - ДА!

UpdateLayeredWindow рулит 


--------------------
Обижено школьников: 8
PM MAIL   Вверх
bems
Дата 19.6.2006, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



Цитата(Snowy @  15.6.2006,  08:18 Найти цитируемый пост)
Не. На всё окно одна прозрачность.
А для раздельной ничего стандартного нет.
Тут уже идут глючные извращения.  

Есть функция UpdateLayeredWindow. Но разобраться с ней на 100% не выходит. 
В теории все выглядит так: нужно создать контекст устройства, битмап, выбрать битмап в контекст и в битмап напрямую (не в ДиСи) записывать значения прозрачности для каждой точки. Потом вызвать UpdateLayeredWindow с этим контекстом и общим значением прозрачности для всего окна. Реальная прозрачность в каждой точке должна быть результирующей между индивидуальной и общей. Это в теории.
А на практике:из теории делаю вывод что одинаковое значение прозрачности для каждой точки($30 к примеру) и полная непрозрачность всего окна должны дать тот же результат, что и отсутствующая прозрачность точек со значением $30 для всего окна. Но не сходиться! я написал такой вот код:
Код

program Alpha;
uses windows,messages;

const
 sCaption='UpdateLayeredWindow test program';
 width=500;height=500;
 GWL_LAYEREDDC=0;clBack=$0000FF00;
 PerPixelAlpha=$FF;//прозрачность каждого пикселя
 ConstantAlpha=$30;//прозрачность всего окна

type TRGBA=packed record
           Blue,Green,
           Red,Alpha:byte
           end;//Как RGBQuad, только теперь мы знаем что такое Reserved
     pRGBA=^TRGBA;

function AppWndProc(wnd:HWND;uMsg:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
begin
result:=DefWindowProc(wnd,uMsg,wParam,lParam);
end;

function InitLayeredDC:HDC;
var hBMP:HBITMAP;
    x,y:integer;bi:BITMAPINFO;
    bits:pointer;rgba:pRGBA;
begin
result:=CreateCompatibleDC(0);
bi.bmiHeader.biSize:=SizeOF(bi.bmiHeader);
bi.bmiHeader.biWidth:=width;
bi.bmiHeader.biHeight:=-height;
bi.bmiHeader.biPlanes:=1;
bi.bmiHeader.biBitCount:=32;
bi.bmiHeader.biCompression:=BI_RGB;
bi.bmiHeader.biSizeImage:=0;
bi.bmiHeader.biXPelsPerMeter:=0;
bi.bmiHeader.biYPelsPerMeter:=0;
bi.bmiHeader.biClrUsed:=0;
bi.bmiHeader.biClrImportant:=0;
hBMP:=CreateDIBSection(result,bi,DIB_RGB_COLORS,bits,0,0);
SelectObject(result,hBMP);
SelectObject(result,CreateSolidBrush(clBack));
RoundRect(result,0,0,width-1,height-1,50,50);
for y:=0 to height-1 do
 for x:=0 to width-1 do
  begin
  rgba:=pRGBA(DWORD(bits)+(x+y*width)*4);
  rgba.alpha:=PerPixelAlpha; //у всего окна ставим одинаковою прозрачность
  end;
end;

procedure FreeLayeredDC(DC:HDC);
begin
DeleteDC(DC)
end;

function MonitorWndProc(wnd:HWND;uMsg:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var pt:TPoint;sz:TSize;bf:BLENDFUNCTION;
begin
if (uMsg=WM_SHOWWINDOW) and (wParam<>0)//при появлении
   then begin
        pt.X:=0;pt.Y:=0;
        sz.cx:=width;sz.cy:=height;
        bf.BlendOp:=AC_SRC_OVER;
        bf.BlendFlags:=0;
        bf.AlphaFormat:=AC_SRC_ALPHA;
        bf.SourceConstantAlpha:=ConstantAlpha;//а это работает
        UpdateLayeredWindow(wnd,0,@pt,@sz,GetWindowLong(wnd,GWL_LAYEREDDC),@pt,$FF,@bf,ULW_ALPHA);
        end;
result:=DefWindowProc(wnd,uMsg,wParam,lParam);
case uMsg of
  WM_NCCREATE:SetWindowLong(wnd,GWL_LAYEREDDC,InitLayeredDC);
 WM_NCDESTROY:begin
              FreeLayeredDC(SetWindowLong(wnd,GWL_LAYEREDDC,0));
              PostQuitMessage(0);
              end;
 WM_NCHITTEST:if result=HTCLIENT then result:=HTCAPTION;
end;
end;

function CreateAppWnd:HWND;
var clss:WNDCLASS;
begin
clss.style:=0;
clss.lpfnWndProc:=@AppWndProc;
clss.cbClsExtra:=0;
clss.cbWndExtra:=0;
clss.hInstance:=hInstance;
clss.hIcon:=0;
clss.hCursor:=0;
clss.hbrBackground:=0;
clss.lpszMenuName:=nil;
clss.lpszClassName:=sCaption;
RegisterClass(clss);
result:=CreateWindow(clss.lpszClassName,sCaption,WS_POPUP,0,0,0,0,0,0,clss.hInstance,nil);
end;

function CreateWnd(owner:HWND):HWND;
var clss:WNDCLASS;bmp:BITMAP;
begin
clss.style:=CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW or CS_DBLCLKS;
clss.lpfnWndProc:=@MonitorWndProc;
clss.cbClsExtra:=0;
clss.cbWndExtra:=8;
clss.hInstance:=hInstance;
clss.hIcon:=0;
clss.hCursor:=0;
clss.hbrBackground:=CreateSolidBrush(clBack);
clss.lpszMenuName:=nil;
clss.lpszClassName:=PChar('Monitor');
RegisterClass(clss);
result:=CreateWindowEx(WS_EX_TOPMOST or WS_EX_LAYERED,clss.lpszClassName,
                       sCaption,WS_POPUP or WS_VISIBLE,0,0,width,height,
                       owner,0,clss.hInstance,nil);
end;

var msg:TMSG;
begin
if CreateWnd(CreateAppWnd)<>0
   then while GetMessage(msg,0,0,0) do
              begin
              TranslateMessage(msg);
              DispatchMessage(msg);
              end;
end.
Помогите плиз разобраться.
При значения PerPixelAlpha:=$FF и ConstantAlpha:=$50 все выглядит так как я и ожидал (ничем не лучше и не хуже SetLayeredWindowAttributes). А если поменять эти значения, то картинка почему-то меняется, и у меня складывается впечатление, что откуда-то вмешался в картинку прозрачности какой-то слой белого цвета. 

Давайте вместе что-нить придумаем... 


--------------------
Обижено школьников: 8
PM MAIL   Вверх
urix
Дата 20.6.2006, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



вот, работающий правильно пример: http://www.codeproject.com/gdi/pxalphablend.asp 
PM MAIL   Вверх
Girder
Дата 20.6.2006, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй 2
***


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

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



Код

procedure TForm1.FormCreate(Sender: TObject);
type
    TAlphaTable=Array[0..255] of Byte;
    TRGBAData=Array[0..3] of Byte;
    PRGBAData=^TRGBAData;
var b1,b2,BA:TBitmap;
    BF:TBlendFunction;
    FBmpSize:TSize;
    FBmpTopLeft:TPoint;
    AlphaTable:TAlphaTable;
    pAlphaTable:Array[0..255] of TAlphaTable;
    Lb1,Lb2,LBA:Integer;
    PRGBA,PRGB:PRGBAData;
    PA:PByte;
    A:Byte;
    ReverseA:Boolean;
    i,j:integer;
begin
 for i:=0 to 255 do
  for j:=0 to 255 do pAlphaTable[i,j]:=(j*i) shr 8;
  
 form1.BorderStyle:=bsNone;
 form1.Width:=500;
 form1.Height:=500;
 form1.Position:=poScreenCenter;
 b1:=TBitmap.Create;
 b2:=TBitmap.Create;
 b1.PixelFormat:=pf32Bit;
 b2.PixelFormat:=pf32Bit;

 b1.Width:=form1.Width;
 b1.Height:=form1.Height;
 b2.Width:=form1.Width;
 b2.Height:=form1.Height;

 b1.Canvas.Brush.Color:=0;
 b1.Canvas.FillRect(Rect(0,0,form1.Width,form1.Height));
 b1.Canvas.Brush.Color:=$fff0ff;
 b1.Canvas.RoundRect(10,10,form1.Width-10,form1.Height-10,50,50);
 //b1.SaveToFile('e:\vvv.bmp');

 b2.Canvas.Brush.Color:=$0;
 b2.Canvas.FillRect(Rect(0,0,form1.Width,form1.Height));
 b2.Canvas.Brush.Color:=$40f0ff;
 b2.Canvas.RoundRect(10,10,form1.Width-10,form1.Height-10,50,50);

 b2.Canvas.Brush.Color:=0;
 b2.Canvas.RoundRect(50,50,form1.Width-50,form1.Height-50,10,10);
 b2.PixelFormat:=pf8Bit;
 //b2.SaveToFile('e:\vvv2.bmp');

 SetWindowLong(form1.Handle, GWL_EXSTYLE, GetWindowLong(form1.Handle, GWL_EXSTYLE) or WS_EX_LAYERED);

 BF.BlendOp:=AC_SRC_OVER;
 BF.BlendFlags:=0;
 BF.SourceConstantAlpha:=255;
 BF.AlphaFormat:=AC_SRC_ALPHA;

 FBmpSize.cx := form1.Width;
 FBmpSize.cy := form1.Height;
 FBmpTopLeft := Point(0, 0);

 BA:=TBitmap.Create;
 BA.PixelFormat:=pf32Bit;
 BA.Width:=form1.Width;
 BA.Height:=form1.Height;

 LBA:=DWord(BA.Scanline[1])-DWord(BA.Scanline[0])-(form1.Width shl 2);
 Lb1:=DWord(b1.Scanline[1])-DWord(b1.Scanline[0])-(form1.Width shl 2);
 Lb2:=DWord(b2.Scanline[1])-DWord(b2.Scanline[0])-form1.Width;

 PRGBA:=BA.Scanline[0];
 PRGB:=b1.Scanline[0];
 PA:=b2.Scanline[0];

 ReverseA:=true; //Или False

 for i:=0 to form1.Height-1 do
  begin
   for j:=0 to form1.Width-1 do
    begin
     A:=PA^;
     if ReverseA then A:=not(A);
     AlphaTable:=pAlphaTable[A];

     PRGBA[0]:=AlphaTable[PRGB[0]];
     PRGBA[1]:=AlphaTable[PRGB[1]];
     PRGBA[2]:=AlphaTable[PRGB[2]];
     PRGBA[3]:=A;

     DWord(PRGBA):=DWord(PRGBA)+4;
     DWord(PRGB):=DWord(PRGB)+4;
     DWord(PA):=DWord(PA)+1;
    end;
    DWord(PRGBA):=DWord(PRGBA)+LBA;
    DWord(PRGB):=DWord(PRGB)+Lb1;
    DWord(PA):=DWord(PA)+Lb2;
  end;

 //BA.SaveToFile('e:\vvv3.bmp');
 UpdateLayeredWindow(form1.Handle, 0, nil, @FBmpSize, BA.Canvas.Handle, @FBmpTopLeft, clNone, @BF, ULW_ALPHA);

 BA.Free;
 b1.Free;
 b2.Free;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 ReleaseCapture();
 SendMessage(form1.Handle,WM_NCLBUTTONDOWN, HTCAPTION, 0);
end;


PS: Или ReverseA:=false; 


--------------------
Как слышим, так и пишим.
Истина где-то там...
PM   Вверх
bems
Дата 20.6.2006, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

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



urixGirder, списибо ребята, я уже разобрался. Нагуглил этот пример с codeproject. Весь фокус был в предумноженном цвете (как перевести premultipled?) Я думал так никто и не откликнется.
Спасибо вам еще раз и "+" 


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Wolf
Дата 4.5.2009, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Хм, а теперь как бы на этом всём контролы какие нибуть рисовать? Что-то они не охотно рисуются )
PM MAIL ICQ   Вверх
vovaok
Дата 1.12.2010, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



вот-вот.. я знаю 2 варианта.. рисовать контролы вручную, либо сделать дырку в LayeredWindow а под ней помещать обычную форму с контролами
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

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

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

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

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

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


 




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


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

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