Как создать метель на рабочем столе Windows?
практическое использование в стороне, как (если это вообще возможно) вы могли бы создать эффект "снег" на вашем настольном ПК под управлением Windows? Предпочтительно только с сырым C / C++ и WinAPI.
требования к снегу:
- появляется над всем остальным показанным (Примечание: всегда-на-верхние окна могут получить поверх снега все еще, это нормально. Я понимаю, что для любого приложения не может быть флага "absolute on top")
- снежинки маленькие, возможно, простые точки или кластеры из нескольких белых пикселей;
- не утруждает себя работой с компьютером (щелчок снежинки отправляет щелчок в базовое окно);
- хорошо играет с пользователями, перетаскивающими окна;
- Multi-монитор способен.
бонусные баллы за любую из следующих функций:
- снег скапливается на нижнем краю окна или панели задач (если он находится в нижней части экрана);
- снега скапливается также на окнах верхнего уровня. Или, может быть,некоторые снег накапливается, некоторые продолжают вниз, накапливаясь на каждом окне с заголовком;
- снег, накопленный на окнах, "стряхивается" при перетаскивании окон;
- снег, накопленный на панели задач, знает о расширенной кнопке "Пуск" под Vista/7.
- снежинки имеют тени / контуры, поэтому они видны на белом фоне;
- снежинки имеют сложные snowflike-подобные формы (они должно быть, все еще крошечные).
- щелчок по снежинке отправляет щелчок в базовое окно, но снежинка испаряется с небольшой крутой анимацией;
большинство из этих эффектов достаточно просты, за исключением той части, где снег щелкает и хорошо играет с перетаскиванием окон. В мои первые дни я сделал реализацию, которая опирается на HDC, который вы получаете от GetDesktopWindow()
, который был щелчком мыши, но имел проблемы с перетаскиванием пользователей windows (снежинки, оказавшиеся на них, "волочились").
решение может использовать функции Vista / 7 Aero, но, конечно, предпочтительным является универсальное решение. Есть идеи?
1 ответов
для краткости и простоты этот ответ был обрезан до ограниченного набора требований. Это тривиально, чтобы расширить это и сделать его более надежным.
этот ответ использует WPF в Windows XP. Он должен работать на мониторах до 2 и должен работать и на других системах Windows.
Он начинается с простого окна:
<Window x:Class="TestDump.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" WindowStartupLocation="Manual" Loaded="Window_Loaded"
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
>
<Grid x:Name="FieldOfSnow"/>
</Window>
В это окно мы добавим снежинки, определенные следующим образом:
<UserControl x:Class="TestDump.SnowFlake"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="5" Width="5">
<Border Background="White" CornerRadius="2" BorderThickness="1" BorderBrush="LightGray"/>
</UserControl>
снежинки есть код UserControl по умолчанию-без изменений.
наконец, окно CodeBehind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;
namespace TestDump
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private TimeSpan _lastRender;
public Window1()
{
InitializeComponent();
_lastRender = TimeSpan.FromTicks(0);
CompositionTarget.Rendering += SnowflakeTick;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Topmost = true;
this.Top = 0;
this.Left = 0;
this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
if (System.Windows.Forms.SystemInformation.MonitorCount == 2)
{
System.Drawing.Rectangle SecondScreenArea = System.Windows.Forms.Screen.AllScreens[1].Bounds;
this.Width += SecondScreenArea.Width;
this.Height = this.Height > SecondScreenArea.Height ? this.Height : SecondScreenArea.Height;
}
}
public const int WS_EX_TRANSPARENT = 0x00000020;
public const int GWL_EXSTYLE = (-20);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(this).Handle;
// Change the extended window style to include WS_EX_TRANSPARENT
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
}
List<TranslateTransform> Flakes = new List<TranslateTransform>();
Random rand = new Random();
private void SnowflakeTick(object sender, EventArgs e)
{
RenderingEventArgs renderingArgs = (RenderingEventArgs)e;
TimeSpan dTime = (renderingArgs.RenderingTime - _lastRender);
double deltaTime = dTime.TotalMilliseconds;
_lastRender = renderingArgs.RenderingTime;
if ( _lastRender.Milliseconds < deltaTime)
{
TranslateTransform SnowPos = new TranslateTransform(this.Width * rand.Next(1000) / 1000.0 - this.Width/2, -this.Height/2);
SnowFlake sf = new SnowFlake();
sf.RenderTransform = SnowPos;
// The flakes are centered when added, so all positions must be translated with this in mind.
FieldOfSnow.Children.Add(sf);
Flakes.Add(SnowPos);
}
foreach (TranslateTransform Flake in Flakes)
{
double ScreenHeight = this.Height / 2 - 2;
if (Flake.Y < ScreenHeight)
{
Flake.Y += deltaTime / 50;
}
}
}
}
}
мне пришлось использовать немного кода форм, чтобы получить многоэкранный материал, и я должен был включить ссылки на сборки в свой проект.
Я не тестировал его много, но он работает на моей системе, и снег сидит в нижней части экрана, когда это сделано.
Я этой ссылка для поведения click through.
A более преданный товарищ, чем я мог бы приспособиться!--24-->этой, плюс некоторое обнаружение края к задаче получения снега, чтобы сидеть в другом месте.
имейте в виду, что снежинки никогда не очищаются в этом примере, и после запуска его достаточно долго, вы можете заметить некоторое замедление.
Удачи!