т.е. чтобы моя прога была в нормальном цвете, а все остальное плавно становилось черно-белым, как при пуск->завершение работы
на сайте есть пример scramble.zip, который извращает текущую картинку на мониторе, а как затемнить думаю сам догадаешься
Можно, наверное, создать окно без границ с WS_EX_TOPMOST, развернув на весь экран. Ну, а, дальше, сделать постепенное приравнивание байтов цвета RGB к среднему арифметическому.
tinok Не, так не получиться, будут тормоза и мигание. В XP какой-то хитрый механизм введенный вместе с темами. Кто-нибудь об этом слышал?
На язык кода не кричите. На других языках будет аналогично! Статья отличная с CodeProject. Но сделать можно лучше чем в статье, т.к. там вначале эффект мигания. Итак. Основная идея - создаем другой десктоп, там окно и рисуем по таймеру постепенно засерЯем. Десктоп создается функцией CreateDesktop. Далее вызываем SetThreadDesktop тем самым ассоциируем вызывающий поток с новый десктопом. Теперь все окна созданные данным потоком будут создаваться и выводиться на новом десктопе. Переключение делается функцией SwitchDesktop. Важно тут заметить зачем вообще окно создается на новом десктопе. Можно создать окно неперекрывающееся, вырисовывать его и брать экран и рисовать на его hdc. Это действительно работает, если бы не другие окна которые постоянно лезут наверх и фокус с нашего окна постоянно уходит. Тривиально это решить не удается. Т.о. мы используем другой десктоп и как результат - других окон кроме наших там нет вообще, и еще отключатся разные ненужные в данном случае клавиши - Alt+Tab, Win и другие, потому что их обрабатывают хуки експлорера, а у каждого десктопа свой набор хуков. Далее у нового класса окна делаем стиль CS_SAVEBITS, чтобы лишний раз не перерисовываться, а background устанавливаем в NULL. Таймер создаем в оконной прицедуре. На самом окне рисуем функциями GDI+, засерение предыдущей картинки в памяти также с помощью функций GDI+. Функция LockBits даем возможность менять пиксели картинки, возвращая область памяти с пикселями. Функция UnlockBits копирует измененные пиксели обратно в объект типа Bitmap. Рисуем с помощью ImageDraw как обычно в GDI+. Скрин экрана все знают как получить. Для преобразования обычного TBITMAP, в TGPBITMAP (GDI+) делаем так Код (Text): GpBitmap := TGpBitmap.Create(Bitmap.Handle,Bitmap.Palette); Далее функция одного шага засерения. В GpBitmap - старая картинка. Код (Text): procedure DimBitmap; var BitmapData:TBitmapData; Rect:TGpRect; ScanData:PBYTE; nOffset:integer; red,green,blue:integer; i,j,width,height:integer; begin Rect.X := 0; Rect.Y := 0; Rect.Width := Screen.Width; Rect.Height := Screen.Height; GpBitmap.LockBits(Rect,3,PixelFormat24bppRgb,BitmapData); ScanData := BitmapData.Scan0; nOffset := BitmapData.Stride - GpBitmap.GetWidth()*3; width := GpBitmap.GetWidth; height := GpBitmap.GetHeight; for i:=0 to height-1 do begin for j:=0 to width-1 do begin blue := ScanData^; green := pbyte((dword(ScanData)+1))^; red := pbyte((dword(ScanData)+2))^; case ColorStep of 1: begin ScanData^ := byte(round((0.001 * red + 0.286 * green + 0.713 * blue))); pbyte((dword(ScanData)+1))^ := byte(round((0.001 * red + 0.986 * green + 0.013 * blue))); pbyte((dword(ScanData)+2))^ := byte(round((0.899 * red + 0.087 * green + 0.013 * blue))); end; 2: begin ScanData^ := byte(round((0.099 * red + 0.387 * green + 0.514 * blue))); pbyte((dword(ScanData)+1))^ := byte(round((0.099 * red + 0.887 * green + 0.014 * blue))); pbyte((dword(ScanData)+2))^ := byte(round((0.699 * red + 0.287 * green + 0.013 * blue))); end; 3: begin ScanData^ := byte(round((0.199 * red + 0.487 * green + 0.314 * blue))); pbyte((dword(ScanData)+1))^ := byte(round((0.199 * red + 0.787 * green + 0.014 * blue))); pbyte((dword(ScanData)+2))^ := byte(round((0.499 * red + 0.487 * green + 0.014 * blue))); end; 4: begin ScanData^ := byte(round((0.299 * red + 0.587 * green + 0.114 * blue))); pbyte((dword(ScanData)+1))^ := ScanData^; pbyte((dword(ScanData)+2))^ := ScanData^; end; end; ScanData := pbyte(dword(ScanData) + 3); end; ScanData := pbyte(dword(ScanData) + nOffset); end; end; GpBitmap.UnlockBits(BitmapData); end; Само рисование тривиально. Код (Text): graphics := TGPGraphics.Create(DC); graphics.DrawImage(GpBitmap,0,0); graphics.Free;
Great Нет, окно нужно. Потому как мы над серым фоном собираемся выводить другое окно, а полностью экран мы можем перерисовать имея полноэкранное окно.
Great Вах, отлично. Как узнаешь, что экран похерился окном выше экрана? Или будем перерисоввывать по таймеру? Если есть окно, то есть и WM_PAINT.
А ну это уже смотря как тебе надо сделать затемнение такое. Если надолго - то конечно нужно окно. А если просто нарисовать и забыть, то можно и просто так