программирование :: разное

Практическое руководство по компьютерным приколам 8

Доброго времени суток всем читателям “Компьютерной Газеты”, и в частности, этой веселой серии статей, которая уже давно приобрела статус "ты мне, я тебе". Ты мне идею, я тебе — код. Именно на такой бартерной основе происходит в последнее время мое взаимодействие с читателем, что, конечно же, не может не радовать. Сегодня вашему вниманию будет предоставлена очередная порция компьютерных шуток для укрепления собственных сил в программировании на Delphi, а также для укрепления убежденности объекта шутки в том, что нечистая сила и его компьютер имеют нечто синонимичное (читателям в возрасте до 14 лет этого слова можно не запоминать). Я решил снова затронуть тему графических приколов, поскольку прошлая статья оказалась, судя по отзывам, весьма удачной, и подобные идеи имеют право на дальнейшее развитие. На этом лирика закончена, но наша справедливая война только начинается:).

1. Дежавю

Хм, у меня такое ощущение, что где-то я это слово уже слышал:). Так вот, наша задача будет заключаться в том, что компьютер тоже способен испытывать ощущение "дежавю", только он об этом пока что не знает, а следовательно, нужно его этому научить. Представим программу, которая при своем первом запуске запоминает текущую картинку на мониторе, а затем с заданным интервалом исправно возвращает ее обратно на родину — точнее, на монитор. Представили? Тогда принимаемся за работу, пока ваше воображение не нарисовало что-нибудь более вредное. Создаем новый проект, вешаем на форму таймер и задаем ему интервал 10000 (10 сек.). Затем создаем глобальную переменную типа TBitmap:

var
bmp: TBitmap;
Form1: TForm1;

В обработчике создания формы onCreate пишем:

procedure TForm1.FormCreate (Sender: TObject);
var
DC:HDC;
begin
//скрываем форму от посторонних глаз
application.ShowMainForm:=false;
//инициализируем переменную типа tBitmap
bmp:=TBitmap.Create;
//задаем ее размеры равными разрешению экрана
bmp.Height:=Screen.Height;
bmp.Width:=Screen.Width;
//получаем контекст текущего экрана
DC:=GetDC(0);
//копируем картинку экрана в нашу переменную bmp
bitblt(bmp.Canvas.Handle, 0, 0,
Screen.Width, Screen.Height,
DC, 0, 0, SRCCOPY);
end;

После выполнения этого кода в глобальной переменной bmp у нас окажется все, что творилось на экране монитора в момент запуска программы. Осталось исправно обновлять монитор до этого состояния с заданным интервалом времени. В обработчике таймера напишем:

procedure TForm1.Timer1Timer (Sender: TObject);
var
DC: HDC;
begin
//получаем контекст текущего экрана
DC:=GetDC(0);
//меняем его на картинку из переменной bmp
bitblt(dc, 0, 0, Screen.Width, Screen.Height,
bmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

Вот, в принципе, и все. Сразу предупреждаю: шутка далеко не такая безобидная, как кажется на первый взгляд, поскольку, тыкаясь по измененному экрану, вполне можно здорово набедокурить на рабочем столе, поэтому я бы рекомендовал сразу сказать противнику, что у него нервное расстройство, а у его компьютера болезнь Дауна, которая лечится, но, увы, не бесплатно. Затем мы ненавязчиво предлагаем нашу помощь в решении этой проблемы и создаем о себе благоприятное впечатление скромного компьютерного гуру. Результаты работы шутки можно наблюдать на скриншоте. И, поверьте, это еще самое безобидное из того, что может быть на самом деле.



А мы между тем перейдем к следующей шутке.

2. Учимся клеить обои


А что ж вы думали? Надо и этому делу научиться — в хозяйстве пригодится. Скажите спасибо, что обои мы будем клеить виртуальные, а не настоящие. Наверняка многим надоело играться с картинкой экрана, поэтому сейчас мы будем править рабочий стол жертвы. Только посмотрите, какой там бардак. Ну кому нужна эта футуристическая мазня, кроме объекта шутки, слепо считающего, что совокупление совокупляющихся квадратов и ромбов на его рабочем столе — это виртуальный образ одной из ранних картин Пикассо. И даже надпись "Студия Арт-Дизайна имени Васи Непупкина" в левом углу экрана не может его разубедить. Придется заняться больным, ибо, как говорят настоящие врачи: "Нет здоровых пациентов. Бывают необследованные".
Давайте-ка поищем в закромах собственного компьютера картинку на весь рабочий стол с самым неприличным содержанием (например, Билл Гейтс, программирующий под Linux). Итак, картинка найдена (я даже могу с одной попытки угадать ее содержимое:)). Теперь рассмотрим 2 пути замены обоев.

1. Временная замена обоев на рабочем столе. Для этого нам достаточно создать следующую процедуру:

procedure SetWallpaper(st: string);
var p : pchar;
begin
st:=st+#0;
p:=@bitmap[1];
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, p, SPIF_UPDATE INIFILE);
end;

После вызова этой процедуры по таймеру обои на рабочем столе жертвы быстренько сменятся заранее подготовленными. Вызов должен быть следующего вида:

SetWallpaper('c:\mywallpaper.bmp');

Имя файла, указываемое в скобках, должно вести именно к bmp-файлу. Этот способ самый простой и доступный, поэтому... мы, товарищи, пойдем другим путем.

2. Собственно, другим путем — громковато сказано. Его отличие заключается в том, что, помимо обоев, изменения будут внесены в реестр, чтобы при перезагрузке компьютера наш шедевр не пропал даром. Для начала в раздел Uses кода нашей программы добавляем 2 модуля: registry и winprocs (это нужно сделать обязательно). Затем пишем процедуру:

procedure SetWallpaper(fname:String);
var
//переменная для работы с реестром
reg : TRegIniFile;
begin
//инициализация переменной и привязка ее к ветви реестра
reg := TRegIniFile.Create('Control Panel\Desktop' );
with reg do begin
//запись в реестр имени файла с картинкой
WriteString( '', 'Wallpaper',fname );
WriteString('', 'TileWallpaper', '0' );
end;
reg.Free;
//обновление обоев на рабочем столе
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Nil,SPIF_SENDWININICHANGE );
end;

Теперь достаточно в каком-нибудь обработчике onTimer написать:

procedure TForm1.Timer1Timer (Sender: TObject);
begin
SetWallpaper('d:\s1.bmp');
end;

и можно смело наслаждаться эффектом от содеянного. Можно выбросить MessageBox с сообщением о том, что необходимо активировать Windows, или компьютер сгорит в праведном гневе Microsoft, и т.д. Дерзайте.

3. Гляжусь в тебя, как в зеркало...


Скажите, кому-нибудь из вас приходило в голову посмотреть на содержимое экрана монитора, отраженное в зеркале?
Если вы часами сидите с зеркалом и смотрите через него в монитор, дальше можете не читать. Удивительно, как к вам в сумасшедший дом вообще дошла Компьютерная Газета:). Всем остальным рекомендую взглянуть на следующую шутку: зеркальное отображение содержимого экрана. Для начала пишем процедуру:

procedure FlipVertical(var Bitmap: TBitmap);
var
x, y, W, H: Integer;
P1, P2: PRGBTriple;
MP: TRGBTriple;
begin
Bitmap.PixelFormat := pf24Bit;
W := Bitmap.Width — 1;
H := Bitmap.Height — 1;
for y := 0 to H div 2 do
begin
P1 := Bitmap.ScanLine[y];
P2 := Bitmap.ScanLine[H — y];
for x := 0 to W do
begin
MP := P1^;
P1^ := P2^;
P2^ := MP;
Inc(P1);
Inc(P2);
end;
end;
end;

Процедура эта изменяет переданный в нее Bitmap на зеркально отраженный. Осталось только вызвать сам прикол в обработчике таймера:

procedure TForm1. Timer1Timer (Sender: TObject);
var
DC: HDC;
bmp:Tbitmap;
begin
bmp:=TBitmap.Create;
bmp.PixelFormat:=pf24Bit;
bmp.Height:=Screen.Height;
bmp.Width:=Screen.Width;
DC:=GetDC(0);
bitblt(bmp.Canvas.Handle, 0, 0,
Screen.Width, Screen.Height,
DC, 0, 0, SRCCOPY);
flipVertical(bmp);
bitblt(dc, 0, 0, Screen.Width, Screen.Height,
bmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

Подробно останавливаться на объяснении вышеприведенного кода я не буду, поскольку похожими шутками мы занимались в прошлом выпуске этой серии. Результат показан на скриншоте. Впечатляет, не правда ли?



Для поворота по горизонтали нам необходимо создать процедуру flipHorizontal:

procedure FlipHorizontal(var Bitmap: TBitmap);
var
x, y, W, H: Integer;
P1, P2: PRGBTriple;
MP: TRGBTriple;
begin
Bitmap.PixelFormat := pf24Bit;
W := Bitmap.Width — 1;
H := Bitmap.Height — 1;
for y := 0 to H do
begin
P1 := Bitmap.ScanLine[y];
P2 := Bitmap.ScanLine[y];
Inc(P2, W);
for x := 0 to W div 2 do
begin
MP := P1^;
P1^ := P2^;
P2^ := MP;
Inc(P1);
Dec(P2);
end;
end;
end;

Затем пишем в обработчике таймера:

procedure TForm1. Timer1Timer (Sender: TObject);
var
DC: HDC;
bmp:Tbitmap;
begin
bmp:=TBitmap.Create;
bmp.PixelFormat:=pf24Bit;
bmp.Height:=Screen.Height;
bmp.Width:=Screen.Width;
DC:=GetDC(0);
bitblt(bmp.Canvas.Handle, 0, 0,
Screen.Width, Screen.Height,
DC, 0, 0, SRCCOPY);
flipHorizontal(bmp);
bitblt(dc, 0, 0, Screen.Width, Screen.Height,
bmp.Canvas.Handle, 0, 0, SRCCOPY);
end;

и наслаждаемся другой модификацией нашего зеркала:



Так что посмотрим, кто сможет со спокойным лицом вынести подобные издевательства над своим экраном. Я бы не смог, наверное. Теперь можно спокойно брать зеркало, включать наш прикол и с умным видом глядеть в отражение родного экрана.

Ну что ж, на этом выпуск объявляется закрытым. До новых встреч. Пишите письма мелким почерком;).



Паша Либер aka Fireangel, Fireangel@tut.by

© компьютерная газета