WPF виджеты на рабочий стол
На досуге я решил написать приложение-виджет ресурсов http://msug.vn.ua/ и http://wp7rocks.com/. Тоесть на рабочем столе будут отображаться логотипы этих ресурсов. Писать будем на Visual Studio 2008 с использованием WPF на C#.
И так, создаем новое WPF приложение (сделаем для msug). Логотипы у нас в формате .png, хорошо, потому что этот формат поддерживает альфа-каналы и если картинка прозрачная то она прозрачной и будет. После создания нового проекта, добавим компонент Image из Toolbox. Тепер загружаем подготовленную картинку в проект.
В свойстве Source у Image добавим имя картинки: Source=“logo3.png” и выравниваем картинку до нормальных размеров.
Убираем рамку вокруг формы и фон:
- Свойство WindowsStyle = None;
- AllowTransparency = True;
- Background = Transparent.
Перемещение виджета мышкой
Нам понадобится 2 обработчика кампонента Image: MouseDown и MouseMove. Зачем? В MouseDown будем запоминать текущее положение мыши, а в MouseMove нажата ли левая клавиша, а если нажата то получаем координаты курсора относительно левого верхнего края формы, прибавляя к текущему положению формы разницу между полученными координатами и координатой, сохраненной в момент нажатия на форму. И так объявляем глобальную переменную:
Point old;
В обработчике MouseDown пишем:
old = e.GetPosition(null);
Таким образом в момент клика запоминается координата мыши, а в MouseMove:
if (e.LeftButton == MouseButtonState.Pressed) { Point cur = e.GetPosition(null); this.Left += cur.X - old.X; this.Top += cur.Y - old.Y; }
В условии производится сравнение, нажата ли левая кнопка мыши. Вот так должен выглядет код:
Point old; private void image_MouseDown(object sender, MouseButtonEventArgs e) { old = e.GetPosition(null); } private void image_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { Point cur = e.GetPosition(null); this.Left += cur.X - old.X; this.Top += cur.Y - old.Y; } }
Убираем из TaskBar
Нужно установить свойство формы ShowInTaskbar в False.
Убираем из Alt+Tab
Нам понадобиться две WinAPI функции: SetWindowLong и GetWindowLong. Но сначала их нужно импортировать из библиотеки:
[DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr window, int index, int value); [DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr window, int index);
и добавить пространство имен:
using System.Runtime.InteropServices;
Далее напишем необходимые константы и функцию:
private const int GWL_EXSTYLE = -20; private const int WS_EX_TOOLWINDOW = 0x00000080; public static void HideFromAltTab(IntPtr Handle) { SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); }
В качестве входного параметра подается дескриптор. Чтобы все было «гуд» напишем свойство, которое предоставляет дескриптор формы:
private IntPtr Handle { get { return new WindowInteropHelper(this).Handle; } }
и добавим пространство имен:
using System.Windows.Interop;
Теперь создадим обработчик формы Loaded (не в Image, а у Window) и в нем напишем:
HideFromAltTab(Handle);
Йопт... а где окно
Сейчас сделаем так, чтобы наш виджет был позади всех окон. Берем WinAPI функцию SetWindowPos, ее также импортируем и пишем несколько констант:
[DllImport("user32.dll")] public static extern bool SetWindowPos(int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); public const int HWND_BOTTOM = 0x1; public const uint SWP_NOSIZE = 0x1; public const uint SWP_NOMOVE = 0x2; public const uint SWP_SHOWWINDOW = 0x40;
Пишем функцию, устанавливающую форму позади всех окон:
private void ShoveToBackground() { SetWindowPos((int)this.Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); }
и ее вызываем, создадим обработчик Activated (у Window), в нем напишем
ShoveToBackground();
Happy End!
Таким же образом можна создать виджет для http://wp7rocks.com/. Сам виджет далеко не идеальный, его можна усовершенствовать, добавив что-то для себя личное. Скачать программу msug и wp7rocks. Проекты целиком msug и wp7rocks.