如何创建Windows桌面上雪灾? [英] How to create a snowstorm on your Windows desktop?

查看:156
本文介绍了如何创建Windows桌面上雪灾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的实际应用不谈,如何(如果可能的话),你可以创建运行Windows桌面PC上的飘雪的效果? preferably什么也没有要生的C / C ++和WinAPI的。

Practical uses aside, how (if it is possible at all) could you create a "snowing" effect on your desktop PC running Windows? Preferably with nothing but raw C/C++ and WinAPI.

有关雪的要求是:


  • 出现在一切所示(注意:永远-on-top窗口可能会得到雪仍然之上,这是确定我明白,不可能有任何应用标志上面绝对)

  • 雪花很小,可能是简单的点或几个白色像素集群;

  • 不打扰与计算机工作(点击雪花通过发送点击到底层窗口);

  • 与用户拖动窗口好听播放;

  • 多显示器能力。

有关下列任一功能加分点:

Bonus points for any of the following features:


  • 雪积聚在窗口或任务栏(如果它是在屏幕的底部)的下边缘;

  • 雪山上也蓄积顶级窗口。或许的部分的雪积累,一些继续下去,每一个窗口标题栏上的积累;

  • 积累了窗口雪被抖落窗口时,被拖动;

  • 积累了任务栏上的雪都知道Vista / 7的下扩展的开始按钮。

  • 雪花有阴影/轮廓,所以他们在白色背景可见;

  • 雪花有复杂的snowflike酷似形状(他们一定很小)。

  • 点击雪花确实通过对基础窗口发送点击,但雪花带着一点酷动画蒸发;

  • Snow accumulates on the lower edge of the window or the taskbar (if it's at the bottom of the screen);
  • Snow accumulates also on top-level windows. Or perhaps some snow accumulates, some continues down, accumulating on every window with a title bar;
  • Snow accumulated on windows gets "shaken off" when windows are dragged;
  • Snow accumulated on taskbar is aware of the extended "Start" button under Vista/7.
  • Snowflakes have shadows/outlines, so they are visible on white backgrounds;
  • Snowflakes have complex snowflike-alike shapes (they must still be tiny).
  • Clicking on a snowflake does send the click through to the underlying window, but the snowflake evaporates with a little cool animation;

大多数的这些影响是直接的就够了,除非雪的点击和窗户拖着很好地扮演的一部分。在我的早年,我所做的HDC您从 GetDesktopWindow(),被点阅,但与用户拖动窗口的问题(雪花得到绘制的实现呈现在他们身上得到了)拖着。

Most of these effects are straightforward enough, except the part where snow is click-through and plays nicely with dragging of windows. In my early days I've made an implementation that draws on the HDC you get from GetDesktopWindow(), which was click-through, but had problems with users dragging windows (snowflakes rendered on them got "dragged along").

的溶液可以使用的是Vista / 7的Aero特性,但是,当然,一个普遍的解决方案是preferred。任何想法?

The solution may use Vista/7 Aero features, but, of course, a universal solution is preferred. Any ideas?

推荐答案

有关简洁和简单起见,这个答案已经被修整成一组有限的要求。这是微不足道的,扩大这一点,并使其更加坚固。

For the sake of brevity and simplicity, this answer has been trimmed to a limited set of requirements. It is trivial to expand this and make it more robust.

这答案在Windows XP上使用WPF。它可以工作在高达2台显示器,并应在其他Windows系统的正常工作。

This answer uses WPF on Windows XP. It should work on up to 2 monitors, and should work on other Windows systems as well.

它以一个简单的窗口:

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

要这个窗口,我们将添加定义雪花如下:

To this window, we will add Snowflakes defined as follows:

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

雪花具有默认的用户控件code-背后没有变化。

The snowflakes have the default UserControl code-behind with no changes.

最后,窗口codeBehind

Finally, the 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;
                }
            }
        }
    }
}

我不得不使用位形式code,以获得多屏幕的东西,我不得不在自己的项目向大会的参考。

I had to use a bit of forms code to get the multiscreen stuff, and I had to include the references to the Assemblies in my project.

我没有测试过很多,但我的系统上工作,并在完成后雪坐在屏幕的底部。

I haven't tested it much, but it does work on my system, and the snow sits at the bottom of the screen when done.

我用这个< /通过行为点击一个>引用。

I used this reference for the click through behavior.

一个更敬业的家伙比我应该能够适应这个,加上一些边缘检测,以获取雪坐到其他地方的任务。

A more dedicated fellow than I should be able to adapt this, plus some edge detection to the task of getting the snow to sit elsewhere.

请注意,雪花从来没有在这个例子中清理,并运行它足够长的时间后,你可能会注意到一些放缓。

Please be aware that snowflakes are never cleaned up in this example, and after running it long enough, you may notice some slowdown.

玩得开心!

这篇关于如何创建Windows桌面上雪灾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆