...
...

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

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

Привет, Паша. Ты вроде в делфах шариш, у меня вирус принтер повредил, может, знаешь, где драйвер взять? Денис
(Из письма на мой адрес)

Мое почтение всем начинающим и не только начинающим программистам, которые всегда рады повеселить друзей невинными розыгрышами, написанными своими руками. Отгремело эхо сессии, посему с новыми силами я с удовольствием готов продолжать свои маленькие и даже полюбившиеся некоторым заметки (см. КГ №№ 38, 40, 46 за 2003 год). Как и в прошлый раз, описание многих приколов будет по заявкам читателей, так что не стесняйтесь, заказывайте. Ну что ж, поехали!

1. Эту песню не задушишь, не убьешь…
Во всех предыдущих статьях при описании шуток было указано, что для запуска наших веселых программ вместе с системой следует затащить ярлык на нее в Автозагрузку. Поэтому вопросы в большинстве писем читателей разделились на две части: как заставить приложение автоматически прописываться в реестре и… что такое Автозагрузка. Если с первым все более или менее понятно, то второе — удел техподдержки Windows и, следовательно, не будет описано в этой статье. Зачем это нужно? Да, собственно, затем, что после пары-тройки шуток недруг скорее всего вас за свой компьютер вообще пускать перестанет, а если и пустит, то глаз сводить не будет, чтобы вы ничего никуда не закидывали. Тут-то нам и пригодится следующий способ. Запускаем Delphi, дважды кликаем по пустой форме и в обработчике OnCreate пишем:
Application.ShowMainForm:=false;
Всем, кто не читал предыдущие три статьи (как я, например:)), сообщаю, что эта строчка сделает нашу форму невидимой при запуске. Затем в список подключаемых модулей нужно добавить Registry (это, собственно, сам модуль для работы с реестром). Просто допишите это слово после зарезервированного слова Uses. Модифицируем наш OnCreate следующим образом:

procedure TForm1.FormCreate(Sender: TObject);
var
reg: TRegistry;
begin
Application.ShowMainForm:=false;
reg := TRegistry.Create;
reg.RootKey:=HKEY_LOCAL_MACHI NE;
reg.LazyWrite := false;
reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',false);
reg.WriteString('mscv32', Application. ExeName);
reg.CloseKey;
reg.free;
MessageBox(0,'System error in 00FF001AAA','Windows',MB_ICONERROR);
end;

Вот, собственно, и все. Данный код прячет наше основное окно, записывается в реестр по адресу HKEY_LOCAL_MA-CHINE\Software\Microsoft\Windows\CurrentVersion\Run и показывает на экран сообщение о том, что произошла ошибка:
Сообщение об ошибке можно придумать и самому. Главное — фантазия. Все равно в стандартных error'ах ничего не понятно, а чем мы хуже? В автозапуске наша программа будет называться "mscv32". Многолетний опыт написания вир… приколов;) показывает, что чем сложнее и бессмысленнее буквосочетание, тем меньше у пользователя шансов догадаться, что именно за этим прячется. А магическая цифра 32 поклонников Мелкософта вообще повергает в чувство глубокой нирваны и единения с дядей Биллом. Поэтому приносите нашу замечательную программку, запускаете на вражеском компьютере и глядя на сообщение об ошибке с глубокомысленным видом и умным лицом сообщаете другу, что двух Гб оперативной памяти на его компьютере совершенно недостаточно для запуска вашего свеженаписанного творения:). В случае обнаружения противником в реестре подозрительного объекта, валите все на новую модификацию вируса MyDoom.C и требуйте вознаграждение за своевременное спасение компьютера от неминуемой смерти.

2. Черна…Беля…Черна…Беля… (команда КВН РУДН)…
Давным-давно, когда мышки были квадратными, а мониторы — черно-белыми, проблема частоты обновления экрана не так волновала общественность, как в наши дни. За своим старым черно-белым ATI на 60 Гц мои глаза уставали гораздо меньше, чем на цветном при 85 Гц. Все было как-то размерено, неторопливо. Вот и решил я спасти глаза читателя и попутно попугать его врагов следующей шуткой. К сожалению, разработчики Windows не предусмотрели явной эмуляции черно-белого монитора, посему этим мы сейчас с вами и займемся. Нет более простого способа убедить человека в том, что у него испорчен монитор, чем нижеприведенный:). Для начала описываем небольшую функцию:

function coltogray(RGBColor : TColor) : TColor;
var Gray : byte;
begin
Gray := Round((0.30 * GetRValue (RGBColor)) +
(0.59 * GetGValue(RGBColor)) +
(0.11 * GetBValue(RGBColor )));
Result := RGB(Gray, Gray, Gray);
end;

На вход ей подается любой цвет (переменная типа TColor), а на выходе мы получаем этот цвет в оттенках серого. Далее все просто, как наша жизнь. В обработчике FormCreate скрываем нашу форму (описано в пункте выше). Вешаем на кнопку таймер, ставим его интервал =300000 (5 минут) и в обработчике пишем:

procedure TForm1.Timer1Timer(Sender: TObject);
var i,k:integer;
c,c1:TCOLOR;
dc:HDC;
begin
dc:=GetDC(0);
for i:=1 to screen.Width do begin
for k:=1 to screen.Height do begin
c1:=GetPixel(dc,i,k);
Setpixel(dc,i,k,coltogray(c1));
end;end;
end;

Через 5 минут изображение на экране постепенно слева направо окрасится в серый цвет. И так каждое срабатывание таймера. Причем цвет иконок, кнопок и т.д. будет возвращаться только если по ним пройтись курсором мышки. Можно еще больше усложнить шутку и закрашивать экран полосками. Это в конец убедит опротивника в том, что монитор его срочно нужно выбрасывать, ну или, на худой конец, подарить вам. Ставим интервал таймера в 1 и в обработчике пишем:

procedure TForm1.Timer1Timer(Sender: TObject);
var i,k,m:integer;
c,c1:TCOLOR;
dc:HDC;
begin
dc:=GetDC(0);
i:1=random(screen.Width)-200;
k:=random(screen.Height);
for m:=i to i+200 do begin
c1:=GetPixel(dc,m,k);
Setpixel(dc,m,k,coltogray(c1));
end;
end;

Функция coltogray () естественно должна быть описана выше. Попробуйте сами поэкспериментировать с цветом и коэффициентами в функции. Эффект довольно любопытный. А объединение с кодом автозагрузки программы, описанной в первом пункте, превращает нашу маленькую шутку в довольно убойное оружие средне-серого действия.

3. Нажми на кнопку, получишь результат…
Каждый из нас видел кнопки, затененные серым цветом, на которые нельзя нажать. А вот кто из вас видел в таком плачевно-беспомощном состоянии кнопку "Пуск"? Вот и ваш противник тоже наверняка даже не подозревает о существовании такой "недокументированной фичи". Ничего, сейчас мы его в этом переубедим. Точнее, поставим перед фактом. Кода-то кот наплакал:

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.ShowMainForm:=false;
EnableWindow(FindWindowEx(Find Window('Shell_TrayWnd', nil),0,'Button', nil),false);
end;

Как видно, мы снова используем обработчик FormCreate для сокрытия нашей формы и запрета кнопки Пуск. Соответственно для разрешения ее процедура Enable- Window должна выглядеть так:

EnableWindow(FindWindowEx(FindWindow('Shell_TrayWnd', nil),0,'Button', nil),true);

Следующий эффект будет не очень сильно похож на прикол, но, думаю, вам он понравится. Не каждый день на кнопке Пуск проскралливается твое великое имя. Начало стандартное. Прячем форму, вешаем таймер, ставим его интервал=300 и пишем (код представлен с обработчиком FormCreate):

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.ShowMainForm:=false;
end;
procedure TForm1.Timer1Timer(Sen der: TObject);
var d:integer;
st,ff:string;
but:HWND;
begin
st:=' Fireangel ';
but:=FindWindowEx(FindWindow ('Shell_TrayWnd',nil),0,'Button',nil);
if (i+k)<length(st) then
i:=i+1
else
i:=0;
ff:=''; setlength(ff,k);
for d:=0 to k do ff[d]:=st[i+d];
SendMessage(but,WM_SETTEXT,0, lparam(ff));
end;

Заметьте, что в строке ' Fireangel ' 4 пробела слева и справа от слова. Вам тоже обязательно нужно их ставить перед своим. Затем запускаете и наслаждаетесь. И помните: у вас нет мании величия… великие люди этим не страдают;).

4. Позвони мне, позвони…
Приколы — это, конечно, хорошо. Но вот приколы по сети, особенно если 2 машины расположены недалеко друг от друга — истинное удовольствие, ибо нет ничего приятнее, чем воочию убедиться в реакции друга, степени квадратности его глаз и падения челюсти при виде системных сообщений, любезно составленных для него вами. Все, что для этого понадобится — знать IP машины, которая подвергнется нашей психической атаке (как матросы на зебрах:)). Приложение наше будет основано на такой замечательной вещи, как клиент-сервер. Сперва пара слов о том, что же это за зверь такой и для чего он может нам пригодиться. Проект будет состоять фактически из двух разрозненных программ. Первая — сервер — должна быть запущена на машине, которой будут посылаться сообщения. Вторая — клиент — будет соединяться с первой по сети и слать эти самые сообщения. Получается эдакий однобокий чат. А для пущей убедительности мы сделаем так, чтобы фразы, приходящие от клиента серверу, поступали на экран к жертве в виде уже знакомого окошка с ошибкой Windwos. Т.е. для сервера должны выполняться следующие требования:
— автозагрузка с системой
— невидимость на экране
— отображение сообщения на экран при его приходе извне.
Изготовлением первой части мы сейчас и займемся. Запускаем Delphi и помещаем на форму компонент ServerSocket с вкладки Internet палитры компонентов:
Больше нам ничего не понадобится. Все, что нужно дополнительно указать, так это порт, через который будут связываться наши программы. Я задавал 7766. Берите что-нибудь похожее больше 5000 — не ошибетесь. Кликаем дважды по нашей форме и в обработчике пишем:

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.ShowMainForm:=false;
ServerSocket1.Port:=7766;
ServerSocket1.Active:=true;
end;

Этим кодом мы прячем главную форму, устанавливаем порт (его можно изменять, но главное — чтобы у клиента и сервера значения port были одинаковы) и активируем наш сервер. Теперь он висит в памяти в непрерывном ожидании сообщения от клиента. В качестве домашнего задания модифицируйте этот код так, чтобы при запуске сервер прописывал себя на автозагрузку системы. Сделать это легко, если вы внимательно ознакомились с первым пунктом данной статьи. Теперь займемся самим обработчиком сообщений. Выделяем на форме наш компонент ServerSocket и на вкладке Events инспектора объектов дважды кликаем по свойству OnClienRead:

procedure TForm1.ServerSocket1 ClientRead(Sender: TObject;Socket: TCustomWinSocket);
begin
MessageBox(0,PCHAR(Socket.ReceiveText),"Windows XP", MB_ICONERROR);
end;

Как видим, на экран выбрасывается окно с заголовком "Windows XP", содержащее строку, пришедшую к нам от клиента в переменной Socket. ReceiveText.
Если с написанием сервера все довольно просто, то создание клиента потребует немного больше времени. Как-никак это ваше основное оружие:). Создаем новый проект и помещаем на форму два Edit'а, две кнопки Button и компонент ClientSocket с вкладки Internet палитры компонентов:
Для начала заведем глобальную переменную булевского типа, которая будет устанавливаться в true при удачном соединении с сервером.

var
Form1: TForm1;
isconnect:boolean=false;

В первом поле должен быть введен IP-адрес машины, на которой должен быть запущен сервер. При нажатии на кнопку Button1 пробуем соединиться:

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address:=Edit1.Text;
ClientSocket1.Port:=7766;
ClientSocket1.Active:=true;
end;

Не забудьте, что перед нажатием на кнопку нужно ввести в поле Edit1 IP-адрес машины противника вида "xxx. xxx.xxx.xxx" (без кавычек), и у клиента и работающего сервера должны совпадать номера порта (в данном случае 7766). Для отслеживания удачного соединения или не менее удачного разъединения выделите Client Socket и в событиях управляйте свойствами OnConnect и OnDisconnect соответственно:

procedure TForm1.ClientSocket1 Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage('Соединение успешное!');
isconnect:=true;
end;

procedure TForm1.ClientSocket1 Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage('Соединение разорвано сервером!');
isconnect:=false;
end;

В случае успешного или неуспешного соединения с сервером мы получим соответствующее сообщение. Осталось только в поле Edit2 ввести нужный текст и нажать Button2:

procedure TForm1.Button2Click(Sender: TObject);
begin
if isconnect then
ClientSocket1.Socket.SendText(edit2. text)
else ShowMessage('Нет соединения!');
end;

Если IP был введен правильно, и на удаленной машине запущен ваш сервер, написанное сообщение соответствующим образом отобразится на экране монитора ничего не подозревающего противника. Для теста правильной работы программы вовсе не обязательно наличие сети.
Все это можно сделать и у себя дома, поскольку хорошая шутка должна быть тщательно отработана и подготовлена. Просто запустите сервер (проверьте, висит ли он в процессах, так как визуально работа сервера на экране не отображается). Затем запустите клиент и в поле ввода IP введите "127.0.0.1". Это так называемый локальный адрес, который позволяет компьютеру соединяться самому с собой.
При нажатии на кнопку у вас должно выскочить сообщение об успешном соединении. Если оно появилось, значит, все было сделано правильно. Теперь можете смело набирать сообщение и посылать его самому себе, нажав Button2.

На этом пока все. Присылайте свои заявки на мой адрес, и, вполне возможно, вы найдете реализацию своей идеи просто в очередном купленном номере КГ.

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


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

полезные ссылки
IP камеры видеонаблюдения
Корпусные камеры видеонаблюдения