Windows 10的虚拟桌面
Windows 10的虚拟桌面
- 简介
- 使用虚拟桌面的快捷键
- IVirtualDesktopManager接口
- Windows Desktop API
- 总结
- 注脚
简介
Windows 10发布后,Windows系统外壳终于内置了虚拟桌面功能。虽然该功能有些跟随Mac多重桌面的嫌疑,但它的确极大方便了桌面组织。
首先,本文将介绍一些使用虚拟桌面的快捷键。然后,讨论使用IVirtualDesktopManager接口,在C#里实现追随虚拟桌面的代码。最后,谈谈Windows 10虚拟桌面和Windows Desktop API的区别。
使用虚拟桌面的快捷键
新建桌面:Ctrl+Win + D
删除桌面:Ctrl+Win + F4
上个桌面:Ctrl+Win + <-
下个桌面:Ctrl+Win + ->
如果记不清快捷键也没关系,可以用Win+Tab还呼出桌面管理视图。或者,用鼠标点击任务栏上的“任务视图”图标:
出现桌面管理视图后,用鼠标新建,删除,切换,以及移动窗口到其他桌面。
IVirtualDesktopManager接口
Windows SDK Support Team博客中,有一篇Chris Lewis1的文章《Virtual Desktop Switching in Windows 10》。它介绍了如何在C#里利用Windows Shell的VirtualDeskTopManager2,以及它的COM接口IVirtualDeskTopManager3来将当前窗口移动到活跃桌面的方法。这里给出简单的c#实现。
首先,在Visual Studio中新建一个WinForm项目,选用DotNet Framework4.0或以上都可以。
然后,在Form1.cs文件中,Form1类的后面,贴入如下COM调用声明:
public partial class Form1 : Form{//...}[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")][System.Security.SuppressUnmanagedCodeSecurity]public interface IVirtualDesktopManager{bool IsWindowOnCurrentVirtualDesktop([In] IntPtr TopLevelWindow);Guid GetWindowDesktopId([In] IntPtr TopLevelWindow);void MoveWindowToDesktop([In] IntPtr TopLevelWindow, ref Guid CurrentDesktop);}[ComImport, Guid("aa509086-5ca9-4c25-8f95-589d3c07b48a")]public class CVirtualDesktopManager{}
接口和COM class的GUID可以在Shobjidl.h头文件中找到。
使用IVirtualDesktopManager接口,我们可以
- 判断是否当前窗口位于活动桌面上,
- 获取某个顶级窗口所在桌面的桌面标志,
- 将某个顶级窗口移动到目标桌面上。
在Form1的构造函数下,我们启用一个定时器。定时器每一秒将检查是否当前窗口位于活动桌面下。
如果用户切换到另外一个虚拟桌面,我们将尝试获取该活动虚拟桌面的标志,并将当前窗口移动到活动桌面下。
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace WindowsFormsApp1
{public partial class Form1 : Form{public Form1(){InitializeComponent();this.timer.Tick += delegate{if (!virtualDesktopManager.IsWindowOnCurrentVirtualDesktop(this.Handle)) // 如果当前窗口不在活动桌面(Active Desktop)下{Guid activeVirtualDesktop;using (var form = new Form() { Size = new Size(50, 50), Location = new Point(-100, -100) }){form.Show(null); // 创建一个‘隐藏窗口’,该窗口将默认显示在活动桌面下。activeVirtualDesktop = virtualDesktopManager.GetWindowDesktopId(form.Handle); // 获取该‘隐藏窗口’的桌面标志this.Text = activeVirtualDesktop.ToString();}if (activeVirtualDesktop != Guid.Empty){virtualDesktopManager.MoveWindowToDesktop(this.Handle, ref activeVirtualDesktop); // 将当前窗口移动到活动桌面下。}}};try{virtualDesktopManager = new CVirtualDesktopManager() as IVirtualDesktopManager;this.timer.Start(); // 如果virtualDesktopManager顺利创建,开始定时器}catch{ }}readonly IVirtualDesktopManager virtualDesktopManager;readonly Timer timer = new Timer() { Interval = 1000 };}[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")][System.Security.SuppressUnmanagedCodeSecurity]public interface IVirtualDesktopManager{bool IsWindowOnCurrentVirtualDesktop([In] IntPtr TopLevelWindow);Guid GetWindowDesktopId([In] IntPtr TopLevelWindow);void MoveWindowToDesktop([In] IntPtr TopLevelWindow, ref Guid CurrentDesktop);}[ComImport, Guid("aa509086-5ca9-4c25-8f95-589d3c07b48a")]public class CVirtualDesktopManager{}
}
编译成功后,运行。用快捷键或“任务视图图标”创建新的虚拟桌面。约一秒内,测试窗口将自动移到当下的虚拟桌面中。
Windows Desktop API
在回答“曹同学”的帖子4《c#的windows服务程序中调用dll(c++编写),在dll中调用了一个exe外部文件》中,我简单地介绍了Windows系统的Session,WindowStation和Desktop的关系。
但是,我的回答中有错误的地方。实际上Windows 10里的快速虚拟桌面,不等于传统Win32 API里的Desktop。Windows 10里的快速虚拟桌面,不是用User32里的CreateDesktop API5实现的。要实现传统意义上的User32 Desktop创建和切换,有兴趣的朋友,可以下载和运行Mark Russinovich的Desktop.exe工具6。
这里我给出了检查当前程序的会话ID,当前WindowStation和当前Win32桌面名字的C#实现:
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;static class Program
{static void Main(){var hWINSTA = GetProcessWindowStation();var stationName = GetUserObjectName(hWINSTA); // WinSta0var hDESK = GetThreadDesktop(GetCurrentThreadId());var desktopName = GetUserObjectName(hDESK); // Defaultvar currentTime = DateTime.Now.ToString("s");var sessionId = Process.GetCurrentProcess().SessionId;var detail = $"[{currentTime}] 会话:{sessionId}, 当前用户:{Environment.UserName}, Station:{stationName}, 桌面:{desktopName}";Console.WriteLine(detail);if (File.Exists(@"c:\temp\log.txt")){File.AppendAllLines(@"c:\temp\log.txt", new[] { detail }); // 写文件里。当该程序在Windows服务中调用时,方便检查。}}static string GetUserObjectName(IntPtr hObject){const int UOI_NAME = 2;var bufferLength = 128;var buffer = new byte[bufferLength];if (!GetUserObjectInformationW(hObject, UOI_NAME, buffer, bufferLength, ref bufferLength)){throw new Win32Exception();}return Encoding.Unicode.GetString(buffer, 0, bufferLength).TrimEnd('\0');}[DllImport("User32", SetLastError = true)]extern static bool GetUserObjectInformationW(IntPtr hObj, int nIndex, byte[] pvInfo, int nLength, ref int lpnLengthNeeded);[DllImport("User32", SetLastError = true)]extern static IntPtr GetProcessWindowStation();[DllImport("User32", SetLastError = true)]extern static IntPtr GetThreadDesktop(int dwThreadId);[DllImport("Kernel32", SetLastError = true)]extern static int GetCurrentThreadId();
}
当该程序在Windows 10的虚拟桌面下运行时,将汇报当前桌面名字为’Default’。
如果用Russinovich的Desktop.exe工具,切换Win32桌面,那么该程序将汇报桌面名字为’SysInternals Desktop 1‘等等。
Win32的Desktop的隔离性比Windows 10的虚拟桌面强。Win32的Desktop界定了Windows消息,菜单,和钩子的范围7。也就是说,SendMessage和PostMessage不能跨越Win32 Desktop。Windows相关的钩子,也只能在当前Win32 Desktop内有效。
我大胆猜测这也是Windows 10的虚拟桌面不采用Win32 Desktop实现的原因。
总结
本文简单介绍了Windows 10的新功能“虚拟桌面”。并解释了它没有采用传统的Win32 Desktop实现。它的实现是基于Windows Shell新增的IVirtualDeskTopManager接口。
注脚
https://blogs.msdn.microsoft.com/winsdk/2015/09/10/virtual-desktop-switching-in-windows-10/ ↩︎
https://docs.microsoft.com/en-us/windows/win32/shell/virtualdesktopmanager ↩︎
https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager ↩︎
https://bbs.csdn.net/topics/395462438 ↩︎
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createdesktopa ↩︎
https://docs.microsoft.com/en-us/sysinternals/downloads/desktops ↩︎
https://docs.microsoft.com/en-us/windows/win32/winstation/desktops ↩︎
Windows 10的虚拟桌面相关推荐
- 怎样取消Windows 10的虚拟桌面切换动画和窗口动画
怎样取消Windows 10的虚拟桌面切换动画和窗口动画 对于晕3D的人来说这是真的要命. 步骤: 在"这台电脑"上点击右键(如bai何在Win10桌面上显示"du这台电 ...
- windows虚拟桌面_在Windows中使用虚拟桌面的最佳免费程序
windows虚拟桌面 If you often open a lot of applications at once, a virtual desktop program can help you ...
- NVIDIA GRID 和 NICE DCV 技术用于实现 Linux 和 Windows® 图形加速虚拟桌面
NVIDIA GRID 和 NICE DCV 技术用于实现 Linux 和 Windows® 图形加速虚拟桌面. NICE DCV: 满足 LINUX 和 WINDOWS 的远程 3D 通过 NICE ...
- 桌面图标设计里的计算机是灰色的,小技巧教您如何将Windows 10上的桌面图标设置中的回收站为灰色!...
如果Windows 10的``桌面图标设置''窗口中的``回收站''选项显示为灰色,则可以查看本逐步指南以解决问题.这将帮助您取回"桌面图标设置"面板中的"回收站&quo ...
- 如何使用python获取Windows 10精美的桌面壁纸
Windows 10界面UI相较于Windows 7做了很多优化,个人最喜欢的就是隔几天自动更新一次的锁屏壁纸.每一张看起来都是大师所做,非常精美.看到打动自已的壁纸,往往想要收藏起来,自定义成桌面壁 ...
- Windows 10打开远程桌面的方法
今天使用windows 10,想要用远程桌面连接,可是怎么都找不到,哎,win10相比于win7和XP系统,感觉还是有点使用不习惯.不过后来还是找到了两个方法,在此记录下来,分享给需要的朋友. 1. ...
- Windows 10 开机进入桌面没有任何图标,闪屏系统自动重启explorer.exe,调不出任务管理器
环境: 电脑:联想台式电脑 操作系统:Windows 10 专业版 64位 问题描述: 开机进入桌面没有图标,闪屏系统自动重启explorer.exe,点击开始没反应,调不出任务管理器,进入安全模式也 ...
- Windows 10 企业版远程桌面连接CredSSP 加密数据库修正问题解决
Win10企业版远程桌面连接报错如下: 解决方案 1.新建文件复制下面内容命名.bat右键使用管理员身份运行 @echo offpushd "%~dp0"dir /b C:\Win ...
- Windows 10修改远程桌面的端口以及防火墙设置
Windows系统自带了远程桌面连接[Win+R 运行,输入mstsc 打开],也非常好用,系统自带远程服务默认端口是[3389],但可能会担心他人恶意连接不安全或遇到端口被占用的问题(如想内网映射到 ...
最新文章
- Windows下curl使用
- 2017云计算及工业物联网论坛即将于广州开幕
- 2021年河北高考成绩位次怎么查询,2021年河北高考一分一段表查询排名方法 成绩排名位次什么时候公布...
- php数据库表怎么删除,php删除数据库表的方法
- boost::filesystem模块实现打印window属性的测试程序
- PHP数组推入弹出的函数:头进头出array_unshift/array_shift 尾进尾出array_push/array_pop
- css固定gridview的表头
- Cmake:linux中cmake添加动态库
- 【BZOJ 1566】 1566: [NOI2009]管道取珠 (DP)
- java中线程的6种状态
- axure实现搜索功能_vue实现模糊搜索功能
- 【转】C++中#include包含头文件带 .h 和不带 .h 的区别
- 大佬!莫言获颁第13个荣誉博士学位
- java地球_java – 应用地球纹理地图的球体
- 转:程序员最值得关注的10个C开源项目
- tapestry mysql_tapestry与mybatis模块的结合
- 初中语文古诗词作者生平归纳
- Debian11 更换软件源
- ROS TF2 中的 四元数 基础部分
- 由FREENOS看去
热门文章
- 辨别亦真亦假的Svchost.exe
- CVPR‘21 | 真·内卷!involution:超越convolution和self-attention的神经网络新算子
- aero peek_如何在Windows中禁用Aero Peek
- 怎么把计算机里隐藏的文件显示,怎么把隐藏的文件夹显示出来 多种方法介绍【图文教程】...
- 2022汽车驾驶员(初级)考试模拟100题及模拟考试
- vTPM环境部署(ubuntu)
- c 当前程序的语言,c语言实现获取macos当前的系统语言
- 文件管理系统FastDFS详解
- 苹果iPad2充不上电的问题
- 联想小新笔记本充不上电——客服提供的处理办法(已解决)