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

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

I had a dream... DIR C: 999,937,498,127 bytes free
Так… навеяло…

Да, вы не ошиблись, это снова я с очередной подборкой компьютерных приколов юбилейной пятой серии "Сделай сам и сделай ноги:)", степень полезности которых, несомненно, растет вместе с уровнем знания WinApi у наших читателей, если, конечно, верить письмам с просьбами реализации тех или иных шуточек при помощи двух стандартных устройств, именуемых в народе руки обыкновенные:). Именно ими вам придется воспользоваться для создания очередной порции софтин, заставляющих людей креститься, пугаться и вопить изо всех сил, что в компьютере завелась нечистая сила, наделяющая его мистическими возможностями и несомненной опасностью для окружающих. Итак, концерт по заявкам читателей КГ продолжается, и открывает его виртуальный собеседник…

Поговори хоть ты со мной, гитара семиструнная…
Итак, первым номером нашей импровизированной программы идет старый добрый диалог компьютера с пользователем, или, если уже быть совсем точным, написание универсального драйвера для родной клавиатуры. Причем после внедрения этого драйвера на машину противника вы, несомненно, узнаете о себе много нового, интересного и в совершенно нецензурной форме. Ведь назначение нашей будущей программки так же просто и понятно, как энергетические уровни квантового осциллятора:). Отныне для определенных приложений больше не потребуется участие человека в написании текста, поскольку клавиатура, которая не умеет сама нажимать на свои клавиши — однозначно MustDie, недостойный внимания настоящих шутников. Как вы уже, наверно, и сами догадались, объект нашего изучения — посылка нужных клавиш в заданное окно, ибо нет ничего прекраснее наблюдения за курсором, который самостоятельно выводит слова в Блокноте, оживлением которого мы сейчас и займемся. Запускаем Delphi. Тем, кто споткнулся на этой фразе, я бы советовал почитать серию моих статей от самого начала, ибо описывать одно и то же — труд неблагодарный, а получать письма с жалобами, что приведенный код не работает в Pascal'е или Basic'е, порядком поднадоело, хотя и жутко весело:). Ознакомились? Тогда милости просим дальше. Все, что нам понадобится — формочка и таймер. Интервал срабатывания таймера выставляем в 10000 (10 секунд). В целом это зависит от длины строки, которую мы будем посылать. Для начала определим процедуру непосредственно посылки символа в окно программно, поскольку именно этот вопрос послужил толчком к созданию нижеприведенного прикола:

procedure SendKey(h: Hwnd; key: char);
var nKey, ScanCode, wParam: Word;
lParam, ConvKey: longint;
begin
ConvKey:= OemKeyScan(ord(Key));
ScanCode:= ConvKey and $000000FF or $FF00;
nkey:= ord(key);
wParam:= nKey;
lParam:= longint(ScanCode) shl 16 or 1;
SendMessage(H, WM_KEYDOWN, nkey, lParam);
SendMessage(H, WM_CHAR, nkey, lParam);
lParam:= lParam or $C0000000;
SendMessage(H, WM_KEYUP, nkey, lParam);
end;

На вход ей мы подаем дескриптор окна, куда будет посылаться символ, и непосредственно сам символ. Посылка клавиши осуществляется функцией SendMessage, описания которой нет только в учебнике "Занимательный Фотошоп для чайников". Дескриптор окна Блокнота нам поможет найти знакомая по предыдущим выпускам WinApi функция FindFindow. В случае обнаружения в системе искомого окна при срабатывании таймера маленький цикл посимвольно с интервалом в 200 мс выводит в окно нужную строку, задаваемую в переменной S. В общем, проще показать код:

procedure TForm1.Timer1Timer (Sender: TObject);
var h:HWND;
s: string;
i:integer;
begin
h:=findwindow(nil,'Безымянный — Блокнот');
h:=GetWindow(h, GW_CHILD);
s:='The matrix has you ...'+#13;
if h<> 0 then begin
for i:=1 to length(s) do begin
sendkey(h,s[i]);
sleep(200);
end;end;end;

Достаточно присвоить переменной S свою строку и задать нужный интервал между печатью символов в процедуре-паузе Sleep(). Для получения дескрипторов окон, как правило, достаточно запустить окно и посмотреть на надпись в заголовке окна (это на такой синенькой полосочке:)). Если не верите, запустите Пуск — Программы — Стандартные — Блокнот и убедитесь, что его заголовок будет "Безымянный — Блокнот" (если, конечно, у вас русская версия Windows). Все, что остается — это спрятать окно, обработав событие FormCreate:

procedure TForm1.FormCreate (Sender: TObject);
begin
Application.ShowMainForm:=false;
end;

Кажись, закончили. Конечно, не стоит даже пробовать писать систему управления вашим игроком в Quake3 методом эмуляции нажатий клавиш:), но для простых шуток программа вполне пригодна, особенно если эмулировать случайным образом нажатия управляющих стрелочек в какой-нибудь аркаде. Маленький бонус к сложности и большая неприятность для объекта розыгрыша. Вот вам и домашнее задание, чтобы простым копированием кода не занимались. Это уже серьезная шутка, а не банальное рисование в окне, которое было описано в первой статье о приколах. Если все получилось с первого раза — прекрасно. А если нет, то, как говорится, парашютный спорт не для вас:). Поехали дальше.

И волки сыты, и овцы целы, и пастуху вечная память…
А теперь мы будем заниматься маленькой, но очень полезной иногда пакостью. Копированием текста и последующей его вставкой на новое место наверняка занимались все, кто держит эту газету в руках (кроме тех, кто использует ее не по прямому назначению за неимением рулонов другой бумаги;)), посему обойти нашим драгоценным вниманием буфер обмена бедной Windows было бы просто кощунством. Итак, представьте себе картину, когда человек копирует один текст, а вставляет подготовленный для него заранее другой текст. Итак, как и в прошлый раз, помещаем на форму таймер, вот только интервал его ставим 1 мс. Это чтобы исправно подменялось содержимое буфера. В список подключаемых модулей Uses понадобится добавить модуль Clipbrd для работы с буфером обмена системы. В обработчике таймера пишем:

procedure TForm1.Timer1Timer (Sender: TObject);
begin
Clipboard.SetTextBuf('Зарегистрируйте свой Буфер Обмена :)');
end;

Прячем форму, как это было описано в предыдущем пункте, и наслаждаемся. Теперь при попытке вставки любого объекта благодарный пользователь будет получать строчку с просьбой о регистрации родного буфера или любую другую, заданную вами. Давайте немного усложним задание и сделаем себе фирменную картинку с логотипом, которая будет вставляться где ни попадя вместо исходного объекта. Создайте на форме компонент Image и загрузите в него любую картинку (свойство Picture). Осталось слегка модифицировать код:

procedure TForm1.Timer1Timer (Sender: TObject);
begin
Clipboard.Assign(Image1.Picture.Bitmap);
end;

Предполагается, что картинка ваша хранится в компоненте с названием Image1. Вот теперь сидим и ждем момента заветного нажатия Ctrl+V и последующего появления плаката "Вася Пупкин & Co — хакинг, фрикинг, кардинг и другие страшные слова":). Хотелось бы отметить, что ваша программа будет успешно блокировать импорт/экспорт текста и изображений между любыми приложениями Windows, и даже нажатие PrintScreen и последующая вставка образа экрана приведет всего лишь к появлению вашего логотипа. Вот такая вот занятная программка для будущих спамеров и работников рекламной сферы.

Программа выполнила допустимую операцию, но по привычке будет закрыта…
Вам не кажется, что кнопка минимизации окна и ей подобные сделаны по умолчанию слишком маленькими, чтобы с ними можно было работать комфортно? Печатать наша клавиатура научилась, значит, будем учить и окна сворачиваться абсолютно самостоятельно. Если честно, достает жутко, да и потом: кто сказал, что это не глюк родных форточек. Как говорится, сколько Windows ни ломай, а дядя Билли все равно новую напишет. Вот и решил я набросать по-быстрому для наших читателей небольшую программку, которая по заданному интервалу времени просматривает окна и минимизирует их в панель, на которой расположена заветная кнопка Пуск. Опять же, форма, таймер. Выставляем интервал в 30 секунд, хотя это сугубо ваш выбор, и пишем в обработчике таймера следующий код:

procedure TForm1.Timer1Timer (Sender: TObject);
var
h : HWND;
begin
h := GetWindow(Handle, GW_HWNDFIRST);
while h <> 0 do
begin
if (IsWindowVisible(h) and (GetWindow (h, GW_OWNER) = 0) and (GetParent(h) = 0))
then PostMessage(h, WM_SYSCOMMAND, SC_MINIMIZE, 0);
h := GetWindow(h, GW_HWNDNEXT);
end;
end;

Функция GetWindow с параметром GW_HWNDFIRST получает дескриптор первого найденного окна в системе, эта же функция с параметром GW_ HWNDNEXT — дескриптор следующего окна, и так в цикле до тех пор, пока эти самые окна не закончатся. Каждое окно проверяется на предмет видимости на экране в данный момент и наличие у него родительских/дочерних окон. Затем посылаем сообщение PostMessage, эквивалентное SendMessage, описание которой вы уже знаете в какой книге не нужно искать:), и наслаждаемся полученным эффектом. В качестве теста можно поставить интервал таймера поменьше и открыть побольше окон, а лучше просто взять и поработать с тем же "Вордом" для получения условий, максимально приближенных к боевым. Точно так же можно окна потом обратно восстановить с помощью параметра SC_MAXIMIZE, который нужно передать в PostMessage, но это уже совсем другая история…
Ну что, поморгали окошками? Мило, весело, но, согласитесь, совершенно безобидно. А душа жаждет пакостей покрупнее. Таких, от которых кровь застывает в жилах, на лице выступают капли пота, и руки, трясясь, набирают телефон лаборатории Касперского. Сейчас мы слегка модифицируем вышеприведенную программу до уровня, достойного настоящих программистов. Это трудно описать зрительно и скриншот снять тоже крайне проблематично. Почему, спросите вы и получите исчерпывающий ответ, модифицировав предыдущий обработчик и запустив его на выполнение:

procedure TForm1.Timer1Timer (Sender: TObject);
var
h : HWND;
rgn : HRGN;
begin
h := GetWindow(Handle, GW_HWNDFIRST);
while h <> 0 do
begin
if ((h<> handle) and IsWindowVisible(h) and (GetWindow(h, GW_OWNER) = 0) and (GetParent(h) = 0))
then begin
rgn := CreateEllipticRgn(random(800), random(600),random(800),random(600) );
SetWindowRgn(h,rgn, TRUE);
end;
h := GetWindow(h, GW_HWNDNEXT);
end;
end;

Здесь мы будем использовать такую замечательную вещь, как эллиптические регионы — эллипсы на экране, под которыми будут благополучно видны фрагменты наших окошек. Вот только работать с ними будет крайне проблематично ввиду их чрезмерного непостоянства. Не забудьте спрятать свою форму от глаз недруга с помощью заветного Application.ShowMain Form:=false. Да, чуть не забыл. Присвойте таймеру интервал 500-1000 на ваше усмотрение, и вы сами убедитесь, что есть вещи, которые больше нигде не увидишь, пока не напишешь собственными руками.

"Рекурсия — см. рекурсия" (с) словарная статья
И напоследок я бы хотел остановиться на такой замечательной вещи, как скринсейвер aka заставка. Если у нашего противника он есть, то было бы просто преступлением не изменить слегка интервал времени для его активации. Догадались, что я задумал? Постоянную активацию заставки и игнорирование совершенно наглым образом изменения времени ее запуска в системе. Вешаем на форму таймер и задаем ему любой интервал. Минуту, например (60000). Теперь создадим процедуру, отвечающую за включение непосредственно заставки:

Procedure ScreenSaverOn;
var
b : bool;
begin
if SystemParametersInfo(SPI_GET SCREENSAVEACTIVE,0,@b,0) <> true
then exit;
if not b then exit;
PostMessage(GetDesktopWindow, WM_SYSCOMMAND, SC_SCREENSAVE, 0);
end;

При вызове этой процедуры наша Windows будет на все 100% уверена, что пора включать любимый скринсейвер хозяина, а то, что хозяин уже битый час с пеной у рта проклинает свою систему за своевольство, пытаясь выставить вручную время показа заставки в настройках, ее совершенно не интересует. Чтобы срабатывание происходило через определенный интервал времени, просто обработайте свой таймер:

procedure TForm1.Timer1Timer (Sender: TObject);
begin
ScreenSaverOn;
end;

Запускаем, наслаждаемся… можно заранее принести в подарок веселые картинки с красивыми малоодетыми девушками несомненно легкого поведения и большой стоимости:).
На этом пока все. Дерзайте, пробуйте, учитесь. Главное, помните: от смеха еще никто не умер… кроме тех, кто шутил;). Удачи!

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



Компьютерная газета. Статья была опубликована в номере 17 за 2004 год в рубрике программирование :: разное

©1997-2024 Компьютерная газета