2011-01-11 22 views
11

Sử dụng thực tế sang một bên, làm cách nào (nếu có thể) bạn có thể tạo hiệu ứng "tuyết" trên máy tính để bàn chạy Windows không? Tốt hơn là không có gì ngoài nguyên C/C++ và WinAPI.Cách tạo bão tuyết trên màn hình nền Windows của bạn?

Các yêu cầu đối với tuyết là:

  • Xuất hiện trên mọi thứ khác hiển thị (Lưu ý: luôn luôn-on-top cửa sổ có thể nhận được trên đầu trang của tuyết vẫn còn, đó là OK Tôi hiểu rằng không thể có ". tuyệt đối trên đầu "cờ cho bất kỳ ứng dụng nào)
  • Bông tuyết là các chấm nhỏ hoặc có thể đơn giản hoặc một vài điểm trắng;
  • Không bận tâm khi làm việc với máy tính (nhấp vào bông tuyết sẽ gửi nhấp qua cửa sổ bên dưới);
  • Phát độc đáo với người dùng kéo cửa sổ;
  • Khả năng đa màn hình.

điểm thưởng cho bất kỳ các tính năng sau:

  • Tuyết tích tụ trên mép dưới của cửa sổ hoặc thanh tác vụ (nếu nó ở dưới cùng của màn hình);
  • Tuyết cũng tích lũy trên các cửa sổ cấp cao nhất. Hoặc có lẽ một số tích lũy tuyết, một số tiếp tục xuống, tích lũy trên mọi cửa sổ có thanh tiêu đề;
  • Tuyết tích tụ trên cửa sổ bị "tắt" khi cửa sổ được kéo;
  • Tuyết tích lũy trên thanh tác vụ là nhận thức được nút "Bắt đầu" mở rộng trong Vista/7.
  • Bông tuyết có bóng/viền, vì vậy chúng có thể nhìn thấy trên nền màu trắng;
  • Bông tuyết có hình dạng giống như bông tuyết phức tạp (chúng vẫn phải rất nhỏ).
  • Nhấp vào bông tuyết sẽ gửi nhấp qua cửa sổ bên dưới, nhưng bông tuyết bay hơi với một hoạt ảnh nhỏ mát mẻ;

Hầu hết các hiệu ứng này đều đơn giản, ngoại trừ phần tuyết rơi qua và phát độc đáo bằng cách kéo cửa sổ. Trong những ngày đầu của tôi, tôi đã thực hiện triển khai dựa trên HDC mà bạn nhận được từ GetDesktopWindow(), được nhấp qua nhưng gặp sự cố với người dùng kéo cửa sổ (bông tuyết được hiển thị trên chúng đã bị "kéo dọc").

Giải pháp có thể sử dụng các tính năng Aero/7 Aero, nhưng, tất nhiên, một giải pháp phổ quát được ưu tiên. Bất kỳ ý tưởng?

+10

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. –

+0

@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ả ... –

+0

Để người naysayer (cử tri gần) - những gì bạn không hiểu? Tôi sẽ làm rõ hơn? –

Trả lời

6

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!

+0

Tôi thấy rằng mẹo của bạn cũng là WS_EX_TRANSPARENT (còn gọi là cửa sổ nhiều lớp). Cảm ơn bạn đã xác nhận rằng tác phẩm này hoạt động! :) –

+0

câu trả lời rất hay, +1 –

+0

Bất kỳ ý tưởng làm thế nào để làm cho nó trong Java? – Alpine

Các vấn đề liên quan