Сквозь покрытые тайной искусства строки кода: Как я оживил рабочий стол с помощью P/Invoke ?

от автора

У каждого из нас есть свои маленькие радости, даже на фоне серой рутины. Для меня, как для обычного смертного, это был стандартный фон рабочего стола в Windows. Но, как это бывает, однажды моя жизнь пошла по новому пути, и я столкнулся с чудеснейшей картинкой, которая словно проникла в мою душу. Она стала моим вдохновением, моим маленьким островком радуги в море повседневной скуки. И, конечно же, это была картинка… ну, довольно вызывающего характера.

Сразу же в моей голове появилась идея: «Почему бы не поставить эту картинку на фон рабочего стола?». Ведь у нас есть горячие клавиши, правда? Но вот беда – ожидается общественное негодование и взгляды укоризны. Сквозь страхи и сомнения родилась невероятная идея: я напишу код, который будет мгновенно менять фон рабочего стола по нажатию горячих клавиш! Да, именно так, уважаемые читатели, я решил смело потрясти мир своим выбором обоев.

И вот, внезапно, на сцене появляется наш герой – P/Invoke! Если вы, как и я, не были в ладах с C/C++, не отчаивайтесь – P/Invoke стоит на страже ваших инноваций. Дело в том, что у меня не было ни малейшего понятия о C/C++, но это не остановило меня. Сила P/Invoke заключается в том, что он позволяет вам вызывать функции из низкоуровневых библиотек так, будто они были написаны на чистом C#. Вот как это работает:

Регистрация горячих клавиш

Мы нацелились на две магические комбинации клавиш: одну для эротического фона (да-да, я так и назвал) и другую для обычного. Итак, RegisterHotKey из «user32.dll» становится нашим верным спутником:

[DllImport("user32.dll")] public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);  // Настройки для магических клавиш. public const int MOD_ALT = 0x0001; public const int MOD_CONTROL = 0x0002; public const int MOD_SHIFT = 0x0004;  // Заклинания в виде клавиш. На этот раз мы выбрали "B" и "C". public const int VK_B = 0x42; public const int VK_C = 0x43;  // Ритуальные команды для вызова заклинаний. Наши числа имеют особое значение. public const int WallpaperErroticCommand = 11; // Пора призвать эротику! public const int WallpaperNormalCommand = 12; // А здесь - обычные обои.  if (RegisterHotKey(IntPtr.Zero, WallpaperErroticCommand, MOD_ALT | MOD_CONTROL, VK_B)     && RegisterHotKey(IntPtr.Zero, WallpaperNormalCommand, MOD_SHIFT, VK_C)) {     Console.WriteLine("Горячие клавиши успешно зарегистрированы. Время для волшебства!");     Console.WriteLine("Нажмите Ctrl+Alt+B, чтобы погрузиться в мир эротики. Это наш секрет!");     Console.WriteLine("Нажмите Shift+C, чтобы вернуться к обычным обоям. Магия тоже может быть невидимой."); } else {     Console.WriteLine("Не удалось зарегистрировать горячие клавиши. Магия чуть подвела нас."); }

Получение сообщений

И вот он, грядущий момент! Наш код ждет, когда кто-то нажмет горячие клавиши. GetMessage, снова из «user32.dll», оказывается в роли почтового голубя, который приносит нам эти важные сообщения:

[DllImport("user32.dll")] public static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);  public const int WM_HOTKEY = 0x0312;  MSG msg; while (GetMessage(out msg, IntPtr.Zero, 0, 0)) {     // Дело в том, что когда наступает момент и горячая клавиша нажимается,      // код ощущает, что что-то важное произошло. Все благодаря таинственному WM_HOTKEY,      // сообщению, которое как будто шепчет: "Друг мой, нажата горячая клавиша!".     if (msg.message != WM_HOTKEY) continue;          // ... }

Однако перед тем, как зажечь огонь фонов рабочего стола, я вынужден был призвать на помощь двух верных спутников – MSG и POINT.

// Структура MSG – это настоящий посланник между мирами. // Она приносит с собой множество важных данных и оставляет на них свой отпечаток. [StructLayout(LayoutKind.Sequential)] public struct MSG {     public IntPtr hwnd;        // Окно, через которое проникают тайные сообщения.     public uint message;       // Секретный код сообщения, как магическая формула.     public IntPtr wParam;      // Внутренний атрибут для заклинаний.     public IntPtr lParam;      // Еще одна загадочная составляющая.     public uint time;          // Время, в которое произошла магия.     public POINT pt;           // Точка, из которой мы начинаем свое магическое путешествие.     public uint lPrivate;      // Загадочное личное свойство, которое всегда вызывает вопросы.      // Магическая формула, раскрывающая суть MSG.     public readonly override string ToString() =>         $"hwnd: {hwnd}, message: {message}, wParam: {wParam}, lParam: {lParam}, time: {time}, pt: {pt}, lPrivate: {lPrivate}"; }  // А вот и наш друг POINT, тоже со своими тайнами. // Он умеет указывать на самые глубокие секреты координат. [StructLayout(LayoutKind.Sequential)] public struct POINT {     public int x;              // Секретная координата X, на которой начинается магия.     public int y;              // И Y, естественно, не менее загадочный.      // Интригующая загадка, которую POINT оставляет нам в наследство.     public readonly override string ToString() =>         $"x: {x}, y: {y}"; }

Установка обоев

Да-да, самая волнительная часть! Определяем, какой фон стоит поставить, и SystemParametersInfo возвращает нам победу или патовую ситуацию:

[DllImport("user32.dll", CharSet = CharSet.Auto)]     public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);  // Готовимся к великому замаху - выбору обоев! var imagePath = msg.wParam switch {     WallpaperErroticCommand => WallpaperErroticPath,     WallpaperNormalCommand => WallpaperNormalPath,     _ => throw new InvalidOperationException($"Недопустимое значение команды {nameof(msg.wParam)}:{msg.wParam}") };  // Поднимаем путеводный факел - адрес изображения! var imagePtr = Marshal.StringToHGlobalUni(imagePath);  // Открываем ворота в мир фантазий - установка обоев! if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imagePtr, 0)) {     Console.WriteLine("Не удалось установить фон рабочего стола. Жизнь не по детски сложна, верно?"); } else {     Console.WriteLine("Фон успешно установлен. Помните, обои – это ваше зеркало в мир!"); }  // Освобождаем место для других идей - освобождение памяти! Marshal.FreeHGlobal(imagePtr); 

Результат

И вот, наконец, наступило время раскрыть завесу и рассказать о результатах магических воздействий!

До нажатия Ctrl+Alt+B:

После нажатие Ctrl+Alt+B

И так, подготовьтесь к следующей главе моей истории. Нажимаю Shift+C:

Представьте, как будто мир вокруг меняется с каждым нажатием клавиши, как будто прикосновение волшебной палочки!

Заключение

Итак, что у нас получается? Не волнуйтесь, если мир C/C++ вам кажется далеким и непонятным, это совсем не повод опускать руки! P/Invoke – это наш надежный союзник в этом мире низкоуровневых библиотек. Так что даже если вы совсем не связаны с этими технологиями, не унывайте! Не бойтесь претворять ваши идеи в жизнь, даже если они затрагивают такой обыденный момент, как выбор обоев рабочего стола. Помните, одним маленьким шагом в коде вы можете придать жизнь всему окружающему миру!


ссылка на оригинал статьи https://habr.com/ru/articles/756460/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *