【问题标题】:Replacing the windows desktop更换windows桌面
【发布时间】:2016-01-13 21:28:32
【问题描述】:

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

要求:

  • 窗口需要位于桌面图标之上(不再需要它们)
  • 多个屏幕/监视器
  • 其他窗口可以照常运行
  • 我想保持任务栏不变
  • 当按下 windows+D 或单击桌面按钮时,它应该会显示我的应用程序。

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

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

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

【问题讨论】:

    标签: c# wpf windows client desktop


    【解决方案1】:

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

    其次,通过使用 HWND_BOTTOM 将窗口设置为最底部。 有一些古怪的行为最好在多个操作系统的Setting a Windows form to be bottommost进行测试


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

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

    使用系统; 使用 System.Collections.Generic; 使用 System.ComponentModel; 使用 System.Data; 使用 System.Diagnostics; 使用 System.Drawing; 使用 System.Linq; 使用 System.Runtime.InteropServices; 使用 System.Text; 使用 System.Threading.Tasks; 使用 System.Windows.Forms; 命名空间桌面替换 { 公共部分类Form1:表格 { 私人布尔_enableOverride; 内部类 NativeMethods { 公共常量 int WM_WINDOWPOSCHANGING = 0x46; 公共常量 int WM_WINDOWPOSCHANGED = 0x47; 公共常量 int GWL_HWNDPARENT = -8; 公共常量 int SW_SHOW = 1; [标志()] 公共枚举 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, } 公共枚举 WindowZOrder { HWND_TOP = 0, HWND_BOTTOM = 1, HWND_TOPMOST = -1, HWND_NOTOPMOST = -2, } [StructLayout(LayoutKind.Sequential)] 公共结构 WINDOWPOS { 公共 IntPtr hWnd; 公共 IntPtr hwndInsertAfter; 公共整数 x; 公共整数 y; 公共 int cx; 公共信息; 公共 SetWindowPosFlags 标志; // 返回lParam参数指向的WINDOWPOS结构 // WM_WINDOWPOSCHANGING 或 WM_WINDOWPOSCHANGED 消息。 公共静态WINDOWPOS FromMessage(消息消息) { // 将 lParam 参数编组到 WINDOWPOS 结构, // 并返回新结构 返回 (WINDOWPOS)Marshal.PtrToStructure(msg.LParam, typeof(WINDOWPOS)); } //替换lParam指向的原始WINDOWPOS结构 // WM_WINDOWPOSCHANGING 或 WM_WINDOWPSCHANGING 消息的参数 // 有了这个,这样本机窗口就可以看到任何 // 我们对其值所做的更改。 公共无效更新消息(消息消息) { // 将此更新后的结构封送回 lParam,以便原生 // 窗口可以响应我们的更改。 // 它指向的旧结构也应该被删除。 Marshal.StructureToPtr(this, msg.LParam, true); } } } 公共静态类 HWND { 公共静态只读 IntPtr NOTOPMOST = 新的 IntPtr(-2), 广播 = 新的 IntPtr(0xffff), TOPMOST = 新的 IntPtr(-1), TOP = 新的 IntPtr(0), 底部 = 新的 IntPtr(1); } 公共静态类 SWP { 公共静态只读 int 噪声 = 0x0001, NOMOVE = 0x0002, NOZORDER = 0x0004, NOREDRAW = 0x0008, 无激活 = 0x0010, 画框 = 0x0020, FRAMECHANGED = 0x0020, 显示窗口 = 0x0040, 隐藏窗口 = 0x0080, NOCOPYBITS = 0x0100, NOOWNERZORDER = 0x0200, NOREPOSITION = 0x0200, NOSENDCHANGING = 0x0400, 延迟 = 0x2000, ASYNCWINDOWPOS = 0x4000; } [DllImport("user32.dll", SetLastError = true)] 静态外部 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); 公共表格1() { 初始化组件(); } 私人无效Form1_Load(对象发送者,EventArgs e) { IntPtr hprog = FindWindowEx( 查找窗口Ex( FindWindow("Progman", "程序管理器"), IntPtr.Zero, "SHELLDLL_DefView", "" ), IntPtr.Zero, "SysListView32", "FolderView" ); SetWindowLong(this.Handle, NativeMethods.GWL_HWNDPARENT, hprog); } 受保护的覆盖无效 WndProc(参考消息 m) { 如果(_enableOverride) { if (m.Msg == NativeMethods.WM_WINDOWPOSCHANGING) { // 提取该消息对应的WINDOWPOS结构 NativeMethods.WINDOWPOS wndPos = NativeMethods.WINDOWPOS.FromMessage(m); wndPos.flags = wndPos.flags | NativeMethods.SetWindowPosFlags.SWP_NOZORDER; wndPos.UpdateMessage(m); } } base.WndProc(参考 m); } private void timer1_Tick(对象发送者,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 = 真; } } }

    既然您使用的是 WPF - 请尝试一下。它需要一些清理/格式化,但你明白了:)

    使用系统; 使用 System.Diagnostics; 使用 System.Runtime.InteropServices; 使用 System.Windows; 使用 System.Windows.Interop; 使用 System.Windows.Threading; 命名空间 WpfApplication1 { /// /// MainWindow.xaml 的交互逻辑 /// 公共部分类 MainWindow : 窗口 { 公共主窗口() { this.SourceInitialized += MainWindow_SourceInitialized; this.WindowStyle = WindowStyle.None; this.Loaded += Window_Loaded; this.WindowState = WindowState.Maximized; 初始化组件(); DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += dispatcherTimer_Tick; dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500); dispatcherTimer.Start(); } 私人布尔_enableOverride; 内部类 NativeMethods { 公共常量 int WM_WINDOWPOSCHANGING = 0x46; 公共常量 int WM_WINDOWPOSCHANGED = 0x47; 公共常量 int GWL_HWNDPARENT = -8; 公共常量 int SW_SHOW = 1; [旗帜] 公共枚举 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 } 公共枚举 WindowZOrder { HWND_TOP = 0, HWND_BOTTOM = 1, HWND_TOPMOST = -1, HWND_NOTOPMOST = -2 } [StructLayout(LayoutKind.Sequential)] 公共结构 WINDOWPOS { 公共 IntPtr hWnd; 公共 IntPtr hwndInsertAfter; 公共整数 x; 公共整数 y; 公共 int cx; 公共信息; 公共 SetWindowPosFlags 标志; // 返回lParam参数指向的WINDOWPOS结构 // WM_WINDOWPOSCHANGING 或 WM_WINDOWPOSCHANGED 消息。 公共静态 WINDOWPOS FromMessage(IntPtr lParam) { // 将 lParam 参数编组到 WINDOWPOS 结构, // 并返回新结构 返回 (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); } //替换lParam指向的原始WINDOWPOS结构 // WM_WINDOWPOSCHANGING 或 WM_WINDOWPSCHANGING 消息的参数 // 有了这个,这样本机窗口就可以看到任何 // 我们对其值所做的更改。 公共无效更新消息(IntPtr lParam) { // 将此更新后的结构封送回 lParam,以便原生 // 窗口可以响应我们的更改。 // 它指向的旧结构也应该被删除。 Marshal.StructureToPtr(this, lParam, true); } } } 公共静态类 HWND { 公共静态只读 IntPtr NOTOPMOST = 新的 IntPtr(-2), 广播 = 新的 IntPtr(0xffff), TOPMOST = 新的 IntPtr(-1), TOP = 新的 IntPtr(0), 底部 = 新的 IntPtr(1); } 公共静态类 SWP { 公共静态只读 int 噪声 = 0x0001, NOMOVE = 0x0002, NOZORDER = 0x0004, NOREDRAW = 0x0008, 无激活 = 0x0010, 画框 = 0x0020, FRAMECHANGED = 0x0020, 显示窗口 = 0x0040, 隐藏窗口 = 0x0080, NOCOPYBITS = 0x0100, NOOWNERZORDER = 0x0200, NOREPOSITION = 0x0200, NOSENDCHANGING = 0x0400, 延迟 = 0x2000, ASYNCWINDOWPOS = 0x4000; } [DllImport("user32.dll", SetLastError = true)] 静态外部 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) { //确保我们不重叠任务栏。 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 = 真; } 私人 IntPtr WndProc(IntPtr hwnd,int msg,IntPtr wParam,IntPtr lParam,ref bool 处理) { 如果(_enableOverride) { if (msg == NativeMethods.WM_WINDOWPOSCHANGING) { Debug.WriteLine("WM_WINDOWPOSCHANGING"); // 提取该消息对应的WINDOWPOS结构 //lParam 有指向 WindowsPos 结构的指针,如果它是我们的 WM_WINDOWPOSCHANGING 结构 NativeMethods.WINDOWPOS wndPos = NativeMethods.WINDOWPOS.FromMessage(lParam); wndPos.flags = wndPos.flags | NativeMethods.SetWindowPosFlags.SWP_NOZORDER; wndPos.UpdateMessage(lParam); //处理=真; } } 返回 IntPtr.Zero; } 私人无效MainWindow_SourceInitialized(对象发送者,EventArgs e) { HwndSource source = PresentationSource.FromVisual(this) as HwndSource; source.AddHook(WndProc); } 私人无效Window_Loaded(对象发送者,RoutedEventArgs e) { IntPtr hWnd = new WindowInteropHelper(this).Handle; IntPtr hprog = FindWindowEx( 查找窗口Ex( FindWindow("Progman", "程序管理器"), IntPtr.Zero, "SHELLDLL_DefView", "" ), IntPtr.Zero, "SysListView32", "FolderView" ); SetWindowLong(hWnd, NativeMethods.GWL_HWNDPARENT, hprog); } } }

    【讨论】:

    • 但我实际上希望任务栏可见..所以我想我会忽略它。
    • 我明天测试一下!
    • 通过电子邮件向我发送您遇到问题的基本复制品,我可以尝试检查一下 - 您在哪里遇到问题?在微软坚持
    • 已发送电子邮件:D,谢谢
    猜你喜欢
    • 2023-03-06
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多