更换 windows 桌面

Replacing the windows desktop

对于我正在进行的软件项目,我需要更换桌面 window。

要求:

我目前一直在尝试 Naskohell,但这会替换整个桌面,包括任务栏。我可以编写自己的任务栏,但我觉得这是我可以避免的很多额外工作。

然后是SetWindowPos功能,但我不知道用哪个Z级别来实现我想要的。

谁能告诉我实现我的要求的最佳方法是什么?

您需要位于桌面之上,应用之下,并隐藏任务栏。 我首先尝试通过 Hide TaskBar in WinForms Application

隐藏任务栏

其次,使用 HWND_BOTTOM 将 window 设置到最底部。 有一些古怪的行为最好在多个 OS 的 Setting a Windows form to be bottommost

中进行测试

编辑 - 好吧,因为任务栏不断出现,所以花了一点时间。加载时会出现闪烁,然后转到后面。其中一些可以优化,但我会把它留给你 - 但这是一个工作演示。我已经测试过移动任务栏和多个桌面 - 一切似乎都正常。您还需要防止 window 关闭(如果您想要这种行为),但要连接到 WM_CLOSE 中。并忽略它(仍然不会阻止某人使用任务管理器,在这种情况下,您需要类似观察者进程的东西,并且两个进程相互监视以检测对方何时关闭)。我从几个 SO 帖子和一些琐碎的事情中编译了这个。

window属性 在任务栏中显示 = false WindowState = 最大化 控制框 = 假 FormBorderStyle = none

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DesktopReplacement
{
    public partial class Form1 : Form
    {
        private bool _enableOverride;
        internal class NativeMethods
        {
            public const int WM_WINDOWPOSCHANGING = 0x46;
            public const int WM_WINDOWPOSCHANGED = 0x47;
            public const int GWL_HWNDPARENT = -8;
            public const int SW_SHOW = 1;


            [Flags()]
            public enum SetWindowPosFlags
            {
                SWP_NOSIZE = 0x1,
                SWP_NOMOVE = 0x2,
                SWP_NOZORDER = 0x4,
                SWP_NOREDRAW = 0x8,
                SWP_NOACTIVATE = 0x10,
                SWP_FRAMECHANGED = 0x20,
                SWP_DRAWFRAME = SWP_FRAMECHANGED,
                SWP_SHOWWINDOW = 0x40,
                SWP_HIDEWINDOW = 0x80,
                SWP_NOCOPYBITS = 0x100,
                SWP_NOOWNERZORDER = 0x200,
                SWP_NOREPOSITION = SWP_NOOWNERZORDER,
                SWP_NOSENDCHANGING = 0x400,
                SWP_DEFERERASE = 0x2000,
                SWP_ASYNCWINDOWPOS = 0x4000,
            }

            public enum WindowZOrder
            {
                HWND_TOP = 0,
                HWND_BOTTOM = 1,
                HWND_TOPMOST = -1,
                HWND_NOTOPMOST = -2,
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct WINDOWPOS
            {
                public IntPtr hWnd;
                public IntPtr hwndInsertAfter;
                public int x;
                public int y;
                public int cx;
                public int cy;
                public SetWindowPosFlags flags;

                // Returns the WINDOWPOS structure pointed to by the lParam parameter
                // of a WM_WINDOWPOSCHANGING or WM_WINDOWPOSCHANGED message.
                public static WINDOWPOS FromMessage(Message msg)
                {
                    // Marshal the lParam parameter to an WINDOWPOS structure,
                    // and return the new structure
                    return (WINDOWPOS)Marshal.PtrToStructure(msg.LParam, typeof(WINDOWPOS));
                }

                // Replaces the original WINDOWPOS structure pointed to by the lParam
                // parameter of a WM_WINDOWPOSCHANGING or WM_WINDOWPSCHANGING message
                // with this one, so that the native window will be able to see any
                // changes that we have made to its values.
                public void UpdateMessage(Message msg)
                {
                    // Marshal this updated structure back to lParam so the native
                    // window can respond to our changes.
                    // The old structure that it points to should be deleted, too.
                    Marshal.StructureToPtr(this, msg.LParam, true);
                }
            }
        }


        public static class HWND
        {
            public static readonly IntPtr
            NOTOPMOST = new IntPtr(-2),
            BROADCAST = new IntPtr(0xffff),
            TOPMOST = new IntPtr(-1),
            TOP = new IntPtr(0),
            BOTTOM = new IntPtr(1);
        }


        public static class SWP
        {
            public static readonly int
            NOSIZE = 0x0001,
            NOMOVE = 0x0002,
            NOZORDER = 0x0004,
            NOREDRAW = 0x0008,
            NOACTIVATE = 0x0010,
            DRAWFRAME = 0x0020,
            FRAMECHANGED = 0x0020,
            SHOWWINDOW = 0x0040,
            HIDEWINDOW = 0x0080,
            NOCOPYBITS = 0x0100,
            NOOWNERZORDER = 0x0200,
            NOREPOSITION = 0x0200,
            NOSENDCHANGING = 0x0400,
            DEFERERASE = 0x2000,
            ASYNCWINDOWPOS = 0x4000;
        }


        [DllImport("user32.dll", SetLastError = true)]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpWindowClass, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

        [DllImport("user32.dll")]
        private static extern int ShowWindow(IntPtr hwnd, int command);



        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            IntPtr hprog = FindWindowEx(
                FindWindowEx(
                    FindWindow("Progman", "Program Manager"),
                    IntPtr.Zero, "SHELLDLL_DefView", ""
                ),
                IntPtr.Zero, "SysListView32", "FolderView"
            );

            SetWindowLong(this.Handle, NativeMethods.GWL_HWNDPARENT, hprog);
        }

        protected override void WndProc(ref Message m)
        {
            if (_enableOverride)
            {
                if (m.Msg == NativeMethods.WM_WINDOWPOSCHANGING)
                {

                    // Extract the WINDOWPOS structure corresponding to this message
                    NativeMethods.WINDOWPOS wndPos = NativeMethods.WINDOWPOS.FromMessage(m);


                    wndPos.flags = wndPos.flags | NativeMethods.SetWindowPosFlags.SWP_NOZORDER;
                    wndPos.UpdateMessage(m);

                }
            }

            base.WndProc(ref m);
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            SetWindowPos(Handle, HWND.BOTTOM, 0, 0, 0, 0, SWP.SHOWWINDOW | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOACTIVATE);

            IntPtr task = FindWindow("Shell_TrayWnd", "");
            ShowWindow(task, NativeMethods.SW_SHOW);

            _enableOverride = true;
        }

    }
}

由于您使用的是 WPF - 请试一试。它需要一些 cleanup/formatting 但你明白了:)

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;

namespace WpfApplication1
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.SourceInitialized += MainWindow_SourceInitialized;
            this.WindowStyle = WindowStyle.None;
            this.Loaded += Window_Loaded;
            this.WindowState = WindowState.Maximized;
            InitializeComponent();


            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += dispatcherTimer_Tick;
            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
            dispatcherTimer.Start();

        }


        private bool _enableOverride;
        internal class NativeMethods
        {
            public const int WM_WINDOWPOSCHANGING = 0x46;
            public const int WM_WINDOWPOSCHANGED = 0x47;
            public const int GWL_HWNDPARENT = -8;
            public const int SW_SHOW = 1;


            [Flags]
            public enum SetWindowPosFlags
            {
                SWP_NOSIZE = 0x1,
                SWP_NOMOVE = 0x2,
                SWP_NOZORDER = 0x4,
                SWP_NOREDRAW = 0x8,
                SWP_NOACTIVATE = 0x10,
                SWP_FRAMECHANGED = 0x20,
                SWP_DRAWFRAME = SWP_FRAMECHANGED,
                SWP_SHOWWINDOW = 0x40,
                SWP_HIDEWINDOW = 0x80,
                SWP_NOCOPYBITS = 0x100,
                SWP_NOOWNERZORDER = 0x200,
                SWP_NOREPOSITION = SWP_NOOWNERZORDER,
                SWP_NOSENDCHANGING = 0x400,
                SWP_DEFERERASE = 0x2000,
                SWP_ASYNCWINDOWPOS = 0x4000
            }

            public enum WindowZOrder
            {
                HWND_TOP = 0,
                HWND_BOTTOM = 1,
                HWND_TOPMOST = -1,
                HWND_NOTOPMOST = -2
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct WINDOWPOS
            {
                public IntPtr hWnd;
                public IntPtr hwndInsertAfter;
                public int x;
                public int y;
                public int cx;
                public int cy;
                public SetWindowPosFlags flags;

                // Returns the WINDOWPOS structure pointed to by the lParam parameter
                // of a WM_WINDOWPOSCHANGING or WM_WINDOWPOSCHANGED message.
                public static WINDOWPOS FromMessage(IntPtr lParam)
                {
                    // Marshal the lParam parameter to an WINDOWPOS structure,
                    // and return the new structure
                    return (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
                }

                // Replaces the original WINDOWPOS structure pointed to by the lParam
                // parameter of a WM_WINDOWPOSCHANGING or WM_WINDOWPSCHANGING message
                // with this one, so that the native window will be able to see any
                // changes that we have made to its values.
                public void UpdateMessage(IntPtr lParam)
                {
                    // Marshal this updated structure back to lParam so the native
                    // window can respond to our changes.
                    // The old structure that it points to should be deleted, too.
                    Marshal.StructureToPtr(this, lParam, true);
                }
            }
        }


        public static class HWND
        {
            public static readonly IntPtr
            NOTOPMOST = new IntPtr(-2),
            BROADCAST = new IntPtr(0xffff),
            TOPMOST = new IntPtr(-1),
            TOP = new IntPtr(0),
            BOTTOM = new IntPtr(1);
        }


        public static class SWP
        {
            public static readonly int
            NOSIZE = 0x0001,
            NOMOVE = 0x0002,
            NOZORDER = 0x0004,
            NOREDRAW = 0x0008,
            NOACTIVATE = 0x0010,
            DRAWFRAME = 0x0020,
            FRAMECHANGED = 0x0020,
            SHOWWINDOW = 0x0040,
            HIDEWINDOW = 0x0080,
            NOCOPYBITS = 0x0100,
            NOOWNERZORDER = 0x0200,
            NOREPOSITION = 0x0200,
            NOSENDCHANGING = 0x0400,
            DEFERERASE = 0x2000,
            ASYNCWINDOWPOS = 0x4000;
        }


        [DllImport("user32.dll", SetLastError = true)]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpWindowClass, string lpWindowName);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

        [DllImport("user32.dll")]
        private static extern int ShowWindow(IntPtr hwnd, int command);


        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            //ensure we don't overlap the taskbar.
            SetWindowPos(new WindowInteropHelper(this).Handle, HWND.BOTTOM, 0, 0, 0, 0, SWP.SHOWWINDOW | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOACTIVATE);

            IntPtr task = FindWindow("Shell_TrayWnd", "");
            ShowWindow(task, NativeMethods.SW_SHOW);

            _enableOverride = true;
        }


        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (_enableOverride)
            {
                if (msg == NativeMethods.WM_WINDOWPOSCHANGING)
                {
                    Debug.WriteLine("WM_WINDOWPOSCHANGING");
                    // Extract the WINDOWPOS structure corresponding to this message
                    //lParam has the ptr to a WindowsPos structure if its our WM_WINDOWPOSCHANGING struct
                    NativeMethods.WINDOWPOS wndPos = NativeMethods.WINDOWPOS.FromMessage(lParam);

                    wndPos.flags = wndPos.flags | NativeMethods.SetWindowPosFlags.SWP_NOZORDER;
                    wndPos.UpdateMessage(lParam);
                    //handled = true;
                }
            }

            return IntPtr.Zero;
        }

        private void MainWindow_SourceInitialized(object sender, EventArgs e)
        {
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            IntPtr hWnd = new WindowInteropHelper(this).Handle;

            IntPtr hprog = FindWindowEx(
                           FindWindowEx(
                               FindWindow("Progman", "Program Manager"),
                               IntPtr.Zero, "SHELLDLL_DefView", ""
                           ),
                           IntPtr.Zero, "SysListView32", "FolderView"
                       );

            SetWindowLong(hWnd, NativeMethods.GWL_HWNDPARENT, hprog);
        }
    }
}