searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

windows虚拟多桌面技术

2023-06-28 10:42:23
30
0

引言

Windows 10 发布后,微软终于在自家的操作系统里面内置了虚拟桌面功能,而这是 macOS 上早已标配的功能。

        这个功能确实有很强的需求,在没有虚拟桌面之前,对于主力设备是 Windows 的我来说,经常要频繁切换浏览器、日历软件、任务管理软件、聊天软件和邮件客户端……的窗口。窗口之间的重合交叠让人感到「邋遢」和不爽。

       可以用windows的SysinternalsSuite工具包里面的Desktops.exe进行虚拟桌面的创建:

                                             

 

 

虚拟桌面能干什么

每个虚拟桌面可以被看成是一个独立的工作空间(Workspace)。

每创建一个虚拟桌面,就像打开了一个新的工作空间。在新的空间中,你能够开启一套完全不同的任务,而不用担心和以前的任务窗口混杂陈列。

创建的每个桌面是相互隔离的,也就是说如果一个程序如果实在无法隐藏程序界面,可以单独创建一个桌面并将程序的界面Switch过去即可,这样就可以“偷偷”在后台工作了。当然我们在做windows本地桌面应用的时候也可以利用多桌面技术,比如可以开辟一个干净的“桌面”进行一些私密的工作(比如玩游戏),之后可以快速的切换回来假装什么都没做 :) 

话不多说,下面是windows多桌面创建的代码:

 

// desktop.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
 
#include <string>
#include <Windows.h>
#include <wininet.h>
#include <shlobj.h>
#include <AclAPI.h>
#include <UserEnv.h>
#include <WtsApi32.h>
#include <Sddl.h>
 
#define VIR_DESKTOP L"VirDesktop"
#define SYSTEM_DEFAULT_DESKTOP L"default"
 
#define I_WALLPAPER_STYTLE_NO_CHANGE -1
#define I_WALLPAPER_STYTLE_CENTER 0 //居中
#define I_WALLPAPER_STYTLE_TILE 1 //平铺
#define I_WALLPAPER_STYTLE_STRETCH 2 //拉伸
 
bool set_desktop_picture(const std::wstring& str_img_path, int i_option, bool b_save)
{
HRESULT hr = S_FALSE;
hr = CoInitialize(NULL);
bool b_inited_ok = false;
if (hr == S_OK)
{
b_inited_ok = true;
}
IActiveDesktop* pIAD = NULL;
hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
if (FAILED(hr))
{
if (b_inited_ok)
CoUninitialize();
return false;
}
 
hr = pIAD->SetWallpaper(str_img_path.c_str(), 0);
 
if (FAILED(hr))
{
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
return false;
}
 
if (i_option > 0)
{
WALLPAPEROPT wp = { 0 };
wp.dwSize = sizeof(WALLPAPEROPT);
wp.dwStyle = i_option;
hr = pIAD->SetWallpaperOptions(&wp, 0);
}
 
if (b_save)
{
hr = pIAD->ApplyChanges(AD_APPLY_ALL);
}
else
{
hr = pIAD->ApplyChanges(AD_APPLY_REFRESH);
}
 
if (FAILED(hr))
{
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
return false;
}
 
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
 
return true;
}
 
bool set_desktop_picture(const std::wstring& str_img_path, std::wstring& str_old_img_path, int& i_old_option, int i_option, bool b_save)
{
i_old_option = I_WALLPAPER_STYTLE_NO_CHANGE;
str_old_img_path.clear();
 
HRESULT hr = S_FALSE;
bool b_inited_ok = false;
hr = CoInitialize(NULL);
if (hr == S_OK)
{
b_inited_ok = true;
}
IActiveDesktop* pIAD = NULL;
hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
if (FAILED(hr))
{
if (b_inited_ok)
CoUninitialize();
return false;
}
 
wchar_t img[4096] = { 0 };
hr = pIAD->GetWallpaper(img, 4096, AD_GETWP_LAST_APPLIED);
if (FAILED(hr))
{
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
return false;
}
str_old_img_path = img;
 
WALLPAPEROPT wp = { 0 };
wp.dwSize = sizeof(WALLPAPEROPT);
hr = pIAD->GetWallpaperOptions(&wp, 0);
 
i_old_option = wp.dwStyle;
hr = pIAD->SetWallpaper(str_img_path.c_str(), 0);
 
if (i_option > 0)
{
WALLPAPEROPT wp = { 0 };
wp.dwSize = sizeof(WALLPAPEROPT);
wp.dwStyle = i_option;
hr = pIAD->SetWallpaperOptions(&wp, 0);
}
if (b_save)
{
hr = pIAD->ApplyChanges(AD_APPLY_ALL);
}
else
{
hr = pIAD->ApplyChanges(AD_APPLY_REFRESH);
}
 
if (FAILED(hr))
{
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
return false;
}
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
 
//set_destop_picture_by_reg(str_img_path);
return true;
}
 
bool get_desktop_picture(std::wstring& str_img_path, int& i_option)
{
i_option = I_WALLPAPER_STYTLE_NO_CHANGE;
str_img_path.clear();
 
HRESULT hr = S_FALSE;
bool b_inited_ok = false;
hr = CoInitialize(NULL);
if (hr == S_OK)
{
b_inited_ok = true;
}
IActiveDesktop* pIAD = NULL;
hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
if (FAILED(hr))
{
if (b_inited_ok)
CoUninitialize();
return false;
}
 
wchar_t img[4096] = { 0 };
hr = pIAD->GetWallpaper(img, 4096, AD_GETWP_LAST_APPLIED);
if (FAILED(hr))
{
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
return false;
}
str_img_path = img;
 
WALLPAPEROPT wp = { 0 };
wp.dwSize = sizeof(WALLPAPEROPT);
hr = pIAD->GetWallpaperOptions(&wp, 0);
 
i_option = wp.dwStyle;
 
pIAD->Release();
if (b_inited_ok)
CoUninitialize();
 
return true;
}
 
bool set_destop_picture_by_reg(const std::wstring& str_img_path, bool b_save)
{
// Change the wallpaper.
UINT ui = SPIF_SENDWININICHANGE;
if (b_save)
{
ui = ui | SPIF_UPDATEINIFILE;
}
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)str_img_path.c_str(), ui);
 
return true;
}
 
// bool  set_desktop_path(const std::wstring& str_path, std::wstring& str_old_path)
// {
// QRegEdit reg;
// str_old_path.clear();
// if (reg.OpenDir(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", true, HKEY_CURRENT_USER, KEY_READ | KEY_WRITE))
// {
// reg.GetStr(L"Desktop", str_old_path);
// return reg.SetStr(L"Desktop", str_path);
// }
// 
// return false;
// }
 
int create_desktop(const std::wstring& _str_desk_name)
{
std::wstring str_desk_name = _str_desk_name;
if (str_desk_name.empty())
{
str_desk_name = SYSTEM_DEFAULT_DESKTOP;
}
SECURITY_ATTRIBUTES attributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
 
if (hdesktop == NULL)
{
hdesktop = CreateDesktopW(str_desk_name.c_str(), NULL, NULL, 0, GENERIC_ALL, &attributes);
if (hdesktop == NULL)
{
return -1;
}
 
BOOL bRet = FALSE;
PSECURITY_DESCRIPTOR SecDes = NULL;
bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("S:(ML;;NW;;;LW)"), SDDL_REVISION_1, &SecDes, NULL);
if (bRet)
{
BOOL bSaclDefaulted = FALSE;
BOOL bSaclPresent = FALSE;
PACL SecACL = NULL;
bRet = GetSecurityDescriptorSacl(SecDes, &bSaclPresent, &SecACL, &bSaclDefaulted);
if (bRet)
{
SetSecurityInfo(hdesktop, SE_WINDOW_OBJECT, 0x10, NULL, NULL, NULL, SecACL);
}
}
}
 
CloseDesktop(hdesktop);
return 0;
}
 
int create_desktop_no_close(HDESK& hdesk_ret, const std::wstring& _str_desk_name)
{
hdesk_ret = NULL;
std::wstring str_desk_name = _str_desk_name;
if (str_desk_name.empty())
{
str_desk_name = SYSTEM_DEFAULT_DESKTOP;
}
SECURITY_ATTRIBUTES attributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
 
if (hdesktop == NULL)
{
hdesktop = CreateDesktopW(str_desk_name.c_str(), NULL, NULL, 0, GENERIC_ALL, &attributes);
if (hdesktop == NULL)
{
return -1;
}
 
BOOL bRet = FALSE;
PSECURITY_DESCRIPTOR SecDes = NULL;
bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("S:(ML;;NW;;;LW)"), SDDL_REVISION_1, &SecDes, NULL);
if (bRet)
{
BOOL bSaclDefaulted = FALSE;
BOOL bSaclPresent = FALSE;
PACL SecACL = NULL;
bRet = GetSecurityDescriptorSacl(SecDes, &bSaclPresent, &SecACL, &bSaclDefaulted);
if (bRet)
{
SetSecurityInfo(hdesktop, SE_WINDOW_OBJECT, 0x10, NULL, NULL, NULL, SecACL);
}
}
}
hdesk_ret = hdesktop;
return 0;
}
 
int change_to_desktop(const std::wstring& _str_desk_name)
{
std::wstring str_desk_name = _str_desk_name;
if (str_desk_name.empty())
{
str_desk_name = SYSTEM_DEFAULT_DESKTOP;
}
 
HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
if (hdesktop == NULL)
{
create_desktop_no_close(hdesktop, str_desk_name);
}
 
if (hdesktop != NULL)
{
if (SwitchDesktop(hdesktop))
{
CloseDesktop(hdesktop);
return 0;
}
else
{
CloseDesktop(hdesktop);
return -2;
}
}
else
{
return -3;
}
 
return -4;
}
 
int change_thread_to_desktop(const std::wstring& _str_desk_name)
{
std::wstring str_desk_name = _str_desk_name;
if (str_desk_name.empty())
{
str_desk_name = SYSTEM_DEFAULT_DESKTOP;
}
 
HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
if (hdesktop == NULL)
{
create_desktop_no_close(hdesktop, str_desk_name);
}
 
if (hdesktop != NULL)
{
if (SetThreadDesktop(hdesktop))
{
CloseDesktop(hdesktop);
return 0;
}
else
{
CloseDesktop(hdesktop);
return -2;
}
}
 
return -3;
}
 
 
int  run_exe(const std::wstring& str_img_path, const std::wstring& _str_desk_name)//str_desk_name为空表示切换到系统默认桌面
{
std::wstring str_desk_name = _str_desk_name;
if (str_desk_name.empty())
{
str_desk_name = SYSTEM_DEFAULT_DESKTOP;
}
 
HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
if (hdesktop == NULL)
{
create_desktop_no_close(hdesktop, str_desk_name);
}
 
if (hdesktop != NULL)
{
PROCESS_INFORMATION pInfo = { 0 };
STARTUPINFO sInfo = { 0 };
wchar_t name[1024] = { 0 };
wcscpy_s(name, 1024, str_desk_name.c_str());
sInfo.cb = sizeof(sInfo);
sInfo.lpDesktop = name;
sInfo.dwFlags = STARTF_USESHOWWINDOW;
sInfo.wShowWindow = SW_SHOW;
 
wchar_t cmd[2048] = { 0 };
wcscpy_s(cmd, 2046, str_img_path.c_str());
 
BOOL bRet = CreateProcess(NULL, cmd, NULL, NULL, TRUE,
NULL, NULL, NULL, &sInfo, &pInfo);//MSDN上面说pszCurDir [in] Not supported; set to NULL,不然的话如果cmd参数传入多个参数,就会进程创建失败
 
CloseDesktop(hdesktop);
if (bRet == FALSE)
{
return -2;
}
return 0;
}
 
return -3;
}
 
 

附录:

虚拟桌面可以把不同类型的程序放在不同的桌面上,为不同任务定制一个工作环境,这样有利于您专注于某种应用场景或任务环境。

设置虚拟桌面

点击任务栏中的任务视图图标。

在任务视图页面中,您可以:

  • 点击“新建桌面”,新建一个虚拟桌面。
  • 点击选择某个虚拟桌面,可切换到选择的虚拟桌面内。
  • 移动到要关闭的虚拟桌面上,此时右上角会有一个打叉的图标,单击即可关闭此虚拟桌面。

虚拟桌面快捷键操作:

  • 打开任务视图页面:同时按下 Win + Tab 键。
  • 新建虚拟桌面:同时按下 Win + Ctrl +D 键。
  • 切换虚拟桌面:同时按下 Win+ Ctrl + 左/右方向键。
  • 关闭虚拟桌面:切换到要关闭的虚拟桌面,同时按下 Win + Ctrl + F4 键。
0条评论
0 / 1000