Vì lợi ích ngắn gọn và đơn giản, câu trả lời này đã được cắt thành một nhóm yêu cầu giới hạn. Nó là tầm thường để mở rộng điều này và làm cho nó mạnh mẽ hơn.
Câu trả lời này sử dụng WPF trên Windows XP. Nó sẽ hoạt động trên 2 màn hình và cũng hoạt động trên các hệ thống Windows khác.
Nó bắt đầu với một cửa sổ đơn giản:
<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>
Để cửa sổ này, chúng tôi sẽ bổ sung thêm Snowflakes quy định như sau:
<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>
Những bông tuyết có UserControl mặc định mã phía sau không có thay đổi.
Cuối cùng, Window 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;
}
}
}
}
}
tôi đã phải sử dụng một chút hình thức mã để có được những thứ Multiscreen, và tôi đã phải bao gồm các tài liệu tham khảo để các Assemblies trong dự án của tôi.
Tôi chưa thử nghiệm nhiều, nhưng nó hoạt động trên hệ thống của tôi và tuyết nằm ở cuối màn hình khi hoàn tất.
Tôi đã sử dụng tham chiếu this cho hành vi nhấp qua.
Một đồng nghiệp chuyên dụng hơn tôi có thể thích ứng với this, cộng với một số phát hiện cạnh để thực hiện tác vụ nhận tuyết ở nơi khác.
Hãy lưu ý rằng bông tuyết không bao giờ được làm sạch trong ví dụ này và sau khi chạy đủ lâu, bạn có thể nhận thấy một số chậm lại.
Vui chơi!
Tôi có thể đáp ứng tất cả 5 tính năng được yêu cầu bằng cách để máy tính của tôi trên các bậc ở trước nhà tôi ở NYC tối nay. –
@Larry Lustig - điểm lấy, tuy nhiên tôi đã hy vọng cho một giải pháp phần mềm nhiều hơn, những gì với gửi nó trên SO và tất cả ... –
Để người naysayer (cử tri gần) - những gì bạn không hiểu? Tôi sẽ làm rõ hơn? –