Леонид: Спасибо
20-09-2023
Читать статью
Калужский Александр: Леонид, цикл x повториться 300 раз, цикл..
Леонид: Почему k == 90000 в примере (x > A) ∨ (y..
Привет! Сегодня Хэллоуин (31 октября), и мы сделаем программу-прикол "Убегающая кнопка Пуск".
С помощью данной программы вы можете кого-нибудь разыграть. Когда пользователь подведёт курсор мышки к кнопке Пуск, она начнёт от него убегать! В этот момент мы спрячем данную кнопку, а наша форма программы появится в случайном месте экрана, и на ней будет нарисована кнопка Пуск. Таким образом, получится эффект, что данная кнопка взбунтовалась и просто убегает.
При попытке навести курсор на форму, она снова будет убегать. Остановить шутку можно, если пользователь ещё раз подведёт курсор к законному месту кнопки Пуск, тогда наша программа закроется.
Воспользоваться уже готовой программой можно по ссылке. Эта программа ещё немного усовершенствована в некоторых мелочах.
Идея была взята из книги Михаила Фленова С++ глазами хакера. Но реализацию мы будем делать по-своему на языке С#.
Выбираем проект Windows Forms (.NET Framework). Главная форма будет прозрачной, программу будет видно только в трее.
В настройках нашей программы организатору розыгрыша нужно будет добавить изображение кнопки Пуск для текущей версии Windows на данном компьютере. Её легко сделать с помощью какого-нибудь графического редактора и скришота экрана. Здесь вам рекомендую воспользоваться мои скриншотером, который может сохранить указанную область экрана сразу в файл.
Свойства главной формы: Opacity: 0% (делаем форму прозрачной), ShowInTaskbar: Fasle (убираем программу из панели задач), FormBorderStyle: None (убираем рамку вокруг окна).
Чтобы программу было видно в трее кинем на форму элемент NotifyIcon. Добавим в ресурсы проекта иконку для этого элемента. Переходим Обозреватель решений->Свойства (Проекта)->Ресурсы.
Выбираем в верхнем выпадающем меню Значки.
Возле кнопки Добавить ресурс нажимаем чёрный треугольник и выбираем "добавить существующий файл". Выберем изображение формата .ico с разрешением 150 на 150 пикселей.
Теперь можно обратится в коде к этому ресурсу. Напишем в классе главной формы внутри функции public Form1() после инициализации:
notifyIcon1.Icon = Properties.Resources._1;
_1 - это название иконки.
Зададим свойства для notifyIcon1. Text: Программа-прикол "убегающая кнопка Пуск" (этот текст будет всплывать при наведении на иконку в трее).
Добавим для элемента notifyIcon1 контекстное меню. Кинем элемент contextMenuStrip1 на главную форму. Добавим в свойство ContextMenuStrip для notifyIcon1 имя контекстного меню.
Добавим две позиции в контекстное меню.
Кликним два раза по каждому пункту и получим функции, которые будут вызываться, когда пользователь будет нажимать на них.
Для выхода пропишем:
Перейдём к главной форме. Нажмём F7. Напишем в начале класса Form1.
public string FileImg = "";
Это переменная будет хранить путь к файлу изображения кнопки Пуск. Сделали эту переменную публичной. Мы к ней будем обращаться из формы настроек.
При клике на пункт Настройки должно появится окно с параметрами. В нём пользователь должен указать на изображение кнопки Пуск в формате jpg для данного компьютера, где будет происходит розыгрыш. Добавим ещё одну форму.
В обозревателе решений кликнем правой кнопкой мыши по названию проекта. Выберем Добавить-> Форма -> Добавить.
Пропишем свойства новой формы. Text: Настройки "Убегающая кнопка Пуск" (Название окна); StartPosition: CenterScreen (окно должно появляться по центру экрана); FormBorderStyle: FixedSingle (окно нельзя будет растягивать), MaximizeBox: False (убираем возможность развернуть окно).
Кинем на новую форму элемент Label. Сделаем для него свойства. Font: Размер 14 пт, Text: "Добавьте изображение для кнопки пуск". Размести этот элемент примерно посередине.
Кинем на форму элемент TextBox. Чтобы изменить высоту данного элемента, нужно изменить свойство Font. Поставим Font: 12 пт, установим свойство ReadOnly: True (запретим редактирование текстового поля).
Добавим на новую форму ещё две кнопки Button, чтобы в итоге она выглядела примерно так:
Для контекстного меню настройки пропишем:
Здесь создаётся объект формы настроек. И эта форма становится видимой.
Перейдём на вторую форму. Нажмём F7 и пропишем в начале класса Form2:
string FileName = "";
Кинем ещё один элемент OpenFileDialog на вторую форму. Выделим первую кнопку ("Выбрать изображение"). Настроим обработчик события нажатия этой кнопки. Перейдём на окно События (иконка в виде молнии).
Найдём событие Click и кликнем два раза по ячейке справа. Пропишем в обработчике события:
Здесь вызывается файловый диалог, чтобы пользователь указал файл изображения кнопки пуск. В функции проверяется расширение выбранного файла. Расширение должно быть jpg. Путь до этого файла записывается в текстовое поле textBox1. Если путь превышает 23 символа, то эта строка обрезается и добавляется к ней троеточие.
Чтобы передать путь до изображения в главную форму, сделаем следующие манипуляции. Пропишем в начале класса Form2:
Form1 Prt;
И изменим функцию public Form2():
Тогда и в коде для первой формы в функции настройкиToolStripMenuItem_Click изменим создание объекта для формы настроек:
Form2 FormSitting = new Form2(this);
Таким образом, мы сможет передать путь до изображения кнопки Пуск из формы настроек в главное окно программы.
Пропишем обработчик события Click для второй кнопки окна настроек (кнопки ОК).
Здесь мы проверяем, чтобы файл был именно формата jpg. Если всё нормально - передаём главному окну путь до изображения кнопки Пуск и закрываем окно настроек.
Вернёмся к коду главной формы Form1. Кинем на форму ещё элемент таймер (Timer). Таймер будет запускать функцию каждые 100 миллисекунд. Эта функция будет проверять находится ли курсор мышки над кнопкой Пуск. Пропишем в функции public Form1() внизу:
Именно функция Timer1_Tick будет запускаться каждые 100 миллисекунд.
Добавим в начале класса Form1 переменную-индикатор:
bool move = false;
Эта переменная будет равна true, если наша кнопка уже убегает от пользователя.
Добавим так же очень важные для нашей программы функции из WinAPI в начале класса Form1.
[DllImport("user32.dll")] private static extern IntPtr FindWindow(string ClassName, string WindowName); [DllImport("user32.dll")] static extern IntPtr WindowFromPoint(Point p); [DllImport("user32.dll")] public static extern bool GetCursorPos(out Point lpPoint); [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("User32.Dll")] public static extern long SetCursorPos(int x, int y); [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private const UInt32 SWP_NOSIZE = 0x0001; private const UInt32 SWP_NOMOVE = 0x0002; private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
Теперь реализуем функцию Timer1_Tick, которую будет запускать таймер каждые 100 миллисекунд.
private void Timer1_Tick(object sender, EventArgs e) { Point p; Image img; int x, y; GetCursorPos(out p); // Получим дескриптор кнопки ПУСК IntPtr startWnd = FindWindow("Button", null); IntPtr W = WindowFromPoint(p); if (startWnd == W) { if (move) { Thread.Sleep(400); this.Close(); } if (FileImg != "") { img = Bitmap.FromFile(FileImg); this.Opacity = 100; this.Size = new Size(img.Width, img.Height); if (move == false) { Rectangle resolution = Screen.PrimaryScreen.Bounds; Random rnd = new Random(); x = rnd.Next(Convert.ToInt32(resolution.Width*0.2), Convert.ToInt32(resolution.Width * 0.3)); y = rnd.Next(Convert.ToInt32(resolution.Height * 0.7), Convert.ToInt32(resolution.Height * 0.8)); this.Location = new Point(x, y); this.BackgroundImage = img; SetCursorPos(x-20, y+80); Thread.Sleep(150); ShowWindow(startWnd, 0); SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); } move = true; } } }
Переменная img - она будет содержать картинку кнопки Пуск, которую загрузил пользователь. Функция GetCursorPos будет получать координаты курсора мышки в переменную p.
С помощью функции FindWindow определяем дескриптор кнопки Пуск. С помощью функции WindowFromPoint определяем дескриптор окна для точки p. Таким образом, если у нас эти дескрипторы равны, то курсор мышки находится над кнопкой Пуск. Пора действовать!
Если переменная FileImg не пуста, то значит, пользователь уже настроил изображение для кнопки Пуск. Загружаем изображение в переменную img. Для основной формы возвращаем непрозрачность на 100%. Делаем размер окна таким же, как и изображение для кнопки Пуск.
Если этот механизм сработал первый раз (переменная move всё ещё равна false), то узнаём размеры экрана (переменная resolution) и делаем случайные координаты x, y для Form1 (с изображением кнопки) вблизи левого нижнего угла (где примерно и находится кнопка Пуск). Тем самым достигается эффект того, что кнопка ускользнула от пользователя.
Курсор мышки устанавливаем рядом с новым изображением кнопки Пуск (с Form1) c помощью функции SetCursorPos. Скрываем настоящую кнопку Пуск с помощью функции ShowWindow. Задержку в 150 миллисекунд делаем для более плавной работы.
Функция SetWindowPos помогает муляж кнопки Пуск разместить поверх всех окон.
Так же в этой функции написано условие:
if (move) { Thread.Sleep(400); this.Close(); }
Оно написано для того, чтобы завершить работу программы, если пользователь подведёт курсор мышки к настоящей кнопке Пуск (при move=true, т.е. при уже блуждающем Пуске). Всё равно в этом случае в Windows 10 настоящая кнопка Пуск становится опять видимой, и наша шутка как бы на этом заканчивается. Т.е, чтобы завершить блуждание кнопки, нужно догадаться подвести мышку к месту постоянной дислокации кнопки Пуск.
Запрограммируем убегание муляжа кнопки Пуск (Form1) при наведении на него курсора. Для главной формы настроим обработчик события MouseMove.
private void Form1_MouseMove(object sender, MouseEventArgs e) { Rectangle resolution = Screen.PrimaryScreen.Bounds; Random rnd = new Random(); this.Location = new Point(rnd.Next(10, resolution.Width - 100), rnd.Next(10, resolution.Height - 100)); }
Этот код похож на фрагмент из функции Timer1_Tick. Здесь случайно вычисляются новые координаты для главной формы (муляжа кнопки Пуск). Уже существенно расширен диапазон для переменных x и y. Делаем небольшие отступы от краёв экрана, чтобы картинка не ушла за поле зрения пользователя.
На сегодня всё! Счастливого программирования! ))
Скачать результат данной статьи с небольшими усовершенствованиями можно по ссылке ниже.