И снова здравствуйте, и снова я оброщаюсь за помощью к умным людям. На этот раз задачу я перед собой поставил не простую. Впринцыпе для тех кто видил хоть одним глазком Windows Vista, тот поймёт сразу. Я хочу в моей программе сделать прозрачность и вместе с этим размытие фона, которого видно под прозрачной формой, как это делает Vista на ободке окон. Я сделал это, но по средствам Canvas и можете себе представить, как долго он это делает. Так что я бы хотел услышать Ваши советы по этому поводу: Как это сделать, что бы работало не хуже, чем в Vista?
Вот пример из Vistы: http://programs-desine.narod.ru/Untitled.jpg
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
24-01-2008 08:07
Вам нужна функция DwmIsCompositionEnabled из аэровского апи. На torry есть компонентец AeroGlass, в его исходниках можете глянуть пример работы с этим апи. Сам компонент использовать не рекомендую. Во-первых вызов его функции SetTransparentKey приведет к глюку под вистой. А во-вторых VCL пока не приспособлена для использования в таком режиме.
23-01-2008 11:02 | Комментарий к предыдущим ответам
>>> не сканирует фильмы
А у меня он просто падает с сообщением "Canvas does not allow drawing" при попытке совместить форму Вашей программы с любым проигрывателем: BSplayer, Windows Media Player, FlyTV....
На OnMove и так стоит, а на OnPaint пробовал, ничего не происходит, а при сворачивани можно, но не вижу смысла, всё равно сильно много программа пока не кушает.
Пожалуйста :) Кстати я бы еще отрисовывал по WM_MOVE и на OnPaint. Тогда таймер можно выставить гдето на 250. Ну и при сворачивании его наверно можно отключать.
Torbins, большое спасибо, очень хороший и очень быстрый код размытия. И кстати скачал D2007, установил действительно очень легко делает с Aero в Viste всё что надо, это гораздо упрощает задачу. А в XP у меня осталась только одна проблема:
DeskTop.Handle:=GetWindowDC(GetDesktopWindow); - не сканирует фильмы, вместо них просто чёрный прямоугольник, такой же, как при нажатии клавиши PrtScr.
И вот для всех, кто этого так долго ждал я решил раздать проект в D7, тут всё, чего я смог достич в этом направлении: http://aptypfiles.narod.ru/Aero_in_XP.rar
Буду очень рад, если сможете улучшить или сделать лучше, и надеюсь будете делиться с остальными, потому как это далеко не первый вопрос касающийся Aero в XP, но по моему первый, который получил достойный ответ.
Как бы вы не извращались, если вы будете реализовывать прозрачность в Висте своими средствами, она будет выглядеть убого. Лучше пользоваться средствами самой Висты. Если у вас D2007, то просто поиграйтесь с свойством формы GlassFrame. Ну а если более старшая делфя, то читайте эту статью: http://www.installationexcellence.com/articles/VistaWithDelphi/Original/Index.html особенно рекомендую раздел "Make Your Applications Shine".
Проверил, дествительно как нистранно в Viste такой способ сканирования области экрана не подходит, так как он там уже видит даже полупрозрачные окна и в итоге на зднем фоне программы вообще темнота вместо нужной области. Но как тогда сделать это или может в там уже нет смысла извращяться, как в XP, а воспользоваться средствами Vistы, но я не знаю, буд рад помощи.
20-01-2008 08:01 | Комментарий к предыдущим ответам
Aptyp неплохо получилось :) Но есть пара замечаний. При создании формы попробуйте сделать ей DoubleBuffered:=True, ато сильно мигает. Кроме того данный код не будет работать под Aero. Ну и Scaled:=False тоже не помешает чтобы нижний рисунок никогда за пределы верхнего не выступал.
Вы не поверите, но решение которое я искал всё это время было у меня под носом и было всего в 8 строчек. http://aptypfiles.narod.ru/Project1.exe
Помойму нет ничего проще: всего-то нужно (начиная конечно с Delphi 6) поставить Alphablend:=True, и даже если Value:=255, всё равно при моём способе сканирования экрана нашу прогу не видно и не надо её никуда отодвигать, ни убирать Visible и ничего подобного:
procedure TForm1.Timer2Timer(Sender: TObject);
var DeskTop:TCanvas;
begin
DeskTop := TCanvas.Create;
try
with DeskTop do
Handle := GetWindowDC(GetDesktopWindow);
back.Canvas.CopyRect(Rect(0, 0, Screen.Width, Screen.Height),DeskTop,Rect(Left, Top, Screen.Width+Left, Screen.Height+Top)); //Сдесь вставляем область экрана, находящююся под нашей формой TImage, который растянут на всю форму и находится под всеми остальными контролами
finally
DeskTop.Free;
end;
end;
А по поводу размытия: я его пока убрал, потому как с ним фон обновляется с заметными тормозами.
А Вы не верили. Любуйтесь: http://aptypfiles.narod.ru/Aero_in_XP.rar
Пока не идеально и есть одна значительная не доработка - фон не обновляется, когда программа стоит на месте, только приперемещении, но это всё временно.
В том то и дело, что я задал этот вопрос, что бы сделать красоту как можно удобнее и правильнее, я бы мог и дальше попиксельно извращаться над канвасом, но мне это надоело
28-12-2007 07:32 | Комментарий к предыдущим ответам
>>> тамуша я очень люблю наводить красоту до блеска
Не сочтите за занудство, но я люблю, чтобы программа правильно работала, а внешний вид был удобен, функционален и не тормозил. Размытые грани, скины и прочее - это такая мелочь, которая бросается в глаза, но потом выясняется, что абсолютно неудобна.
Я не успокоюсь пока не разберусь это точно, тамуша я очень люблю наводить красоту до блеска в своих программах.
Вот ещё вопросик, я его так на всякий случай, может кто знает: как сделать вращение рисунков в формате png на форме. У меня есть усовершенствованный tImage он их умеет загружать нормально со всеми альфа-каналами, но я не могу пока ниде найти, как можно над ним издеваться как над простым BitMap.
Вот и здесь тормозить жутко будет. Нет, можно конечно покопатся в томже Windowblinds или во внутренностях Аэро, залезть в исходники какого-нибуть скин пакета... Но если вы и вправду сможете досконально во всем этом разобратся то мой вам до земли поклон :P
Ну так всё-таки возможно, с помощью полно переворота системы, 3D эффектов и давига других штук, вот как это сделать? Я наверное уже достал своей упрямостью, но меня очень раздражает, когда я не могу повторить, то что в других программах считается вообще за семеки. Например я долго искал и ломал голову, как сделать плавный переход от картинки к другой, как это далает даже не то что Vista, а простой Office 2007 даже в Xp очень легко и поломал, конечно не совсем хорошо и на больших картинках и на слабых машинах тормозит, но всё-таки работает!
В Висте это все делает система. Она получает картинку с каждого окошка, выстраивает их в порядке видимости на экране. Потом добавляет аэро рамки и прочие эффекты просчитывая какие области будут частично видны. Потом это все складывается в одну картинку и выводится на экран. Причем производится это все с помощью видеокарты в 3D режиме. В более старых виндах используется намного более простая схема. Есть общий холст на который выводятся все окна. Причем система контролирует только где какую часть окна надо прорисовать. И делается это все в 2D без участия видеокарты. Тоесть в XP нельзя получить изображение рабочего стола, если в это время развернуто другое окно. Просто потому, что он не отрисовывается в это время. В висте же при включенном Аэро такое возможно. Вот поэтому даже если вам и удастся реализовать в старых виндах полное подобие Аэро, то только с большими тормозами.
P.S. Вы можете заметить, что всеже в Windowblinds например это както реализовано. Но: Windowblinds очень глубоко зарывается в систему, всетаки немного подтормаживает, не умеет делать размытие.
А вы хотите чтобы совсем как в Висте? Тогда боюсь без тормозов не получится. Рекомендую остановится на варианте, когда видны только обои. Тем более, что их смену отловить легко.
В висте это поддерживается графическим ядром и выполняется видеокартой. Попробуйте и вы использовать видяху. Кстати ресунок рабочего стола хранится во вполне определенном месте в виде битмапа. Лучше один раз прочитать его, наложить эффект стретч или мозаика и сохранить в памяти.
Randomize;
startTime := GetTickCount;
for y := 0 to BMP.Height - 1 do
for x := 0 to BMP.Width - 1 do
begin
Line := BMP.ScanLine[y];
col := Random(255);
Line[x].B := col;
Line[x].G := col;
Line[x].R := col;
// Line[x].A := col;
end;
endTime := GetTickCount;
Canvas.Draw(0, 0, BMP);
ShowMessage('Executed in ' + IntToStr(endTime - startTime) + ' msec');
BMP.Free;
end;
procedure TMainForm.Button2Click(Sender: TObject);
var
BMP: TBitmap;
y, x: integer;
startTime, endTime: longword;
col: longword;
begin
BMP := TBitmap.Create;
BMP.PixelFormat := pf24bit;
BMP.Width := ClientWidth;
BMP.Height := ClientHeight;
Randomize;
startTime := GetTickCount;
for y := 0 to BMP.Height - 1 do
for x := 0 to BMP.Width - 1 do
begin
col := Random(255);
BMP.Canvas.Pixels[x, y] := col or (col shl 8) or (col shl 16);
end;
endTime := GetTickCount;
Canvas.Draw(0, 0, BMP);
ShowMessage('Executed in ' + IntToStr(endTime - startTime) + ' msec');
BMP.Free;
end;
for x:=0 to bit1.Width-1 do
for y:=0 to bit1.Height-1 do
begin
r:=(GetRValue(bit1.Canvas.Pixels[x,y])*i+GetRValue(bit2.Canvas.Pixels[x,y])*(50-i)) div (50);
g:=(GetGValue(bit1.Canvas.Pixels[x,y])*i+GetGValue(bit2.Canvas.Pixels[x,y])*(50-i)) div (50);
b:=(GetBValue(bit1.Canvas.Pixels[x,y])*i+GetBValue(bit2.Canvas.Pixels[x,y])*(50-i)) div (50);
map.Canvas.Pixels[x,y]:=rgb(r,g,b);
end;
Result:=TBitmap.Create;
Result:=map;
end;
Писал сам ибо ничего более подходящего для меня не нашёл.
Затем размываю, хотя нет, сначала размываю картику с заднего фона:
procedure TForm1.kartinka;
const
d = 2;
var
x, y: integer;
i, j: integer;
r,g,b: integer;
PixR,PixG,PixB: array of array of byte;
begin
move:=False;
PaintDesktop(Form1.Canvas.Handle);
SetLength(Pixr,wd,hg);
SetLength(Pixg,wd,hg);
SetLength(Pixb,wd,hg);
randomize;
with Image2.Canvas do
begin
for y := 0 to hg - 1 do
for x := 0 to wd - 1 do
begin
Pixr[x,y] := GetRValue(Pixels[x,y]);
Pixg[x,y] := GetgValue(Pixels[x,y]);
Pixb[x,y] := GetbValue(Pixels[x,y]);
end;
for y := d to hg - d - 1 do
begin
for x := d to wd - d - 1 do
begin
r := 0;
g := 0;
b := 0;
for i := -d to d do
for j := -d to d do
begin
r := r + Pixr[x+i,y+j];
g := g + Pixg[x+i,y+j];
b := b + Pixb[x+i,y+j];
end;
r := round(r / sqr(2 * d + 1));
g := round(g / sqr(2 * d + 1));
b := round(b / sqr(2 * d + 1));
Pixels[x,y] := RGB(r, g, b);
end;
Application.ProcessMessages;
end;
end;
end;
а потом смешиваю, но не в этом, суть. Он это делает очень медлено, что мне никак не подходит, потому как я хотел бы делать
вот тут я искал им пиксель по всему экрану, в итоге 1 секунду все весь экран, при перетескивании ве равно может тормозать
а что там происходит? у каждого пикселя меняется прозрачность или цвет? http://www.delphikingdom.com/asp/answer.asp?IDAnswer=57804
27-12-2007 03:29 | Вопрос к автору: запрос дополнительной информации
А ты делал через стандартные свойства и методы Canvas, типа Pixels?
Если да, то есть способ в несколько раз ускорить обработку через Canvas, через прямой доступ к памяти. Может здесь поискать, можешь погуглить. Ключевое слово ScanLines
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.