WPF 实现动态Windows桌面壁纸~

       由于微信群人数太多入群请添加小编微信号

 yanjinhuawechat 或 W_Feng_aiQ 入群

 需备注WPF开发者 

  PS:有更好的方式欢迎推荐。

  此项目灵感来源于 丑萌气质狗 B站同名  

  QQ群:560611514  (学习Unity3D)增加了播放视频。

01

代码如下

一、窗口介绍

Windows操作系统所有的地方都是窗口,可能这也是系统名字的由来吧,包括你看到的文件夹,桌面,右键菜单,这些都是由界面组成的, 这么多窗口需要有一个合理的显示,就需要用到我们的层级关系,比如两个窗体谁显示在前,谁显示在后。

VS给我们提供了一个查找和查看窗口信息的工具,叫做Spy++,在工具里面:

2780ab609d654d15ca7aceb6beac6b8a.png

打开之后了,这里给我们展示了当前系统所有的窗口信息,你也可以点击红色框中的查找工具,来查看你想知道的窗口信息:

d6ff0f6e41b78aa68c20fa002e67eb69.png

来演示一下如何查找窗口,点击上方红色框中的查找窗口按钮,两个随便选一个,会弹出如下窗口:

68067242fbfd36dd1f35c9e39b012e2c.png

然后你点击红色区域中的这个控件拖动到你想获取的信息窗口,就能看到当前窗口的详细信息了,包括窗口的句柄、标题、类。

比如我直接将图标拖到桌面上,可以看到这是他显示桌面的信息:

b4891d6538e9d70bce01a38c189ddf25.png

这里我们关掉这个窗口, 回到Spy++的主界面,拖到最底部:

fc152c38cb7f394aeedfd59ef0ac377c.png

可以看到, Progman Manager是桌面窗口的父窗口,前面小窗口图标是灰色的表示的是此窗口是隐藏的(子窗口拥有和父窗口一致的显示层级)。

二、原理操作

现在,我们只需要把我们的界面,也就是放到 Program Manager下面,然后再适当调整它的显示顺序,就可以了,但是这一块我们不好操作。有一个其他路子就是给窗口发送一个特殊的消息,来让我们有操作的空间。

只需要给 Program Manager窗口发送一个消息0x52C,就可以将Program Manager拆分为多个窗口,分别是Program Manager窗口和两个WorkerW窗口。

下面是已经发送过此消息后的样子:

037205cbb91b5abfdfc98195dc6752c7.png

可以看到Program Manager下面已经什么都没有了,内容全都转移到第一个WokerW窗口下,这时候我们只需要将我们的窗口挂在到Program Manager窗口的下方就能又有和它一样的显示层级了(窗口从下到上依次显示,所以这里Program Manager显示在最底层),不过需要注意的是,在Program Manager和第一个WorkerW窗口之间,还存在另外一个WorkerW窗口,在我的系统中,它默认隐藏了,为了确保效果一致,我们需要手动将它隐藏起来。

三、Win32ApiHelper 代码如下

using System;
using System.Runtime.InteropServices;

namespace WPFDevelopers.Helpers
{
    public class Win32ApiHelper
    {
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string className, string winName);

        [DllImport("user32.dll")]
        public static extern IntPtr SendMessageTimeout(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, uint fuFlage, uint timeout, IntPtr result);

        //查找窗口的委托 查找逻辑
        public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
        [DllImport("user32.dll")]
        public static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string winName);

        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);

        [DllImport("user32.dll")]
        public static extern IntPtr SetParent(IntPtr hwnd, IntPtr parentHwnd);
    }
}

四、DesktopBackground.xaml 代码如下

<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.DesktopBackground"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button Content="选择视频" Height="40" Width="120" Click="Button_Click"/>
    </Grid>
</UserControl>

五、DesktopBackground.xaml.cs 代码如下

using System.Windows;
using System.Windows.Controls;
using WPFDevelopers.Samples.ExampleViews.Desktop;

namespace WPFDevelopers.Samples.ExampleViews
{
    /// <summary>
    /// WorkerWBackground.xaml 的交互逻辑
    /// </summary>
    public partial class DesktopBackground : UserControl
    {
        
        public DesktopBackground()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            new DesktopPlayVideo().Show();
        } 
    }
}

六、DesktopPlayVideo.xaml 代码如下

<Window x:Class="WPFDevelopers.Samples.ExampleViews.Desktop.DesktopPlayVideo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews.Desktop"
        xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
        mc:Ignorable="d" 
        Background="Transparent"
        WindowStyle="None"
        ResizeMode="NoResize"
        AllowsTransparency="True"
        Height="{x:Static SystemParameters.PrimaryScreenHeight}"
        Width="{x:Static SystemParameters.PrimaryScreenWidth}">
    
    <Grid>
        <MediaElement Name="PART_MediaElement"/>
    </Grid>
</Window>
<Window x:Class="WPFDevelopers.Samples.ExampleViews.Desktop.DesktopPlayVideo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews.Desktop"
        xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
        mc:Ignorable="d" 
        Background="Transparent"
        WindowStyle="None"
        ResizeMode="NoResize"
        AllowsTransparency="True"
        Height="{x:Static SystemParameters.PrimaryScreenHeight}"
        Width="{x:Static SystemParameters.PrimaryScreenWidth}">
    
    <Grid>
        <MediaElement Name="PART_MediaElement"/>
    </Grid>
</Window>

七、DesktopPlayVideo.xaml.cs 代码如下

using System;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using WPFDevelopers.Helpers;


namespace WPFDevelopers.Samples.ExampleViews.Desktop
{
    /// <summary>
    /// DesktopPlayVideo.xaml 的交互逻辑
    /// </summary>
    public partial class DesktopPlayVideo : Window
    {
        private IntPtr programHandle;
        public DesktopPlayVideo()
        {
            InitializeComponent();
            this.Loaded += DesktopPlayVideo_Loaded;
        }

        private void DesktopPlayVideo_Loaded(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.DefaultExt = ".mp4";
            openFileDialog.Filter = "视频文件(.MP4)|*.mp4;";
            if (openFileDialog.ShowDialog() == true)
            {
                SendMsgToProgman();
                Width = SystemParameters.PrimaryScreenWidth; Height = SystemParameters.PrimaryScreenHeight; Left = 0; Top = 0;

                //PART_MediaElement.Source = new Uri(openFileDialog.FileName);
                //PART_MediaElement.MediaEnded += (s1, e1) => 
                //{
                //    PART_MediaElement.Position = new TimeSpan(0, 0, 1);
                //    PART_MediaElement.Play();
                //};

                var storyboard = new Storyboard();
                storyboard.RepeatBehavior = RepeatBehavior.Forever;
                var mediaTimeline = new MediaTimeline
                {
                    Source = new Uri(openFileDialog.FileName),
                };
                Storyboard.SetTargetName(mediaTimeline, PART_MediaElement.Name);
                storyboard.Children.Add(mediaTimeline);

                // 设置当前窗口为 Program Manager的子窗口
                Win32ApiHelper.SetParent(new WindowInteropHelper(this).Handle, programHandle);
                PART_MediaElement.Loaded += (s1, e1) =>
                {
                    storyboard.Begin(PART_MediaElement);
                };
                App.CurrentMainWindow.WindowState = WindowState.Minimized;
            }
        }

        /// <summary>
        /// 向桌面发送消息
        /// </summary>
        void SendMsgToProgman()
        {
            // 桌面窗口句柄,在外部定义,用于后面将我们自己的窗口作为子窗口放入
            programHandle = Win32ApiHelper.FindWindow("Progman", null);

            IntPtr result = IntPtr.Zero;
            // 向 Program Manager 窗口发送消息 0x52c 的一个消息,超时设置为2秒
            Win32ApiHelper.SendMessageTimeout(programHandle, 0x52c, IntPtr.Zero, IntPtr.Zero, 0, 2, result);

            // 遍历顶级窗口
            Win32ApiHelper.EnumWindows((hwnd, lParam) =>
            {
                // 找到第一个 WorkerW 窗口,此窗口中有子窗口 SHELLDLL_DefView,所以先找子窗口
                if (Win32ApiHelper.FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null) != IntPtr.Zero)
                {
                    // 找到当前第一个 WorkerW 窗口的,后一个窗口,及第二个 WorkerW 窗口。
                    IntPtr tempHwnd = Win32ApiHelper.FindWindowEx(IntPtr.Zero, hwnd, "WorkerW", null);

                    // 隐藏第二个 WorkerW 窗口
                    Win32ApiHelper.ShowWindow(tempHwnd, 0);
                }
                return true;
            }, IntPtr.Zero);
        }
    }
}

02


效果预览

鸣谢素材提供者 - 丑萌气质狗(李飞)

源码地址如下

Github:https://github.com/WPFDevelopersOrg

Gitee:https://gitee.com/WPFDevelopersOrg

作者:丑萌气质狗   学习Unity3D B站搜索 丑萌气质狗 

出处:https://www.cnblogs.com/choumengqizhigou/p/15702980.html

版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。

转载请注明出处

QQ群:560611514  (学习Unity3D)

WPF开发者QQ群: 340500857

686d509e71945a9a76c940b425f3c056.png

扫一扫关注我们,

1a0df7c26d1a1b9ab1267b14f13954a7.gif

更多知识早知道!

08f32aecf0ca578377860a0164bcc137.gif

点击阅读原文可跳转至源代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值