Среди ретро-софта есть отдельный вид, называемый игрушки (toys) в отличие от игр (games). Две игрушки, которые сегодня нашел в своем старом архиве, когда-то во времена MS DOS вызывали бурный восторг, может, и сейчас кого-то повеселят :)
А начинающим будет нескучно решить несколько занимательных задач.
У меня менее древняя реализация для Windows (вплоть до XP SP3) на Delphi-7. Источники, к сожалению, не помню.
Первая игрушка называется Noga. Запускаем exe-файл и видим, как по десктопу идет кто-то невидимый, оставляя следы:
Вторая игрушка Flip – просто переворачивает десктоп:
Устройство очень простое. На стандартую форму помещаем стандартные таймер и список картинок (TimageList). Список содержит картинки ног:
(в программах использован bmp-формат, но в habrastorage.org он недопустим)
Интервал таймера выставляем 1000 мсек., свойство Enabled в True. Исходный код почти тривиальный (задача №1 начинающему – самостоятельно разобраться, как он работает).
unit noga;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ImgList;
type
TForm1 = class(TForm)
Timer1: TTimer;
Image1: TImage;
ImageList1: TImageList;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Image1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
curX,curY,dx, dy : integer;
lBitmap,rBitmap : tbitmap;
procedure prepMainWindow;
procedure drawNogas;
end;
var
Form1: TForm1;
implementation
uses Clipbrd;
{$R *.DFM}
procedure TForm1.prepMainWindow;
var
h,hMem : HDC;
w,cl : HWnd;
xSz,ySz : integer;
bitmap : TBitmap{HBITMAP};
bt : HBITMAP;
begin
// decktop capture
hide;
w := HWND_DESKTOP;
h := GetDeviceContext(w);
xSz := GetDeviceCaps(h,HORZRES);
ySz := GetDeviceCaps(h,VERTRES);
hMem := CreateCompatibleDC (h);
bitmap := TBitmap.Create;
bitmap.width := xSz;
bitmap.height := ySz;
bt := CreateCompatibleBitmap (h,xSz,ySz);
SelectObject (hMem,bt{bitmap.Handle});
StretchBlt (hMem, 0,0, xSz,ySz,
h, 0,0, xSz,ySz, SRCCOPY);
show;
width := xSz;
height := ySz;
bitmap.Handle := bt;
bitmap.HandleType := bmDIB; {(bmDIB, bmDDB)}
Image1.Picture.Graphic := Bitmap;
Bitmap.free;
// Left Noga
lBitmap := TBitmap.Create;
ImageList1.GetBitmap(0,lBitmap);
lBitmap.transparent := true;
// Right Noga
rBitmap := TBitmap.Create;
ImageList1.GetBitmap(1,rBitmap);
rBitmap.transparent := true;
// --------------------
dx := xSz div 2;
dy := ySz div 20;
curX := dx;
curY := ySz -dy;
end;
procedure TForm1.drawNogas;
begin
messageBeep (mb_Ok);
Canvas.draw(curX-lBitmap.width,curY,lBitmap);
curY := curY -2*dy{-lBitmap.height};
Canvas.draw(curX{+lBitmap.width},curY,rBitmap);
curY := curY -4*dy;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
prepMainWindow;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if curY > 0
then
drawNogas
else
Timer1.Enabled := false;
end;
procedure TForm1.Image1Click(Sender: TObject);
begin
Application.Terminate;
end;
end.
Вторая игрушка легко получается из первой:
unit noga;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure Image1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
curX,curY,dx, dy : integer;
lBitmap,rBitmap : tbitmap;
procedure test;
end;
var
Form1: TForm1;
implementation
uses Clipbrd;
{$R *.DFM}
procedure TForm1.test;
var
h,hMem : HDC;
w,cl : HWnd;
xSz,ySz,x,y : integer;
bitmap,bitmap2 : TBitmap{HBITMAP};
bt : HBITMAP;
begin
hide;
screen.cursor := crHourGlass;
w := HWND_DESKTOP;
h := GetDeviceContext(w);
xSz := GetDeviceCaps(h,HORZRES);
ySz := GetDeviceCaps(h,VERTRES);
hMem := CreateCompatibleDC (h);
bitmap := TBitmap.Create;
bitmap.width := xSz;
bitmap.height := ySz;
bt := CreateCompatibleBitmap (h,xSz,ySz);
SelectObject (hMem,bt{bitmap.Handle});
StretchBlt (hMem, 0,0, xSz,ySz,
h, 0,0, xSz,ySz, SRCCOPY);
width := xSz;
height := ySz;
bitmap.Handle := bt;
bitmap.HandleType := bmDIB;
bitmap2 := TBitmap.Create;
bitmap2.width := xSz;
bitmap2.height := ySz;
for y:=1 to ySz do
for x :=1 to xSz do
bitmap2.Canvas.Pixels [x,y]:=
bitmap.Canvas.Pixels [xSz-x+1,ySz-y+1];
Image1.Picture.Graphic := Bitmap2;
show;
screen.cursor := crDefault;
Bitmap.free;
Bitmap2.free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
test;
end;
procedure TForm1.Image1Click(Sender: TObject);
begin
Application.Terminate;
end;
end.
В заключение еще задачки для начинающих.
Задача №2. С последующими ОС (например, Windows 8.1) приведенный код работать не будет. Нужно переделать. Почитать (Гугл в помощь) и подумать о совместимости ОС Windows.
Примечание. Кто хочет попробовать данные игрушки, но не хочет ставить на диск такую «устаревшую» ОС, как Windows XP, — может поставить ее на виртуальную машину.
Задача №3 (можно объединить с предыдущей). ООП Паскаль Delphi-7 всё еще относительно популярен, но сейчас многие предпочитают другие языки. Переведите код на свой любимый язык под любимую IDE.
Примечание. Стиль кода может быть улучшен. Это можно сделать при переводе.
Задача №4. Объедините приведенные программы в одну, т.е. следы должны появляться на перевернутом десктопе.
Задача №5. Если Вы знакомы с программированием под Linux и/или MacOS – попробуйте портировать.
Задача №6. Попробуйте придумать другие забавные игрушки (toys).
Желаю веселого старого Нового года!
Комментарии (16)
maxzh83
11.01.2019 15:44В школе делал что-то подобное (но я бы не назвал это «игрушкой»), программа делала снимок экрана, потом разворачивалась на весь экран поверх всех окон, отображая сделанный снимок. Создавалось впечатление, что компьютер завис.
third112 Автор
11.01.2019 15:51-1ИМХО если есть практическая цель, нпр., сделать снимок экрана, чтобы сохранить его в файл, то это не игрушка, а инструмент. А если цель посмеяться над испуганным товарищем, то игрушка :)
vesper-bot
11.01.2019 16:03На некоторых системах Flip неплохо реализуется шорткатом Ctrl+Alt+Down Arrow. Да ещё и остается интерактивным. Чем не игрушка? :)
OlegIn_Geolog
11.01.2019 16:18У нас в моде была довольно жестокая шутка (не игрушка, хотя можно было и написать простенький код, но проще было руками сделать). Вместо стандартной заставки Screensaver ставилась знаменитая картинка с надписью «Теперь питание компьютера можно отключить». Человек уходил на перекур, чай, кофе, возвращался, видел экран, сильно удивлялся, еще сильнее расстраивался по поводу несохраненных данных, но питание выключал.
yar3333
11.01.2019 16:34Из аналогичного — сделать скрин экрана и поставить его картинкой на рабочий стол. После чего спрятать или удалить иконки с рабочего стола :)
Ableness
11.01.2019 16:40Ноги — скукота, а вот овечки были весьма прелестны lurkmore.to/Screenmates
third112 Автор
11.01.2019 17:19Но! Они в GUI, а я про MS DOS. В Офисе и пресловутого Помощника можно рассматривать, как овечку.
stavinsky
11.01.2019 16:54На старых мониках вообще можно было яркость выкрутить.
А еще есть вот такой сайт. В фул скрине люди пугаются fakeupdate.net
А в целом не понятно к чему этот информационный пост.third112 Автор
11.01.2019 17:03А в целом не понятно к чему этот информационный пост.
К Новому году, Карл :)
TonyLorencio
Все-таки в идеальном случае код вообще не должен быть привязан к IDE.
third112 Автор
Согласен, что в некоторых случаях м.б. принципиально, чтобы код был не привязан к IDE. В других это не имеет значение. Но для начинающего м.б. проще работать с компонентами (таймер, форма, список картинок и т.д.)
(BTW Я и не говорю: привязать код к IDE. Работать можно под разными IDE (если они есть) в одном проекте, сохраняя независимость от них кода).
third112 Автор
TonyLorencio доказательство предъявите?:
А то уж больно нелепо звучит в одной фразе.