更换Windows桌面

时间:2016-01-13 21:28:33

标签: c# wpf windows client desktop

对于我正在做的软件项目,我需要更换桌面窗口。

要求:

  • 窗口需要超过桌面图标(不再需要它们)
  • 多个屏幕/显示器
  • 其他窗口可以照常运行
  • 我想保持任务栏的完整性
  • 按下Windows + D或点击桌面按钮时,它应显示我的应用程序。

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

然后有SetWindowPos函数,但我不知道用哪个Z级来实现我想要的。

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

1 个答案:

答案 0 :(得分:1)

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

隐藏任务栏

其次,使用HWND_BOTTOM将窗口设置为最低。 有一些奇怪的行为最适合跨多个操作系统的Setting a Windows form to be bottommost

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

窗口属性 在任务栏中显示= false WindowState =最大化 ControlBox = false 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,请尝试一下。它需要一些清理/格式化,但你明白了这一点:)

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);
        }
    }
}