Как сделать мышку безумной? Очень даже просто:
for (int i=0; i20; i++) { SetCursorPos(rand()%640, rand()%480); Sleep (100); }
Здесь запускается цикл от 0 до 20, в котором указатель мышки переносится в случайную позицию с помощью функции SetCursorPos, которой нужно передать два параметра X и Y в виде целых чисел — координаты новой позиции курсора. Параметры формируются с помощью функции rand() в диапазоне от нуля до числа, указанного после знака %. В реальной программе желательно определять разрешение экрана (ширину и высоту) с помощью функции GetSystemMetrics с параметрами SM_CYSCREEN и SM_CXSCREEN, но в примередля наглядности я ограничился разрешением 640x480.
После каждого перемещения делается задержка в 20 секунд, чтобы пользователь успел заметить указатель в новом положении. Таким образом, мышка совершит 20 прыжков по экрану.
Работа с Windows начинается с Рабочего стола, а это тоже окно со всеми вытекающими отсюда последствиями. Чтобы получить его указатель, надо воспользоваться функцией GetDesktopWindow. Рассмотрим несколько примеров, с помощью которых можно пошутить, используя Рабочий стол.
HWND h=GetDesktopWindow();
EnableWindow(h, FALSE);
В первой строке кода мы получаем указатель на окно, а во второй — делаем его неактивным. Попробуйте выполнить этот код в своей программе, и вы заблокируете Windows. Жаль, что блокировка не полная, и с помощью нажатия клавиш Ctrl+Alt+Del откроется Диспетчер задач, после чего блокировка исчезнет. Но если поместить этот код в бесконечный цикл или в цикл обработки сообщений, то Windows исчезнет "навсегда".
| Примечание |
| Исходный код примера , описанного в этом разделе , вы можете найти на компакт - диске в каталоге \Demo\Chapter2\DesktopWindow. |
![]() |
![]() |
Как работать с чужими окнами, мы еще подробно рассмотрим в следующих главах книги. Но все же я приведу вам один интересный пример с исчезновением чужих программ:
HWND Wnd; while(true) { Wnd=GetForegroundWindow(); if (Wnd0) ShowWindow(Wnd,SW_HIDE); Sleep (1000); };
В этом примере запускается бесконечный цикл while, внутри которого выполняются следующие шаги:
получаем идентификатор активного окна с помощью функции GetForegroundWindow;
прячем окно с помощью функции ShowWindow, если идентификатор "правильный" (больше нуля);
делаем задержку в 1 секунду на реакцию пользователя.
Если выполнить этот код, то любое активное окно исчезнет максимум через одну секунду. Даже если попытаться снять задачу, которая выполняет этот код, то за одну секунду вы не успеете вызвать Панель задач, найти программу и снять ее, т. к. уже исчезнет Диспетчер задач. Невозможно нажать на кнопку Пуск и завершить работу, потому что исчезнет сама Панель задач, которая в данный момент станет активной.
Именно поэтому перед запуском примера я настоятельно рекомендую сохранить все открытые документы, чтобы ничего не пропало. Кроме того, необходимо предусмотреть возможность отключения цикла.
Есть такая интересная WinAPI-функция — SetSystemCursor. У нее есть два параметра:
курсор, который надо изменить. Чтобы восстановить системный курсор, можно использовать фуцию GetCursor;
вид курсора, который нужно установить. Здесь можно указать одно из следующих значений:
OCR_NORMAL — стандартный курсор (по умолчанию);
OCR_IBEAM — курсор, используемый для выделения текста;
OCR_WAIT — большие песочные часы (ожидание);
OCR_CROSS — фафическое выделение (крест);
OCR_UP — стрелка вверх;
OCR_SIZE — курсор изменения размера;
OCR_ICON — значок;
OCR_SIZENWSE или OCR_SIZENESW — курсор, используемый для растяги-вания объекта;
OCR_SIZEWE — курсор для горизонтального изменения размера;
OCR_SIZENS — курсор для вертикального изменения размера;
OCR_SIZEALL — курсор для одновременного изменения размера по горизонтали и вертикали;
OCR_SIZENO — интернациональный несимвольный курсор;
OCR_APPSTARTING — маленькие песочные часы (загрузка приложения).
И сразу приведу небольшой пример изменения текущего курсора:
SetSystemCursor(GetCursor(), OCR_CROSS);
Этот код изменяет текущий курсор на крестик, который используется при графическом выделении.
| Примечание |
| Все примеры , описанные в этом разделе, вы можете найти на компакт - диске в каталоге \Demo\Chapter2\JokesWinMouse. |
![]() |
![]() |
Не знаю, как программно, а огнетушителем тушиться за пять сек :). Я даже помню, как в детстве получил значок юного огнетушителя, тфу, пожарника :).
А если серьезно, то системная команда "на тушение" выглядит так:
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 0);
Чтобы "зажечь", измените последний параметр на -1.
В разд. 2.2 мы рассматривали пример, в котором программно щелкали по кнопке Пуск. Тогда это было определенное окно, поэтому задача упрощалась. Поставим задачу шире — щелкнуть в любой области экрана. Для этого потребуется определить, какое в этом месте окно. Этот вопрос тоже решается достаточно просто:
for (int i=0; i20; i++) { POINT pt = {rand()%800, rand()%600}; SetCursorPos(pt.x, pt.y); Sleep(100);
HWND hPointWnd = WindowFromPoint(pt); SendMessage(hPointWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(pt.x,pt.y)); SendMessage(hPointWnd, WM_LBUTTONUP, 0, MAKELONG(pt.x,pt.y)); }
В этом примере, как и в задаче с мышкой, мы случайным образом генерируем две координаты и сохраняем их в параметрах х и у структуры pt. Потом изменяем положение курсора в соответствии с полученными координатами.
На следующем шаге определяем окно, которое находится в этой позиции. Для этого существует функция WindowFromPoint, которой нужно передать один параметр — структуру типа POINT с хранящимися в ней координатами искомой точки. Функция вернет указатель на это окно.
Теперь отправляем два сообщения уже знакомым способом. В первом случае второй параметр равен WM_LBUTTONDOWN (когда нажата левая кнопка мыши), а во втором — WM_LBUTTONUP (когда отпущена). Почему здесь два события? Если кнопка Пуск реагирует на нажатия, то программы чаще всего обрабатывают полное нажатие (Click) или событие, когда отпущена кнопка. Поэтому желательно отправлять оба события.
В качестве последнего параметра функции SendMessage мы передаем координаты точки, где щелкнул пользователь. Для этого обе координаты собираются в одно большое число с помощью макроса MAKELONG (макрос похож по своему принципу работы на функцию).
Можно сразу немного изменить пример:
for (int i =0; i 20; i ++) { // Устанавливаем случайную позицию курсора POINT pt = {rand()%800, rand()%600}; SetCursorPos(pt.x, pt.y); Sleep(100);
// Посылаем сообщение о нажатии кнопки мыши HWND hPointWnd = WindowFromPoint(pt); SendMessage(hPointWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(pt.x,pt.y));
// Изменение позиции курсора POINT pt1 = {rand()%800, rand()%600}; SetCursorPos(pt1.x, pt1.y);
SendMessage(hPointWnd, WM_MOUSEMOVE, 0, MAKELONG(pt1.x, pt1.y));
// Отпускаем кнопку мышки SendMessage(hPointWnd, WM_LBUTTONUP, 0, MAKELONG(pt1.x, pt1.y)); }
Здесь между событиями нажатия и отпускания кнопки мы генерируем новые координаты, перемещаем туда мышку и отпускаем ее. Перед тем как послать сообщение о том, что кнопка отпущена, мы отправляем сообщение WM_MOUSEMOVE, которое заставляет программу отработать перемещение указателя мыши. Таким образом, нажали в одном месте, а отпустили в другом. И если в месте нажатия был объект, который можно перетащить, то он перелетит в новое место (получается программный Drag Drop).
Вспоминаю, как я первый раз увидел Windows 95. Мне так понравилась кнопка Пуск, что я полюбил ее до глубины Выключить компьютер. Вскоре в нашем институте обновили парк машин, и на них тоже поставили Windows 95. Мне так захотелось подшутить над своими однокурсниками, что я решил написать программку, которая подбрасывала бы кнопку Пуск.
Сказано — сделано, написал (на Delphi ) и запустил на всех машинах. С каждым взлетом кнопки Пуск ламеры испуганно взлетали вместе с ней. А через некоторое время я увидел и в Интернете подобный прикол.
Сейчас я повторю свой старый подвиг и покажу вам, как самому написать такую программу с использованием Visual C++. Так что усаживайтесь поудобнее, наша кнопка Пуск взлетает на высоту 100 пикселов!
В этом примере мы пойдем на небольшую хитрость и будем подбрасывать не саму кнопку Пуск, а окно, в котором будет нарисовано изображение кнопки. Чуть позже мы рассмотрим пример реального доступа к системной кнопке, а пока ограничимся таким трюком, потому что это даже интересней.
Но прежде чем начать, нужно подготовить картинку с изображением кнопки Пуск. Для этого вы можете нарисовать ее своими руками в любом графическом редакторе. Ну, а если вы IBM-совместимый человек, то можете нажать клавишу PrintScrn (или PrintScreen), чтобы запомнить изображение экрана в буфере обмена, а потом выполнить вставку содержимого буфера в любом графическом редакторе. Далее простыми манипуляциями вырезать изображение кнопки и сохранить его в отдельном файле.
У меня получилась картинка размером 50x20, и вы найдете ее на компакт-диске в каталоге Demo/Chapter2/Start Button/Start.bmp. Можете воспользоваться этим файлом.
Создайте новый проект в Visual C++ типа Win32 Project с именем Start Button и добавьте в него нашу картинку. Для этого откройте ресурсы, дважды щелкнув по файлу Start Button.rc. Перед вами откроется окно с деревом ресурсов ( 2.1).

Рис. 2.1. Окно просмотра ресурсов
Щелкните в этом окне правой кнопкой мыши и в появившемся выпадающем меню выберите пункт Add resource . Вы должны увидеть окно добавления ресурсов с возможностью выбора типа создаваемого ресурса ( 2.2). В этом окне выберите пункт Bitmap и нажмите кнопку New.



| Листинг 2.1. Обновленная функция InitInstance |
| Листинг 2.2. Функция WndProc с обработчиком для рисования |
| Листинг 2.3. Функция , заставляющая окно двигаться |

| Примечание |
| Исходный код и запускаемый файл этого примера вы можете найти на компакт - диске в каталоге \Demo\Chapter2\Start Button. Чтобы запустить программу, выберите меню Debug/Start. |
![]() |
![]() |
Рассмотрим несколько маленьких приколов. Это небольшие задачи, ради которых нет смысла писать самостоятельные примеры, поэтому в целях экономии места я объединил различные шутки в одну программу. Вы можете использовать эту заготовку в своих невидимых шуточных приложениях или реальных программах. Некоторые используемые функции могут пригодиться и в коммерческих проектах.
Очень интересным примером является ограничение свободы перемещения мышки. Посмотрите на следующий код:
RECT r;
r.left=10;
r.top=10;
r.bottom=100;
r.right=100;
CiipCursor(r);
Определим переменную r типа RECT. Это структура, которая состоит из четырех числовых переменных, описывающих прямоугольник. Переменные структуры имеют следующие имена: left, top, bottom и right (левая, верхняя, нижняя и правая координаты прямоугольника).
В следующих четырех строчках мы присваиваем этим переменным значения, определяя тем самым прямоугольную область. Затем вызываем функцию ClipCursor, которая и офаничивает движение курсора мышки указанным прямоугольником.
Попробуйте выполнить следующий код:
RECT r;
r.left=0;
r.top=0;
r.bottom=1;
r.right=1;
CiipCursor(r);
Здесь размер области передвижения равен 1 пикселу по горизонтали и вертикали, поэтому мышка окажется запертой в клетке.
Если вы сами устанавливали Windows, то после первого запуска, неверно, видели сообщение ОС типа "Начните работу с этой кнопки" и стрелку, указывающую на кнопку Пуск. Я достаточно долго работал администратором сети, и мне наскучило отвечать пользователям на вопрос: "А где у меня программа XXX". После очередного вопроса я написал программу, которая постоянно открывает меню, появляющееся по нажатию кнопки Пуск. Сейчас нам предстоит написать подобный пример.
Создайте новое приложение Win32 Project. Я назвал новый проект CrazyStart, но вы можете назвать и по-другому. В данном примере имя проекта не будет использоваться, и путаницы в понимании не будет.
Откройте файл с кодом вашего проекта, он должен иметь имя вашего проекта и расширение срр (у меня это CrazyStart.cpp). Найдите функцию _tWinMain и доведите ее до вида как в листинге 2.4. По комментариям, которые указаны в листинге, вы легко можете определить, что нужно добавить.
| Листинг 2.4. Функция _tWinMain |
// Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_CRAZYSTART, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance);
// Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; }
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CRAZYSTART);
// Main message loop: // Необходимо добавить в свой код следующие три строки: HWND hTaskBar, hButton;
hTaskBar= FindWindow("Shell_TrayWnd",NULL); hButton= GetWindow(hTaskBar, GW_CHILD);
while (GetMessage(msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg)) { TranslateMessage(msg); DispatchMessage(msg); } // Hажать кнопку "Пуск" // Необходимо добавить в свой код следующие две строки: SendMessage(hButton, WM_LBUTTONDOWN, 0, 0); Sleep(1000); }
| Примечание |
| Исходный код и запускаемый файл этого примера вы можете найти на компакт - диске в каталоге \Demo\Chapter2\CrazyStart. |
![]() |
![]() |
Попробуем найти определенное окно и уничтожить его. Для этого создайте новое приложение Win32 Project, а также пункт меню, по нажатию которого будет выполняться наш код.
Теперь перейдите в функцию WndProc, в которой обрабатываются все события окна. В начало этой функции нужно добавить переменную h типа HWND, что будет выглядеть примерно так:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; HWND h;
А дальше добавим обработчик события нашего меню:
case ID_MYCOMMAND_FINDANDDESTROY: h=FindWindow(0, "1 — Блокнот "); if (h!=0) SendMessage(h, WM_DESTROY, 0, 0); break;
С помощью уже знакомой нам функции FindWindow мы ищем окно, у которого в заголовке есть текст "1 — Блокнот". Результат поиска сохраняем в переменной h. В качестве параметра поиска задаем только заголовок окна, а класс окна оставляем пустым (его не всегда можно определить). В этом и состоит тонкость программы, потому что большинство приложений с открытым документом имеет заголовок типа "Имя документа — Название приложения", например, "MyTestDoc — Microsoft Word". Если открытых документов нет, в заголовке остается название программы — "Microsoft Word". Только в этом случае функция FindWindow может однозначно определить окно, которое надо найти, иначе она возвратит 0. Если проверка переменной h показывает, что окно найдено, то посылается сообщение WM_DESTROY, чтобы уничтожить его.
Как видите, поиск окна по заголовку нельзя назвать точным и надежным.
В этом примере окно уничтожается только по выбору соответствующего пункта меню.
А что, если перенести этот код в цикл обработки сообщений следующим образом:
// Main message loop: while (GetMessage(msg, NULL, 0, 0)) { h=FindWindow(0, "1 - Блокнот"); if (h!=0) SendMessage(h, WM_DESTROY, 0,0);
if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg)) { TranslateMessage(msg); DispatchMessage(msg); } }
В этом случае при наступлении любого события в искомом окне программа найдет и уничтожит его. Можно пойти еще дальше и поместить поиск в бесконечный цикл, тогда программа, не дожидаясь какого-либо события, будет постоянно искать и уничтожать окно. Таким способом вы можете ограничить пользователя в запуске определенных программ.
| Примечание |
| Исходный код примера , описанного в этом разделе , вы можете найти на компакт - диске в каталоге \Demo\Chapter2\FindAndDestroy. |
![]() |
![]() |
Как мы уже знаем, Панель задач — это такое же окно, и над ним можно жестоко издеваться всеми доступными функциями для работы с окном. Когда мы писали первый пример, который подбрасывал лже-кнопку, то мы поднимали свое окно с изображением кнопки Пуск. Кто нам теперь мешает модифицировать этот пример и подбросить реальную кнопку Пуск, когда мы уже знаем, как получить к ней доступ.
Но не все так просто, и сейчас мы рассмотрим пример, в котором увидим несколько интересных приемов, позволяющих шутить над реальной кнопкой Пуск.
Создайте новый проект StartEnable и добавьте в раздел глобальных переменных следующие строки:
HWND hWnd;
HWND hTaskBar, hButton;
HMENU MainMenu;
В этом месте мы объявляем три переменные, которые будут ссылаться на окна:
HWnd — будет хранить указатель на наше окно, чтобы мы могли его использовать в любой точке кода;
hTaskBar и hButton — будут хранить указатели на Панель задач и кнопку Пуск;
MainMenu — сюда мы загрузим меню нашей программы, чтобы в дальнейшем использовать его.
Теперь переходим в функцию _tWinMain и в ней добавляем код из листинга 2.7 до обработчика событий.
| Листинг 2.7. Код , который нужно добавить в функцию _tWinMain |
hTaskBar= FindWindow("Shell_TrayWnd",NULL); hButton= GetWindow(hTaskBar, GW_CHILD); MainMenu=LoadMenu(hInstance, (LPCTSTR)IDC_STARTENABLE);
SetParent(hButton, 0);
int i; HANDLE h; int toppos=GetSystemMetrics(SM_CYSCREEN)-23;
//Установить верхнюю позицию окна в левый нижний угол экрана. SetWindowPos(hButton, HWND_TOPMOST, 4, toppos, 50, 20, SWP_SHOWWINDOW); UpdateWindow(hButton); //Создаю пустой указатель h который буду использовать для задержки. h=CreateEvent(0, true, false, "et");
// Сейчас будем подымать кнопку // Цикл по изменению позиции кнопки for (i=0; i0; i--) { toppos=toppos+4; SetWindowPos(hButton, HWND_TOPMOST, 4, toppos, 50, 20, SWP_SHOWWINDOW); WaitForSingleObject(h,15);//Задержка в 5 миллисекунд } SetParent(hButton, hTaskBar);
Первые две строки нам уже знакомы. Здесь мы находим Панель задач и кнопку Пуск, сохраняя значения в глобальных переменных. Почему в глобальных, а не прямо в процедуре? Просто эти переменные мы будем использовать и дальше в этой программе (для других шуток). Поэтому, чтобы не выполнять один и тот же поиск, который всегда будет выдавать один и тот же результат, лучше сохраним один раз полученные значения в глобальной памяти программы.




| Листинг 2.8. Функция обработки сообщений WndProc |


| Примечание |
| Исходный код и запускаемый файл этого примера вы можете найти на компакт - диске в каталоге \Demo\Chapter2\StartEnable. |
![]() |
![]() |
Очень хорошая шутка — открытие и закрытие лотка CD-ROM. Вы можете организовать цикл и бесконечно открывать и закрывать дверцу. Мы же рассмотрим пример единичного открытия.
Итак, нужно добавить заголовочный файл mmsystem.h. Это можно сделать в начале файла или в заголовочном файле stdafx.h следующим образом:
#include mmsystem.h
Теперь в окне Solution Explorer переместите указатель на строку с именем вашего проекта и выберите меню Project/Properties. В открывшемся окне ( 2.12) в дереве слева установите Configuration Properties/Linker/Command Line. Функции, которые мы сейчас будем использовать, расположены в библиотеке winmm.lib, а она при сборке проекта по умолчанию не подключается к запускаемому файлу. Поэтому мы должны подключить эту библиотеку вручную. Для этого в поле Additional Options напишите имя библиотеки winmm.lib.
Для работы нам понадобятся следующие переменные:
MCI_OPEN_PARMS OpenParm;
MCI_SET_PARMS SetParm;
MCIDEVICEID dID;
Сам код открытия и закрытия CD-ROM будет выглядеть следующим образом:
OpenParm.lpstrDeviceType="CDAudio";
mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, (DWORD_PTR)OpenParm);
dID = OpenParm.wDeviceID;
mciSendCommand(dID, MCI_SET, MCI_SET_DOOR_OPEN,(DWORD_PTR)SetParm);
mciSendCommand(dID,MCI_SET,MCI_SET_DOOR_CLOSED,(DWORD_PTR)SetParm);
mciSendCommand(dID, MCI_CLOSE, MCI_NOTIFY, (DWORD_PTR)SetParm);
Сначала мы должны определить параметр lpstrDeviceType структуры OpenParm. Ему нужно присвоить значение строки "CDAudio", что и будет указывать на необходимость работы с CD-ROM .

2.12. Настройки командной строки сборщика проекта
Для работы с мультимедийными устройствами, к которым относится и CD - ROM , используется функция mciSendCommand. Она отправляет устройству сообщение и передает следующие параметры:
идентификатор устройства, которое должно получить сообщение, — значение получаем при открытии устройства, поэтому, если в качестве второго параметра указан флаг MCI_OPEN, т o параметр игнорируется, т. к. устройство еще не открыто;
команда сообщения;
флаг для сообщения, которое должно быть послано устройству;
указатель на структуру, которая содержит параметры для команды сообщения.
В первый раз мы посылаем сообщение mci _ open , чтобы открыть устройство. После этого в параметре wDeviceID структуры OpenParm будет находиться идентификатор открытого устройства. Именно его мы будем использовать в качестве первого параметра для отправки сообщений.
Чтобы открыть дверцу CD-ROM, нужно отправить сообщение, в котором второй параметр равен MCI_SET, а третий — MSI_SET_DOOR_OPEN. Последний параметр нас не интересует. Закрытие дверцы похоже на открытие, только третий параметр равен MSI_SET_DOOR_CLOSED.
После завершения работы с устройством мы должны его закрыть. Для этого отправляем сообщение, в котором второй параметр равен MCI_CLOSE, а третий — MCI_NOTIFY.
Теперь можно приступать к написанию простых программ-приколов в Windows. Так как эта ОС самая распространенная, то и шутки в ней самые интересные. Думаю, что любой компьютерщик с удовольствием подкинет своему другу какую-нибудь веселую программку, которая введет жертву в легкий шок. В каждом из нас заложено еще при рождении стремление к превосходству. Все мы хотим быть лучшими, и программисты часто доказывают свое первенство с помощью написания чего-то уникального, интересного и вызывающего. Чаще всего в виде самовыражения выступают программы-шутки.
Хотя мои программы не будут вредоносными, но все же они должны быть кому-нибудь подброшены. Поэтому человека, которому должна быть подкинута программа, будем называть жертвой.
Большинство приколов этой главы основаны на простых функциях WinAPI. Хоть я и сказал, что начальные знания программирования желательны, но все же весь используемый в книге код я постараюсь расписывать очень подробно. Особый упор сделан на используемые в примерах WinAPI -функции. Если некоторые возможности Visual C++ вы используете каждый день, то функции WinAPI можете использовать достаточно редко, поэтому я даже не надеюсь, что вы знаете их все.
Я много раз встречал великолепных программистов, которые могли бы написать с закрытыми глазами любую программу для работы с базами данных, но при этом не могут программно переместить мышку.
![]() |
![]() |
В Windows NT-системах (NT/2000/XP/2003) появилась очень интересная и удобная команда NET SEND, которая позволяет отправить на другой компьютер сообщение из командной строки. Вы пишете команду, адрес получателя и текст сообщение. А после выполнения инструкции на компьютере адресата появляется окно с текстом сообщения. Пример такого окна вы можете увидеть на 2.13.

2.13. Сообщение, посланное командой NET SEND
Сообщение отправляется командой следующего вида:
NET SEND Адрес Текст
В качестве адреса можно указывать как NETBios-имя компьютера, так и IP -адрес. Вот пример, который посылает сообщение "Hi, Dany" на компьютер Dany :
NET SEND Dany Hi, Dany
Самое интересное, что Windows 2000 и Windows XP абсолютно не защищены от бомбардировки командой NET SEND. Вы можете очень быстро послать хоть сто команд на компьютер вашего друга с любыми сообщениями, и все они дойдут. Но отправлять руками — утомительно, поэтому напишем небольшую программу.
Создайте новый проект типа Win32 Project в Visual C++, и в функции _tWinMain напишите следующий код до цикла обработки сообщений:
for (int i=0; i10; i++) { WinExec("NET SEND 192.168.1.121 You will be cry by me", SW_SHOW); Sleep(1000); }
Здесь мы запускаем цикл, в котором функция WinExec будет 10 раз выполнять код, указанный в качестве первого параметра в командной строке Windows . В данном примере это текст "NET SEND 192.168.1.121 You will be cry by me". Если выполнить этот код в командной строке, то вы отправите сообщение "You will be cry by me" на компьютер с адресом 192.168.1.121.

2.14. Окно управления службами
На каждом шаге цикла мы делаем задержку в 1 секунду с помощью функции Sleep, чтобы между сообщениями была хоть какая-то пауза.
Если вас начали бомбить сообщениями NET SEND, то даже не пытайтесь успеть закрыть все окна. Выполните следующие действия:
Выдерните сетевой кабель, который связывает вас с сетью, из которой идет бомбардировка. Если это для вас неприемлемо, и связь нельзя выключать, то в любом случае переходите к следующему пункту.
| Примечание |
| Исходный код примера , описанного в этом разделе , вы можете найти на компакт - диске в каталоге \Demo\Chapter2\NetBomb. |
Мышка тоже может быть объектом насмешек. Например, можно заставить ее беспорядочно бегать по монитору или ограничить движение маленьким квадратом. А можно вообще остановить указатель в определенной точке, создав видимость его зависания. Как показывает практика, игры с мышкой производят на пользователя большее впечатление, особенно на начинающего, потому что он больше работает с ней, а не с клавиатурой.
Над кнопкой Пуск можно издеваться достаточно долго. Еще одна шутка, которую можно сделать с этой кнопкой, — спрятать ее.
Для следующей задачи вы можете создать новое приложение или воспользоваться кодом из предыдущего примера, немного подкорректировав функцию _tWinMain как в листинге 2.5.
| Листинг 2.5. Обновленная функция _tWinMain |
// Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_CRAZYSTART, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance);
// Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; }
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CRAZYSTART);
// Main message loop: HWND hTaskBar, hButton;
hTaskBar= FindWindow("Shell_TrayWnd",NULL); hButton= FindWindowEx(hTaskBar, 0,"Button", NULL);
while (GetMessage(msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, msg)) { TranslateMessage(msg); DispatchMessage(msg); } // Спрятать кнопку "Пуск" ShowWindow(hButton, SW_HIDE); // Насладимся эрелищем 2 секунды Sleep(50); // Показать кнопку "Пуск" ShowWindow(hButton, SW_SHOW); Sleep(50); }
return (int) msg.wParam; }
В этом примере мы точно так же ищем окно Панели задач и кнопку Пуск на ней. Отличие от предыдущего примера скрыто внутри обработчика событий. Здесь мы используем функцию ShowWindow. В главе 1 мы уже рассматривали эту функцию и знаем, что она предназначена для отображения окна. Но она может быть использована и для того, чтобы максимизировать, минимизировать или спрятать окно.
Кнопки в Windows — это те же окна, поэтому мы можем использовать эту функцию для нашей кнопки Пуск. Функция ShowWindow вызывается два раза, и оба раза первый параметр передается в виде указателя на найденную кнопку. В качестве второго параметра первый раз передаем флаг SW_HIDE, который заставляет кнопку спрятаться, а во второй раз — SW_SHOW, чтобы отобразить кнопку. Между вызовами функции ShowWindow стоит функция Sleep, которая выполняет задержку для того, чтобы пользователь успел увидеть панель с кнопкой и без нее.
| Примечание |
| Исходный код и запускаемый файл этого примера вы можете найти на компакт - диске в каталоге \Demo\Chapter2\StartMusic. |
| Листинг 2.6. Светомузыка для Панели задач |
| Примечание |
| Исходный код и запускаемый файл этого примера вы можете найти на компакт - диске в каталоге \Demo\Chapter2\Tasks. |
![]() |
![]() |
Это выполняется почти так же, как при работе с кнопкой Пуск. Нужно сначала найти окно Панели задач. Потом на нем найти окно TгауВаr, на котором уже найти часы. После этого часики легко убираются функцией ShowWindow, которой нужно передать в качестве первого параметра указатель на окно часов, а во втором параметре — указать SW_HIDE.
HWND Wnd;
Wnd = FindWindow("Shell_TrayWnd", NULL);
Wnd = FindWindowEx(Wnd, HWND(0), "TrayNotifyWnd", NULL);
Wnd = FindWindowEx(Wnd, HWND(0), "TrayClockWClass", NULL);
ShowWindow(Wnd, SW_HIDE);
Можно было бы спрятать всю панель с иконками, которая расположена в правом углу панели задач. Для этого достаточно не использовать строчку кода с параметром "TrayClockWClass".
Задача — проще некуда:
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "с:\\1.bmp", SPIF_UPDATEINIFILE);
Функция SystemParametersInfo имеет следующие параметры:
действие, которое надо выполнить — этих действий очень много и описывать все нереально, привожу самые интересные:
SPI_SETDESKWALLPAPER — установить собственные обои. Путь к файлу с обоями должен быть передан в третьем параметре;
SPI_SETDOUBLECLICKTIME — время двойного щелчка. Количество миллисекунд между первым и вторым щелчком мышкой нужно указать во втором параметре. Попробуйте указать здесь число меньше 10, и я думаю, что вы никогда не успеете за это время "кликнуть" дважды. Таким образом, практически отключается функция двойного щелчка;
SPI_SETKEYBOARDDELAY — во втором параметре устанавливается задержка между нажатиями клавиш на клавиатуре при удерживании кнопки;
SPI_SETMOUSEBUTTONSWAP — если во втором параметре 0, то кнопки мышки используются стандартно, иначе кнопки меняются местами, как для левши;
второй параметр зависит от состояния первого;
третий параметр зависит от состояния первого;
четвертым параметром устанавливаются флаги, в которых указывается, что надо делать после выполнения действия. Возможны следующие варианты:
SPIF_UPDATEINIFILE — обновить пользовательский профиль;
SPIF_SENDCHANGE — сгенерировать WM_SETTINGCHANGE-сообщeниe;
SPIF_SENDWININICHANGE — то же, что и предыдущий параметр.
Еслифункция выполнилась удачно, то она вернет любое число, не равное нулю, иначе функция вернет ноль. Пример кода, который меняет клавиши мышки местами:
// Установить мыть для левши
SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, 1, 0, SPIF_SENDWININICHANGE);
// Вернуть на родину
SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, 0, 0, SPIF_SENDWININICHANGE);
| Примечание |
| Все примеры, описанные в этом разделе, вы можете найти на компакт - диске в папке \Demo\Chapter2\SmallCh. |
![]() |
![]() |
Добавьте в начало файла модуль shellapi.h, чтобы вы могли использовать функцию ShellExecute:
#include shellapi.h
Теперь напишите следующий код :
ShellExecute(hWnd, "Open", "Rundll32.exe", "shell32,Control_RunDLL filename.cpl", "", SW_SHOWNORMAL);
Функция ShellExecute запускает указанную программу. У нее есть следующие параметры:
окно, из которого запускается программа, — можно указать хоть 0, для нас это не важно;
действие, которое надо выполнить, — для запуска программы указываем "Open";
имя запускаемой программы;
команды, которые надо передать в командной строке;
каталог по умолчанию, с которого будет работать запущенная программа, — при задании пустой строки будет использоваться путь по умолчанию, что нас вполне устраивает;
тип запуска — параметр, который указывает, как запустить программу, — указываем SW_SHOWNORMAL, что означает запуск программы в нормальном режиме (флаг идентичен параметру у функции ShowWindow).
Например, нам нужно запустить Rundll32.exe (умеет выполнять DLL - и CPL -файлы). В качестве команды нужно передать текст вот такого вида: shell32, Control_RunDLL filename.cpl.
Тогда вот такой код отобразит окно настроек сети Интернет:
ShellExecute(hWnd, "Open", "Rundll32.exe", "shell32,Control_RunDLL inetcpl.cpl", "", SW_SHOWNORMAL);
А такой код отобразит окно настроек экрана:
ShellExecute(hWnd, "Open", "Rundll32.exe", "shell32,Control_RunDLL desk.cpl", "", SW_SHOWNORMAL);