# C# winform作为壁纸程序

代码

1、在alt+tab中隐藏窗口

2、不在任务栏显示

3、将窗口设为“桌面”的子窗口

4、重启资源管理器则重新自启动

5、切换桌面重新设置父窗口

C#
//在alt+tab中隐藏
protected override CreateParams CreateParams
{
    get
    {
        const int WS_EX_APPWINDOW = 0x40000;
        const int WS_EX_TOOLWINDOW = 0x80;
        CreateParams cp = base.CreateParams;
        cp.ExStyle &= (~WS_EX_APPWINDOW);
        cp.ExStyle |= WS_EX_TOOLWINDOW;
        return cp;
    }
}

private IntPtr programIntPtr = IntPtr.Zero;
private void Find()
{
    // 通过类名查找一个窗口,返回窗口句柄。
    programIntPtr = Win32.FindWindow("Progman", null);
}
private void Init()
{
    // 窗口句柄有效
    if (programIntPtr != IntPtr.Zero)
    {
        IntPtr result = IntPtr.Zero;
        // 向 Program Manager 窗口发送 0x52c 的一个消息,超时设置为0x3e8(1秒)。
        Win32.SendMessageTimeout(programIntPtr, 0x52c, IntPtr.Zero, IntPtr.Zero, 0, 0x3e8, result);

        // 遍历顶级窗口
        Win32.EnumWindows((hwnd, lParam) =>
        {
            // 找到包含 SHELLDLL_DefView 这个窗口句柄的 WorkerW
            if (Win32.FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null) != IntPtr.Zero)
            {
                // 找到当前 WorkerW 窗口的,后一个 WorkerW 窗口。
                IntPtr tempHwnd = Win32.FindWindowEx(IntPtr.Zero, hwnd, "WorkerW", null);

                // 隐藏这个窗口
                Win32.ShowWindow(tempHwnd, 0);
            }
            return true;
        }, IntPtr.Zero);

        // 窗口置父,设置背景窗口的父窗口为 Program Manager 窗口
        Win32.SetParent(this.Handle, programIntPtr);
    }
}
private void OnLoad(object sender, EventArgs e)
{
    this.Dock = DockStyle.Fill;
    this.ShowInTaskbar = false;
    this.FormBorderStyle = FormBorderStyle.None;
    
    Rectangle bound = Screen.PrimaryScreen.Bounds;
    this.Width = bound.Width;
    this.Height = bound.Height;
    this.Left = 0;
    this.Top = 0;

    Find();
    Init();
    
    this.WindowState = FormWindowState.Maximized;

    IntPtr oldprogramIntPtr = programIntPtr;
    new Thread(() =>
    {
        while (true)
        {
            Find();
            //当资源管理器重启后,程序自动重启
            if (programIntPtr != oldprogramIntPtr)
            {
                Application.ExitThread();
                Application.Exit();
                Application.Restart();
                Process.GetCurrentProcess().Kill();
            }
            
            //某些原因下,桌面窗口的子窗口会失效,比如按下 win+tab
            //我们查找一下桌面窗口的子窗口,找不到当前壁纸程序的句柄,那就重新设置一下
            bool hasChild = false;
            Win32.EnumChildWindows(programIntPtr, (IntPtr hwnd, IntPtr lParam) =>
            {
                hasChild |= hwnd == this.Handle;
                return true;
            }, IntPtr.Zero);
            if (hasChild == false)
            {
                Init();
            }
            
            Thread.Sleep(1000);
        }
    }).Start();
}


public static class Win32
{
    [DllImport("user32.dll")]
    public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, IntPtr lParam);
    public delegate bool EnumChildCallback(IntPtr hwnd, IntPtr lParam);
    
    [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);

    [DllImport("user32.dll")]
    public static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
    public delegate bool EnumWindowsProc(IntPtr hwnd, 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);
}